[reflection] MonoError for mono_reflection_call_is_assignable_to
[mono-project.git] / mono / metadata / reflection.c
blobe5c860d5095de966ac0e510d1bf9a5342d9e8398
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 guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
197 #define RESOLVE_TYPE(type, error) do { \
198 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
199 } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
201 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202 __type = mono_reflection_type_resolve_user_types (__type, error); \
203 if (mono_error_ok (error)) \
204 mono_array_set (arr, MonoReflectionType*, index, __type); \
205 } while (0)
207 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
214 #else
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
216 #endif
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
221 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
246 static inline void
247 dynamic_images_lock (void)
249 mono_os_mutex_lock (&dynamic_images_mutex);
252 static inline void
253 dynamic_images_unlock (void)
255 mono_os_mutex_unlock (&dynamic_images_mutex);
259 * mono_find_dynamic_image_owner:
261 * Find the dynamic image, if any, which a given pointer is located in the memory of.
263 MonoImage *
264 mono_find_dynamic_image_owner (void *ptr)
266 MonoImage *owner = NULL;
267 int i;
269 dynamic_images_lock ();
271 if (dynamic_images)
273 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274 MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275 if (mono_mempool_contains_addr (image->mempool, ptr))
276 owner = image;
280 dynamic_images_unlock ();
282 return owner;
285 void
286 mono_reflection_init (void)
288 mono_os_mutex_init (&dynamic_images_mutex);
291 static inline void
292 dynamic_image_lock (MonoDynamicImage *image)
294 MONO_PREPARE_BLOCKING;
295 mono_image_lock ((MonoImage*)image);
296 MONO_FINISH_BLOCKING;
299 static inline void
300 dynamic_image_unlock (MonoDynamicImage *image)
302 mono_image_unlock ((MonoImage*)image);
305 static void
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
308 MONO_REQ_GC_UNSAFE_MODE;
310 dynamic_image_lock (assembly);
311 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312 dynamic_image_unlock (assembly);
315 static MonoObject*
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
318 MONO_REQ_GC_UNSAFE_MODE;
320 MonoObject *obj;
322 dynamic_image_lock (assembly);
323 obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324 dynamic_image_unlock (assembly);
326 return obj;
329 static void
330 sigbuffer_init (SigBuffer *buf, int size)
332 MONO_REQ_GC_NEUTRAL_MODE;
334 buf->buf = (char *)g_malloc (size);
335 buf->p = buf->buf;
336 buf->end = buf->buf + size;
339 static void
340 sigbuffer_make_room (SigBuffer *buf, int size)
342 MONO_REQ_GC_NEUTRAL_MODE;
344 if (buf->end - buf->p < size) {
345 int new_size = buf->end - buf->buf + size + 32;
346 char *p = (char *)g_realloc (buf->buf, new_size);
347 size = buf->p - buf->buf;
348 buf->buf = p;
349 buf->p = p + size;
350 buf->end = buf->buf + new_size;
354 static void
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
357 MONO_REQ_GC_NEUTRAL_MODE;
359 sigbuffer_make_room (buf, 6);
360 mono_metadata_encode_value (val, buf->p, &buf->p);
363 static void
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
366 MONO_REQ_GC_NEUTRAL_MODE;
368 sigbuffer_make_room (buf, 1);
369 buf->p [0] = val;
370 buf->p++;
373 static void
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
376 MONO_REQ_GC_NEUTRAL_MODE;
378 sigbuffer_make_room (buf, size);
379 memcpy (buf->p, p, size);
380 buf->p += size;
383 static void
384 sigbuffer_free (SigBuffer *buf)
386 MONO_REQ_GC_NEUTRAL_MODE;
388 g_free (buf->buf);
391 #ifndef DISABLE_REFLECTION_EMIT
393 * mp_g_alloc:
395 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396 * from the C heap.
398 static gpointer
399 image_g_malloc (MonoImage *image, guint size)
401 MONO_REQ_GC_NEUTRAL_MODE;
403 if (image)
404 return mono_image_alloc (image, size);
405 else
406 return g_malloc (size);
408 #endif /* !DISABLE_REFLECTION_EMIT */
411 * image_g_alloc0:
413 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
414 * from the C heap.
416 static gpointer
417 image_g_malloc0 (MonoImage *image, guint size)
419 MONO_REQ_GC_NEUTRAL_MODE;
421 if (image)
422 return mono_image_alloc0 (image, size);
423 else
424 return g_malloc0 (size);
428 * image_g_free:
429 * @image: a MonoImage
430 * @ptr: pointer
432 * If @image is NULL, free @ptr, otherwise do nothing.
434 static void
435 image_g_free (MonoImage *image, gpointer ptr)
437 if (image == NULL)
438 g_free (ptr);
441 #ifndef DISABLE_REFLECTION_EMIT
442 static char*
443 image_strdup (MonoImage *image, const char *s)
445 MONO_REQ_GC_NEUTRAL_MODE;
447 if (image)
448 return mono_image_strdup (image, s);
449 else
450 return g_strdup (s);
452 #endif
454 #define image_g_new(image,struct_type, n_structs) \
455 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
457 #define image_g_new0(image,struct_type, n_structs) \
458 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
461 static void
462 alloc_table (MonoDynamicTable *table, guint nrows)
464 MONO_REQ_GC_NEUTRAL_MODE;
466 table->rows = nrows;
467 g_assert (table->columns);
468 if (nrows + 1 >= table->alloc_rows) {
469 while (nrows + 1 >= table->alloc_rows) {
470 if (table->alloc_rows == 0)
471 table->alloc_rows = 16;
472 else
473 table->alloc_rows *= 2;
476 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
480 static void
481 make_room_in_stream (MonoDynamicStream *stream, int size)
483 MONO_REQ_GC_NEUTRAL_MODE;
485 if (size <= stream->alloc_size)
486 return;
488 while (stream->alloc_size <= size) {
489 if (stream->alloc_size < 4096)
490 stream->alloc_size = 4096;
491 else
492 stream->alloc_size *= 2;
495 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
498 static guint32
499 string_heap_insert (MonoDynamicStream *sh, const char *str)
501 MONO_REQ_GC_NEUTRAL_MODE;
503 guint32 idx;
504 guint32 len;
505 gpointer oldkey, oldval;
507 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
508 return GPOINTER_TO_UINT (oldval);
510 len = strlen (str) + 1;
511 idx = sh->index;
513 make_room_in_stream (sh, idx + len);
516 * We strdup the string even if we already copy them in sh->data
517 * so that the string pointers in the hash remain valid even if
518 * we need to realloc sh->data. We may want to avoid that later.
520 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
521 memcpy (sh->data + idx, str, len);
522 sh->index += len;
523 return idx;
526 static guint32
527 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
529 MONO_REQ_GC_UNSAFE_MODE;
531 char *name = mono_string_to_utf8 (str);
532 guint32 idx;
533 idx = string_heap_insert (sh, name);
534 g_free (name);
535 return idx;
538 #ifndef DISABLE_REFLECTION_EMIT
539 static void
540 string_heap_init (MonoDynamicStream *sh)
542 MONO_REQ_GC_NEUTRAL_MODE;
544 sh->index = 0;
545 sh->alloc_size = 4096;
546 sh->data = (char *)g_malloc (4096);
547 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
548 string_heap_insert (sh, "");
550 #endif
552 static guint32
553 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
555 MONO_REQ_GC_NEUTRAL_MODE;
557 guint32 idx;
559 make_room_in_stream (stream, stream->index + len);
560 memcpy (stream->data + stream->index, data, len);
561 idx = stream->index;
562 stream->index += len;
564 * align index? Not without adding an additional param that controls it since
565 * we may store a blob value in pieces.
567 return idx;
570 static guint32
571 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
573 MONO_REQ_GC_NEUTRAL_MODE;
575 guint32 idx;
577 make_room_in_stream (stream, stream->index + len);
578 memset (stream->data + stream->index, 0, len);
579 idx = stream->index;
580 stream->index += len;
581 return idx;
584 static void
585 stream_data_align (MonoDynamicStream *stream)
587 MONO_REQ_GC_NEUTRAL_MODE;
589 char buf [4] = {0};
590 guint32 count = stream->index % 4;
592 /* we assume the stream data will be aligned */
593 if (count)
594 mono_image_add_stream_data (stream, buf, 4 - count);
597 #ifndef DISABLE_REFLECTION_EMIT
598 static int
599 mono_blob_entry_hash (const char* str)
601 MONO_REQ_GC_NEUTRAL_MODE;
603 guint len, h;
604 const char *end;
605 len = mono_metadata_decode_blob_size (str, &str);
606 if (len > 0) {
607 end = str + len;
608 h = *str;
609 for (str += 1; str < end; str++)
610 h = (h << 5) - h + *str;
611 return h;
612 } else {
613 return 0;
617 static gboolean
618 mono_blob_entry_equal (const char *str1, const char *str2) {
619 MONO_REQ_GC_NEUTRAL_MODE;
621 int len, len2;
622 const char *end1;
623 const char *end2;
624 len = mono_metadata_decode_blob_size (str1, &end1);
625 len2 = mono_metadata_decode_blob_size (str2, &end2);
626 if (len != len2)
627 return 0;
628 return memcmp (end1, end2, len) == 0;
630 #endif
631 static guint32
632 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
634 MONO_REQ_GC_NEUTRAL_MODE;
636 guint32 idx;
637 char *copy;
638 gpointer oldkey, oldval;
640 copy = (char *)g_malloc (s1+s2);
641 memcpy (copy, b1, s1);
642 memcpy (copy + s1, b2, s2);
643 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
644 g_free (copy);
645 idx = GPOINTER_TO_UINT (oldval);
646 } else {
647 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
648 mono_image_add_stream_data (&assembly->blob, b2, s2);
649 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
651 return idx;
654 static guint32
655 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
657 MONO_REQ_GC_NEUTRAL_MODE;
659 char blob_size [8];
660 char *b = blob_size;
661 guint32 size = buf->p - buf->buf;
662 /* store length */
663 g_assert (size <= (buf->end - buf->buf));
664 mono_metadata_encode_value (size, b, &b);
665 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
669 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
670 * dest may be misaligned.
672 static void
673 swap_with_size (char *dest, const char* val, int len, int nelem) {
674 MONO_REQ_GC_NEUTRAL_MODE;
675 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
676 int elem;
678 for (elem = 0; elem < nelem; ++elem) {
679 switch (len) {
680 case 1:
681 *dest = *val;
682 break;
683 case 2:
684 dest [0] = val [1];
685 dest [1] = val [0];
686 break;
687 case 4:
688 dest [0] = val [3];
689 dest [1] = val [2];
690 dest [2] = val [1];
691 dest [3] = val [0];
692 break;
693 case 8:
694 dest [0] = val [7];
695 dest [1] = val [6];
696 dest [2] = val [5];
697 dest [3] = val [4];
698 dest [4] = val [3];
699 dest [5] = val [2];
700 dest [6] = val [1];
701 dest [7] = val [0];
702 break;
703 default:
704 g_assert_not_reached ();
706 dest += len;
707 val += len;
709 #else
710 memcpy (dest, val, len * nelem);
711 #endif
714 static guint32
715 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
717 MONO_REQ_GC_UNSAFE_MODE;
719 char blob_size [64];
720 char *b = blob_size;
721 guint32 idx = 0, len;
723 len = str->length * 2;
724 mono_metadata_encode_value (len, b, &b);
725 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
727 char *swapped = g_malloc (2 * mono_string_length (str));
728 const char *p = (const char*)mono_string_chars (str);
730 swap_with_size (swapped, p, 2, mono_string_length (str));
731 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
732 g_free (swapped);
734 #else
735 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
736 #endif
737 return idx;
740 #ifndef DISABLE_REFLECTION_EMIT
741 static MonoClass *
742 default_class_from_mono_type (MonoType *type)
744 MONO_REQ_GC_NEUTRAL_MODE;
746 switch (type->type) {
747 case MONO_TYPE_OBJECT:
748 return mono_defaults.object_class;
749 case MONO_TYPE_VOID:
750 return mono_defaults.void_class;
751 case MONO_TYPE_BOOLEAN:
752 return mono_defaults.boolean_class;
753 case MONO_TYPE_CHAR:
754 return mono_defaults.char_class;
755 case MONO_TYPE_I1:
756 return mono_defaults.sbyte_class;
757 case MONO_TYPE_U1:
758 return mono_defaults.byte_class;
759 case MONO_TYPE_I2:
760 return mono_defaults.int16_class;
761 case MONO_TYPE_U2:
762 return mono_defaults.uint16_class;
763 case MONO_TYPE_I4:
764 return mono_defaults.int32_class;
765 case MONO_TYPE_U4:
766 return mono_defaults.uint32_class;
767 case MONO_TYPE_I:
768 return mono_defaults.int_class;
769 case MONO_TYPE_U:
770 return mono_defaults.uint_class;
771 case MONO_TYPE_I8:
772 return mono_defaults.int64_class;
773 case MONO_TYPE_U8:
774 return mono_defaults.uint64_class;
775 case MONO_TYPE_R4:
776 return mono_defaults.single_class;
777 case MONO_TYPE_R8:
778 return mono_defaults.double_class;
779 case MONO_TYPE_STRING:
780 return mono_defaults.string_class;
781 default:
782 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
783 g_assert_not_reached ();
786 return NULL;
788 #endif
791 * mono_class_get_ref_info:
793 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
795 gpointer
796 mono_class_get_ref_info (MonoClass *klass)
798 MONO_REQ_GC_UNSAFE_MODE;
800 if (klass->ref_info_handle == 0)
801 return NULL;
802 else
803 return mono_gchandle_get_target (klass->ref_info_handle);
806 void
807 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
809 MONO_REQ_GC_UNSAFE_MODE;
811 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
812 g_assert (klass->ref_info_handle != 0);
815 void
816 mono_class_free_ref_info (MonoClass *klass)
818 MONO_REQ_GC_NEUTRAL_MODE;
820 if (klass->ref_info_handle) {
821 mono_gchandle_free (klass->ref_info_handle);
822 klass->ref_info_handle = 0;
826 static void
827 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
829 MONO_REQ_GC_NEUTRAL_MODE;
831 int i;
832 MonoGenericInst *class_inst;
833 MonoClass *klass;
835 g_assert (gclass);
837 class_inst = gclass->context.class_inst;
839 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
840 klass = gclass->container_class;
841 sigbuffer_add_value (buf, klass->byval_arg.type);
842 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
844 sigbuffer_add_value (buf, class_inst->type_argc);
845 for (i = 0; i < class_inst->type_argc; ++i)
846 encode_type (assembly, class_inst->type_argv [i], buf);
850 static void
851 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
853 MONO_REQ_GC_NEUTRAL_MODE;
855 if (!type) {
856 g_assert_not_reached ();
857 return;
860 if (type->byref)
861 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
863 switch (type->type){
864 case MONO_TYPE_VOID:
865 case MONO_TYPE_BOOLEAN:
866 case MONO_TYPE_CHAR:
867 case MONO_TYPE_I1:
868 case MONO_TYPE_U1:
869 case MONO_TYPE_I2:
870 case MONO_TYPE_U2:
871 case MONO_TYPE_I4:
872 case MONO_TYPE_U4:
873 case MONO_TYPE_I8:
874 case MONO_TYPE_U8:
875 case MONO_TYPE_R4:
876 case MONO_TYPE_R8:
877 case MONO_TYPE_I:
878 case MONO_TYPE_U:
879 case MONO_TYPE_STRING:
880 case MONO_TYPE_OBJECT:
881 case MONO_TYPE_TYPEDBYREF:
882 sigbuffer_add_value (buf, type->type);
883 break;
884 case MONO_TYPE_PTR:
885 sigbuffer_add_value (buf, type->type);
886 encode_type (assembly, type->data.type, buf);
887 break;
888 case MONO_TYPE_SZARRAY:
889 sigbuffer_add_value (buf, type->type);
890 encode_type (assembly, &type->data.klass->byval_arg, buf);
891 break;
892 case MONO_TYPE_VALUETYPE:
893 case MONO_TYPE_CLASS: {
894 MonoClass *k = mono_class_from_mono_type (type);
896 if (k->generic_container) {
897 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
898 encode_generic_class (assembly, gclass, buf);
899 } else {
901 * Make sure we use the correct type.
903 sigbuffer_add_value (buf, k->byval_arg.type);
905 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
906 * otherwise two typerefs could point to the same type, leading to
907 * verification errors.
909 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
911 break;
913 case MONO_TYPE_ARRAY:
914 sigbuffer_add_value (buf, type->type);
915 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
916 sigbuffer_add_value (buf, type->data.array->rank);
917 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
918 sigbuffer_add_value (buf, 0);
919 break;
920 case MONO_TYPE_GENERICINST:
921 encode_generic_class (assembly, type->data.generic_class, buf);
922 break;
923 case MONO_TYPE_VAR:
924 case MONO_TYPE_MVAR:
925 sigbuffer_add_value (buf, type->type);
926 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
927 break;
928 default:
929 g_error ("need to encode type %x", type->type);
933 static void
934 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
936 MONO_REQ_GC_UNSAFE_MODE;
938 mono_error_init (error);
940 if (!type) {
941 sigbuffer_add_value (buf, MONO_TYPE_VOID);
942 return;
945 MonoType *t = mono_reflection_type_get_handle (type, error);
946 return_if_nok (error);
947 encode_type (assembly, t, buf);
950 static void
951 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
953 MONO_REQ_GC_UNSAFE_MODE;
955 int i;
957 mono_error_init (error);
959 if (modreq) {
960 for (i = 0; i < mono_array_length (modreq); ++i) {
961 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
962 return_if_nok (error);
963 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
964 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
967 if (modopt) {
968 for (i = 0; i < mono_array_length (modopt); ++i) {
969 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
970 return_if_nok (error);
971 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
972 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
977 #ifndef DISABLE_REFLECTION_EMIT
978 static guint32
979 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
981 MONO_REQ_GC_UNSAFE_MODE;
983 SigBuffer buf;
984 int i;
985 guint32 nparams = sig->param_count;
986 guint32 idx;
988 if (!assembly->save)
989 return 0;
991 sigbuffer_init (&buf, 32);
993 * FIXME: vararg, explicit_this, differenc call_conv values...
995 idx = sig->call_convention;
996 if (sig->hasthis)
997 idx |= 0x20; /* hasthis */
998 if (sig->generic_param_count)
999 idx |= 0x10; /* generic */
1000 sigbuffer_add_byte (&buf, idx);
1001 if (sig->generic_param_count)
1002 sigbuffer_add_value (&buf, sig->generic_param_count);
1003 sigbuffer_add_value (&buf, nparams);
1004 encode_type (assembly, sig->ret, &buf);
1005 for (i = 0; i < nparams; ++i) {
1006 if (i == sig->sentinelpos)
1007 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1008 encode_type (assembly, sig->params [i], &buf);
1010 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1011 sigbuffer_free (&buf);
1012 return idx;
1014 #endif
1016 static guint32
1017 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1019 MONO_REQ_GC_UNSAFE_MODE;
1021 mono_error_init (error);
1024 * FIXME: reuse code from method_encode_signature().
1026 SigBuffer buf;
1027 int i;
1028 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1029 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1030 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1031 guint32 idx;
1033 sigbuffer_init (&buf, 32);
1034 /* LAMESPEC: all the call conv spec is foobared */
1035 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1036 if (mb->call_conv & 2)
1037 idx |= 0x5; /* vararg */
1038 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1039 idx |= 0x20; /* hasthis */
1040 if (ngparams)
1041 idx |= 0x10; /* generic */
1042 sigbuffer_add_byte (&buf, idx);
1043 if (ngparams)
1044 sigbuffer_add_value (&buf, ngparams);
1045 sigbuffer_add_value (&buf, nparams + notypes);
1046 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1047 if (!is_ok (error))
1048 goto leave;
1049 encode_reflection_type (assembly, mb->rtype, &buf, error);
1050 if (!is_ok (error))
1051 goto leave;
1052 for (i = 0; i < nparams; ++i) {
1053 MonoArray *modreq = NULL;
1054 MonoArray *modopt = NULL;
1055 MonoReflectionType *pt;
1057 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1058 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1059 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1060 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1061 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1062 if (!is_ok (error))
1063 goto leave;
1064 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1065 encode_reflection_type (assembly, pt, &buf, error);
1066 if (!is_ok (error))
1067 goto leave;
1069 if (notypes)
1070 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1071 for (i = 0; i < notypes; ++i) {
1072 MonoReflectionType *pt;
1074 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1075 encode_reflection_type (assembly, pt, &buf, error);
1076 if (!is_ok (error))
1077 goto leave;
1080 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1081 leave:
1082 sigbuffer_free (&buf);
1083 return idx;
1086 static guint32
1087 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1089 MONO_REQ_GC_UNSAFE_MODE;
1091 mono_error_init (error);
1093 MonoDynamicTable *table;
1094 guint32 *values;
1095 guint32 idx, sig_idx;
1096 guint nl = mono_array_length (ilgen->locals);
1097 SigBuffer buf;
1098 int i;
1100 sigbuffer_init (&buf, 32);
1101 sigbuffer_add_value (&buf, 0x07);
1102 sigbuffer_add_value (&buf, nl);
1103 for (i = 0; i < nl; ++i) {
1104 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1106 if (lb->is_pinned)
1107 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1109 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1110 if (!is_ok (error)) {
1111 sigbuffer_free (&buf);
1112 return 0;
1115 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1116 sigbuffer_free (&buf);
1118 if (assembly->standalonesig_cache == NULL)
1119 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1120 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1121 if (idx)
1122 return idx;
1124 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1125 idx = table->next_idx ++;
1126 table->rows ++;
1127 alloc_table (table, table->rows);
1128 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1130 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1132 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1134 return idx;
1137 static guint32
1138 method_count_clauses (MonoReflectionILGen *ilgen)
1140 MONO_REQ_GC_UNSAFE_MODE;
1142 guint32 num_clauses = 0;
1143 int i;
1145 MonoILExceptionInfo *ex_info;
1146 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1147 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1148 if (ex_info->handlers)
1149 num_clauses += mono_array_length (ex_info->handlers);
1150 else
1151 num_clauses++;
1154 return num_clauses;
1157 #ifndef DISABLE_REFLECTION_EMIT
1158 static MonoExceptionClause*
1159 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1161 MONO_REQ_GC_UNSAFE_MODE;
1163 mono_error_init (error);
1165 MonoExceptionClause *clauses;
1166 MonoExceptionClause *clause;
1167 MonoILExceptionInfo *ex_info;
1168 MonoILExceptionBlock *ex_block;
1169 guint32 finally_start;
1170 int i, j, clause_index;;
1172 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1174 clause_index = 0;
1175 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1176 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1177 finally_start = ex_info->start + ex_info->len;
1178 if (!ex_info->handlers)
1179 continue;
1180 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1181 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1182 clause = &(clauses [clause_index]);
1184 clause->flags = ex_block->type;
1185 clause->try_offset = ex_info->start;
1187 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1188 clause->try_len = finally_start - ex_info->start;
1189 else
1190 clause->try_len = ex_info->len;
1191 clause->handler_offset = ex_block->start;
1192 clause->handler_len = ex_block->len;
1193 if (ex_block->extype) {
1194 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1196 if (!is_ok (error)) {
1197 image_g_free (image, clauses);
1198 return NULL;
1200 clause->data.catch_class = mono_class_from_mono_type (extype);
1201 } else {
1202 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1203 clause->data.filter_offset = ex_block->filter_offset;
1204 else
1205 clause->data.filter_offset = 0;
1207 finally_start = ex_block->start + ex_block->len;
1209 clause_index ++;
1213 return clauses;
1215 #endif /* !DISABLE_REFLECTION_EMIT */
1218 * method_encode_code:
1220 * @assembly the assembly
1221 * @mb the managed MethodBuilder
1222 * @error set on error
1224 * Note that the return value is not sensible if @error is set.
1226 static guint32
1227 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1229 MONO_REQ_GC_UNSAFE_MODE;
1231 char flags = 0;
1232 guint32 idx;
1233 guint32 code_size;
1234 gint32 max_stack, i;
1235 gint32 num_locals = 0;
1236 gint32 num_exception = 0;
1237 gint maybe_small;
1238 guint32 fat_flags;
1239 char fat_header [12];
1240 guint32 int_value;
1241 guint16 short_value;
1242 guint32 local_sig = 0;
1243 guint32 header_size = 12;
1244 MonoArray *code;
1246 mono_error_init (error);
1248 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1249 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1250 return 0;
1252 /*if (mb->name)
1253 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1254 if (mb->ilgen) {
1255 code = mb->ilgen->code;
1256 code_size = mb->ilgen->code_len;
1257 max_stack = mb->ilgen->max_stack;
1258 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1259 if (mb->ilgen->ex_handlers)
1260 num_exception = method_count_clauses (mb->ilgen);
1261 } else {
1262 code = mb->code;
1263 if (code == NULL){
1264 char *name = mono_string_to_utf8 (mb->name);
1265 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1266 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1267 g_free (str);
1268 g_free (name);
1269 return 0;
1272 code_size = mono_array_length (code);
1273 max_stack = 8; /* we probably need to run a verifier on the code... */
1276 stream_data_align (&assembly->code);
1278 /* check for exceptions, maxstack, locals */
1279 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1280 if (maybe_small) {
1281 if (code_size < 64 && !(code_size & 1)) {
1282 flags = (code_size << 2) | 0x2;
1283 } else if (code_size < 32 && (code_size & 1)) {
1284 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1285 } else {
1286 goto fat_header;
1288 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1289 /* add to the fixup todo list */
1290 if (mb->ilgen && mb->ilgen->num_token_fixups)
1291 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1292 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1293 return assembly->text_rva + idx;
1295 fat_header:
1296 if (num_locals) {
1297 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1298 return_val_if_nok (error, 0);
1301 * FIXME: need to set also the header size in fat_flags.
1302 * (and more sects and init locals flags)
1304 fat_flags = 0x03;
1305 if (num_exception)
1306 fat_flags |= METHOD_HEADER_MORE_SECTS;
1307 if (mb->init_locals)
1308 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1309 fat_header [0] = fat_flags;
1310 fat_header [1] = (header_size / 4 ) << 4;
1311 short_value = GUINT16_TO_LE (max_stack);
1312 memcpy (fat_header + 2, &short_value, 2);
1313 int_value = GUINT32_TO_LE (code_size);
1314 memcpy (fat_header + 4, &int_value, 4);
1315 int_value = GUINT32_TO_LE (local_sig);
1316 memcpy (fat_header + 8, &int_value, 4);
1317 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1318 /* add to the fixup todo list */
1319 if (mb->ilgen && mb->ilgen->num_token_fixups)
1320 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1322 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1323 if (num_exception) {
1324 unsigned char sheader [4];
1325 MonoILExceptionInfo * ex_info;
1326 MonoILExceptionBlock * ex_block;
1327 int j;
1329 stream_data_align (&assembly->code);
1330 /* always use fat format for now */
1331 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1332 num_exception *= 6 * sizeof (guint32);
1333 num_exception += 4; /* include the size of the header */
1334 sheader [1] = num_exception & 0xff;
1335 sheader [2] = (num_exception >> 8) & 0xff;
1336 sheader [3] = (num_exception >> 16) & 0xff;
1337 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1338 /* fat header, so we are already aligned */
1339 /* reverse order */
1340 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1341 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1342 if (ex_info->handlers) {
1343 int finally_start = ex_info->start + ex_info->len;
1344 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1345 guint32 val;
1346 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1347 /* the flags */
1348 val = GUINT32_TO_LE (ex_block->type);
1349 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1350 /* try offset */
1351 val = GUINT32_TO_LE (ex_info->start);
1352 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1353 /* need fault, too, probably */
1354 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1355 val = GUINT32_TO_LE (finally_start - ex_info->start);
1356 else
1357 val = GUINT32_TO_LE (ex_info->len);
1358 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1359 /* handler offset */
1360 val = GUINT32_TO_LE (ex_block->start);
1361 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1362 /* handler len */
1363 val = GUINT32_TO_LE (ex_block->len);
1364 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1365 finally_start = ex_block->start + ex_block->len;
1366 if (ex_block->extype) {
1367 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1368 return_val_if_nok (error, 0);
1370 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1371 } else {
1372 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1373 val = ex_block->filter_offset;
1374 else
1375 val = 0;
1377 val = GUINT32_TO_LE (val);
1378 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1379 /*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",
1380 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);*/
1382 } else {
1383 g_error ("No clauses for ex info block %d", i);
1387 return assembly->text_rva + idx;
1390 static guint32
1391 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1393 MONO_REQ_GC_NEUTRAL_MODE;
1395 int i;
1396 MonoDynamicTable *table;
1397 guint32 *values;
1399 table = &assembly->tables [table_idx];
1401 g_assert (col < table->columns);
1403 values = table->values + table->columns;
1404 for (i = 1; i <= table->rows; ++i) {
1405 if (values [col] == token)
1406 return i;
1407 values += table->columns;
1409 return 0;
1413 * LOCKING: Acquires the loader lock.
1415 static MonoCustomAttrInfo*
1416 lookup_custom_attr (MonoImage *image, gpointer member)
1418 MONO_REQ_GC_NEUTRAL_MODE;
1420 MonoCustomAttrInfo* res;
1422 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1424 if (!res)
1425 return NULL;
1427 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1428 res->cached = 0;
1429 return res;
1432 static gboolean
1433 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1435 MONO_REQ_GC_UNSAFE_MODE;
1437 /* FIXME: Need to do more checks */
1438 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1439 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1441 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1442 return FALSE;
1445 return TRUE;
1448 static MonoCustomAttrInfo*
1449 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1451 MONO_REQ_GC_UNSAFE_MODE;
1453 int i, index, count, not_visible;
1454 MonoCustomAttrInfo *ainfo;
1455 MonoReflectionCustomAttr *cattr;
1457 if (!cattrs)
1458 return NULL;
1459 /* FIXME: check in assembly the Run flag is set */
1461 count = mono_array_length (cattrs);
1463 /* Skip nonpublic attributes since MS.NET seems to do the same */
1464 /* FIXME: This needs to be done more globally */
1465 not_visible = 0;
1466 for (i = 0; i < count; ++i) {
1467 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1468 if (!custom_attr_visible (image, cattr))
1469 not_visible ++;
1471 count -= not_visible;
1473 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1475 ainfo->image = image;
1476 ainfo->num_attrs = count;
1477 ainfo->cached = alloc_img != NULL;
1478 index = 0;
1479 for (i = 0; i < count; ++i) {
1480 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1481 if (custom_attr_visible (image, cattr)) {
1482 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1483 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1484 ainfo->attrs [index].ctor = cattr->ctor->method;
1485 ainfo->attrs [index].data = saved;
1486 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1487 index ++;
1491 return ainfo;
1494 #ifndef DISABLE_REFLECTION_EMIT
1496 * LOCKING: Acquires the loader lock.
1498 static void
1499 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1501 MONO_REQ_GC_UNSAFE_MODE;
1503 MonoCustomAttrInfo *ainfo, *tmp;
1505 if (!cattrs || !mono_array_length (cattrs))
1506 return;
1508 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1510 mono_loader_lock ();
1511 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1512 if (tmp)
1513 mono_custom_attrs_free (tmp);
1514 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1515 mono_loader_unlock ();
1518 #endif
1520 void
1521 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1523 MONO_REQ_GC_NEUTRAL_MODE;
1525 if (ainfo && !ainfo->cached)
1526 g_free (ainfo);
1530 * idx is the table index of the object
1531 * type is one of MONO_CUSTOM_ATTR_*
1533 static gboolean
1534 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1536 MONO_REQ_GC_UNSAFE_MODE;
1538 MonoDynamicTable *table;
1539 MonoReflectionCustomAttr *cattr;
1540 guint32 *values;
1541 guint32 count, i, token;
1542 char blob_size [6];
1543 char *p = blob_size;
1545 mono_error_init (error);
1547 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1548 if (!cattrs)
1549 return TRUE;
1550 count = mono_array_length (cattrs);
1551 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1552 table->rows += count;
1553 alloc_table (table, table->rows);
1554 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1555 idx <<= MONO_CUSTOM_ATTR_BITS;
1556 idx |= type;
1557 for (i = 0; i < count; ++i) {
1558 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1559 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1560 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1561 if (!mono_error_ok (error)) goto fail;
1562 type = mono_metadata_token_index (token);
1563 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1564 switch (mono_metadata_token_table (token)) {
1565 case MONO_TABLE_METHOD:
1566 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1568 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1569 * method, not the one returned by mono_image_create_token ().
1571 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1572 break;
1573 case MONO_TABLE_MEMBERREF:
1574 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1575 break;
1576 default:
1577 g_warning ("got wrong token in custom attr");
1578 continue;
1580 values [MONO_CUSTOM_ATTR_TYPE] = type;
1581 p = blob_size;
1582 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1583 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1584 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1585 values += MONO_CUSTOM_ATTR_SIZE;
1586 ++table->next_idx;
1589 return TRUE;
1591 fail:
1592 return FALSE;
1595 static void
1596 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1598 MONO_REQ_GC_UNSAFE_MODE;
1600 MonoDynamicTable *table;
1601 guint32 *values;
1602 guint32 count, i, idx;
1603 MonoReflectionPermissionSet *perm;
1605 if (!permissions)
1606 return;
1608 count = mono_array_length (permissions);
1609 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1610 table->rows += count;
1611 alloc_table (table, table->rows);
1613 for (i = 0; i < mono_array_length (permissions); ++i) {
1614 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1616 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1618 idx = mono_metadata_token_index (parent_token);
1619 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1620 switch (mono_metadata_token_table (parent_token)) {
1621 case MONO_TABLE_TYPEDEF:
1622 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1623 break;
1624 case MONO_TABLE_METHOD:
1625 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1626 break;
1627 case MONO_TABLE_ASSEMBLY:
1628 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1629 break;
1630 default:
1631 g_assert_not_reached ();
1634 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1635 values [MONO_DECL_SECURITY_PARENT] = idx;
1636 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1638 ++table->next_idx;
1643 * Fill in the MethodDef and ParamDef tables for a method.
1644 * This is used for both normal methods and constructors.
1646 static gboolean
1647 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1649 MONO_REQ_GC_UNSAFE_MODE;
1651 MonoDynamicTable *table;
1652 guint32 *values;
1653 guint i, count;
1655 mono_error_init (error);
1657 /* room in this table is already allocated */
1658 table = &assembly->tables [MONO_TABLE_METHOD];
1659 *mb->table_idx = table->next_idx ++;
1660 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1661 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1662 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1663 values [MONO_METHOD_FLAGS] = mb->attrs;
1664 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1665 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1666 return_val_if_nok (error, FALSE);
1667 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1668 return_val_if_nok (error, FALSE);
1670 table = &assembly->tables [MONO_TABLE_PARAM];
1671 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1673 mono_image_add_decl_security (assembly,
1674 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1676 if (mb->pinfo) {
1677 MonoDynamicTable *mtable;
1678 guint32 *mvalues;
1680 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1681 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1683 count = 0;
1684 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1685 if (mono_array_get (mb->pinfo, gpointer, i))
1686 count++;
1688 table->rows += count;
1689 alloc_table (table, table->rows);
1690 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1691 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1692 MonoReflectionParamBuilder *pb;
1693 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1694 values [MONO_PARAM_FLAGS] = pb->attrs;
1695 values [MONO_PARAM_SEQUENCE] = i;
1696 if (pb->name != NULL) {
1697 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1698 } else {
1699 values [MONO_PARAM_NAME] = 0;
1701 values += MONO_PARAM_SIZE;
1702 if (pb->marshal_info) {
1703 mtable->rows++;
1704 alloc_table (mtable, mtable->rows);
1705 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1706 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1707 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1708 return_val_if_nok (error, FALSE);
1710 pb->table_idx = table->next_idx++;
1711 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1712 guint32 field_type = 0;
1713 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1714 mtable->rows ++;
1715 alloc_table (mtable, mtable->rows);
1716 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1717 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1718 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1719 mvalues [MONO_CONSTANT_TYPE] = field_type;
1720 mvalues [MONO_CONSTANT_PADDING] = 0;
1726 return TRUE;
1729 #ifndef DISABLE_REFLECTION_EMIT
1730 static gboolean
1731 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1733 MONO_REQ_GC_UNSAFE_MODE;
1735 mono_error_init (error);
1736 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1738 rmb->ilgen = mb->ilgen;
1739 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1740 return_val_if_nok (error, FALSE);
1741 rmb->parameters = mb->parameters;
1742 rmb->generic_params = mb->generic_params;
1743 rmb->generic_container = mb->generic_container;
1744 rmb->opt_types = NULL;
1745 rmb->pinfo = mb->pinfo;
1746 rmb->attrs = mb->attrs;
1747 rmb->iattrs = mb->iattrs;
1748 rmb->call_conv = mb->call_conv;
1749 rmb->code = mb->code;
1750 rmb->type = mb->type;
1751 rmb->name = mb->name;
1752 rmb->table_idx = &mb->table_idx;
1753 rmb->init_locals = mb->init_locals;
1754 rmb->skip_visibility = FALSE;
1755 rmb->return_modreq = mb->return_modreq;
1756 rmb->return_modopt = mb->return_modopt;
1757 rmb->param_modreq = mb->param_modreq;
1758 rmb->param_modopt = mb->param_modopt;
1759 rmb->permissions = mb->permissions;
1760 rmb->mhandle = mb->mhandle;
1761 rmb->nrefs = 0;
1762 rmb->refs = NULL;
1764 if (mb->dll) {
1765 rmb->charset = mb->charset;
1766 rmb->extra_flags = mb->extra_flags;
1767 rmb->native_cc = mb->native_cc;
1768 rmb->dllentry = mb->dllentry;
1769 rmb->dll = mb->dll;
1772 return TRUE;
1775 static gboolean
1776 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1778 MONO_REQ_GC_UNSAFE_MODE;
1780 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1782 mono_error_init (error);
1784 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1786 rmb->ilgen = mb->ilgen;
1787 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1788 return_val_if_nok (error, FALSE);
1789 rmb->parameters = mb->parameters;
1790 rmb->generic_params = NULL;
1791 rmb->generic_container = NULL;
1792 rmb->opt_types = NULL;
1793 rmb->pinfo = mb->pinfo;
1794 rmb->attrs = mb->attrs;
1795 rmb->iattrs = mb->iattrs;
1796 rmb->call_conv = mb->call_conv;
1797 rmb->code = NULL;
1798 rmb->type = mb->type;
1799 rmb->name = mono_string_new (mono_domain_get (), name);
1800 rmb->table_idx = &mb->table_idx;
1801 rmb->init_locals = mb->init_locals;
1802 rmb->skip_visibility = FALSE;
1803 rmb->return_modreq = NULL;
1804 rmb->return_modopt = NULL;
1805 rmb->param_modreq = mb->param_modreq;
1806 rmb->param_modopt = mb->param_modopt;
1807 rmb->permissions = mb->permissions;
1808 rmb->mhandle = mb->mhandle;
1809 rmb->nrefs = 0;
1810 rmb->refs = NULL;
1812 return TRUE;
1815 static void
1816 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1818 MONO_REQ_GC_UNSAFE_MODE;
1820 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1822 rmb->ilgen = mb->ilgen;
1823 rmb->rtype = mb->rtype;
1824 rmb->parameters = mb->parameters;
1825 rmb->generic_params = NULL;
1826 rmb->generic_container = NULL;
1827 rmb->opt_types = NULL;
1828 rmb->pinfo = NULL;
1829 rmb->attrs = mb->attrs;
1830 rmb->iattrs = 0;
1831 rmb->call_conv = mb->call_conv;
1832 rmb->code = NULL;
1833 rmb->type = (MonoObject *) mb->owner;
1834 rmb->name = mb->name;
1835 rmb->table_idx = NULL;
1836 rmb->init_locals = mb->init_locals;
1837 rmb->skip_visibility = mb->skip_visibility;
1838 rmb->return_modreq = NULL;
1839 rmb->return_modopt = NULL;
1840 rmb->param_modreq = NULL;
1841 rmb->param_modopt = NULL;
1842 rmb->permissions = NULL;
1843 rmb->mhandle = mb->mhandle;
1844 rmb->nrefs = 0;
1845 rmb->refs = NULL;
1847 #endif
1849 static gboolean
1850 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1852 MONO_REQ_GC_UNSAFE_MODE;
1854 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1855 MonoDynamicTable *table;
1856 guint32 *values;
1857 guint32 tok;
1858 MonoReflectionMethod *m;
1859 int i;
1861 mono_error_init (error);
1863 if (!mb->override_methods)
1864 return TRUE;
1866 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1867 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1869 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1870 table->rows ++;
1871 alloc_table (table, table->rows);
1872 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1873 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1874 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1876 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1877 return_val_if_nok (error, FALSE);
1879 switch (mono_metadata_token_table (tok)) {
1880 case MONO_TABLE_MEMBERREF:
1881 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1882 break;
1883 case MONO_TABLE_METHOD:
1884 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1885 break;
1886 default:
1887 g_assert_not_reached ();
1889 values [MONO_METHODIMPL_DECLARATION] = tok;
1892 return TRUE;
1895 #ifndef DISABLE_REFLECTION_EMIT
1896 static gboolean
1897 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1899 MONO_REQ_GC_UNSAFE_MODE;
1901 MonoDynamicTable *table;
1902 guint32 *values;
1903 ReflectionMethodBuilder rmb;
1904 int i;
1906 mono_error_init (error);
1908 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1909 !mono_image_basic_method (&rmb, assembly, error))
1910 return FALSE;
1912 mb->table_idx = *rmb.table_idx;
1914 if (mb->dll) { /* It's a P/Invoke method */
1915 guint32 moduleref;
1916 /* map CharSet values to on-disk values */
1917 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1918 int extra_flags = mb->extra_flags;
1919 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1920 table->rows ++;
1921 alloc_table (table, table->rows);
1922 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1924 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1925 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1926 if (mb->dllentry)
1927 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1928 else
1929 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1930 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1931 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1932 table = &assembly->tables [MONO_TABLE_MODULEREF];
1933 table->rows ++;
1934 alloc_table (table, table->rows);
1935 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1936 values [MONO_IMPLMAP_SCOPE] = table->rows;
1940 if (mb->generic_params) {
1941 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1942 table->rows += mono_array_length (mb->generic_params);
1943 alloc_table (table, table->rows);
1944 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1945 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1947 mono_image_get_generic_param_info (
1948 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1952 return TRUE;
1955 static gboolean
1956 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1958 MONO_REQ_GC_UNSAFE_MODE;
1960 ReflectionMethodBuilder rmb;
1962 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1963 return FALSE;
1965 if (!mono_image_basic_method (&rmb, assembly, error))
1966 return FALSE;
1968 mb->table_idx = *rmb.table_idx;
1970 return TRUE;
1972 #endif
1974 static char*
1975 type_get_fully_qualified_name (MonoType *type)
1977 MONO_REQ_GC_NEUTRAL_MODE;
1979 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1982 static char*
1983 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1985 MONO_REQ_GC_UNSAFE_MODE;
1987 MonoClass *klass;
1988 MonoAssembly *ta;
1990 klass = mono_class_from_mono_type (type);
1991 if (!klass)
1992 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1993 ta = klass->image->assembly;
1994 if (assembly_is_dynamic (ta) || (ta == ass)) {
1995 if (klass->generic_class || klass->generic_container)
1996 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1997 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1998 else
1999 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2002 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2005 #ifndef DISABLE_REFLECTION_EMIT
2006 /*field_image is the image to which the eventual custom mods have been encoded against*/
2007 static guint32
2008 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2010 MONO_REQ_GC_NEUTRAL_MODE;
2012 SigBuffer buf;
2013 guint32 idx, i, token;
2015 if (!assembly->save)
2016 return 0;
2018 sigbuffer_init (&buf, 32);
2020 sigbuffer_add_value (&buf, 0x06);
2021 /* encode custom attributes before the type */
2022 if (type->num_mods) {
2023 for (i = 0; i < type->num_mods; ++i) {
2024 if (field_image) {
2025 MonoError error;
2026 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2027 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2029 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2030 } else {
2031 token = type->modifiers [i].token;
2034 if (type->modifiers [i].required)
2035 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2036 else
2037 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2039 sigbuffer_add_value (&buf, token);
2042 encode_type (assembly, type, &buf);
2043 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2044 sigbuffer_free (&buf);
2045 return idx;
2047 #endif
2049 static guint32
2050 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2052 MONO_REQ_GC_UNSAFE_MODE;
2054 mono_error_init (error);
2056 SigBuffer buf;
2057 guint32 idx;
2058 guint32 typespec = 0;
2059 MonoType *type;
2060 MonoClass *klass;
2062 init_type_builder_generics (fb->type);
2064 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2065 return_val_if_nok (error, 0);
2066 klass = mono_class_from_mono_type (type);
2068 sigbuffer_init (&buf, 32);
2070 sigbuffer_add_value (&buf, 0x06);
2071 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2072 if (!is_ok (error))
2073 goto fail;
2074 /* encode custom attributes before the type */
2076 if (klass->generic_container)
2077 typespec = create_typespec (assembly, type);
2079 if (typespec) {
2080 MonoGenericClass *gclass;
2081 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2082 encode_generic_class (assembly, gclass, &buf);
2083 } else {
2084 encode_type (assembly, type, &buf);
2086 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2087 sigbuffer_free (&buf);
2088 return idx;
2089 fail:
2090 sigbuffer_free (&buf);
2091 return 0;
2094 static guint32
2095 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2097 MONO_REQ_GC_UNSAFE_MODE;
2099 char blob_size [64];
2100 char *b = blob_size;
2101 char *box_val;
2102 char* buf;
2103 guint32 idx = 0, len = 0, dummy = 0;
2105 buf = (char *)g_malloc (64);
2106 if (!val) {
2107 *ret_type = MONO_TYPE_CLASS;
2108 len = 4;
2109 box_val = (char*)&dummy;
2110 } else {
2111 box_val = ((char*)val) + sizeof (MonoObject);
2112 *ret_type = val->vtable->klass->byval_arg.type;
2114 handle_enum:
2115 switch (*ret_type) {
2116 case MONO_TYPE_BOOLEAN:
2117 case MONO_TYPE_U1:
2118 case MONO_TYPE_I1:
2119 len = 1;
2120 break;
2121 case MONO_TYPE_CHAR:
2122 case MONO_TYPE_U2:
2123 case MONO_TYPE_I2:
2124 len = 2;
2125 break;
2126 case MONO_TYPE_U4:
2127 case MONO_TYPE_I4:
2128 case MONO_TYPE_R4:
2129 len = 4;
2130 break;
2131 case MONO_TYPE_U8:
2132 case MONO_TYPE_I8:
2133 len = 8;
2134 break;
2135 case MONO_TYPE_R8:
2136 len = 8;
2137 break;
2138 case MONO_TYPE_VALUETYPE: {
2139 MonoClass *klass = val->vtable->klass;
2141 if (klass->enumtype) {
2142 *ret_type = mono_class_enum_basetype (klass)->type;
2143 goto handle_enum;
2144 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2145 len = 8;
2146 } else
2147 g_error ("we can't encode valuetypes, we should have never reached this line");
2148 break;
2150 case MONO_TYPE_CLASS:
2151 break;
2152 case MONO_TYPE_STRING: {
2153 MonoString *str = (MonoString*)val;
2154 /* there is no signature */
2155 len = str->length * 2;
2156 mono_metadata_encode_value (len, b, &b);
2157 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2159 char *swapped = g_malloc (2 * mono_string_length (str));
2160 const char *p = (const char*)mono_string_chars (str);
2162 swap_with_size (swapped, p, 2, mono_string_length (str));
2163 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2164 g_free (swapped);
2166 #else
2167 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2168 #endif
2170 g_free (buf);
2171 return idx;
2173 case MONO_TYPE_GENERICINST:
2174 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2175 goto handle_enum;
2176 default:
2177 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2180 /* there is no signature */
2181 mono_metadata_encode_value (len, b, &b);
2182 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2183 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2184 swap_with_size (blob_size, box_val, len, 1);
2185 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2186 #else
2187 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2188 #endif
2190 g_free (buf);
2191 return idx;
2194 static guint32
2195 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2197 MONO_REQ_GC_UNSAFE_MODE;
2199 mono_error_init (error);
2201 char *str;
2202 SigBuffer buf;
2203 guint32 idx, len;
2205 sigbuffer_init (&buf, 32);
2207 sigbuffer_add_value (&buf, minfo->type);
2209 switch (minfo->type) {
2210 case MONO_NATIVE_BYVALTSTR:
2211 case MONO_NATIVE_BYVALARRAY:
2212 sigbuffer_add_value (&buf, minfo->count);
2213 break;
2214 case MONO_NATIVE_LPARRAY:
2215 if (minfo->eltype || minfo->has_size) {
2216 sigbuffer_add_value (&buf, minfo->eltype);
2217 if (minfo->has_size) {
2218 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2219 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2221 /* LAMESPEC: ElemMult is undocumented */
2222 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2225 break;
2226 case MONO_NATIVE_SAFEARRAY:
2227 if (minfo->eltype)
2228 sigbuffer_add_value (&buf, minfo->eltype);
2229 break;
2230 case MONO_NATIVE_CUSTOM:
2231 if (minfo->guid) {
2232 str = mono_string_to_utf8 (minfo->guid);
2233 len = strlen (str);
2234 sigbuffer_add_value (&buf, len);
2235 sigbuffer_add_mem (&buf, str, len);
2236 g_free (str);
2237 } else {
2238 sigbuffer_add_value (&buf, 0);
2240 /* native type name */
2241 sigbuffer_add_value (&buf, 0);
2242 /* custom marshaler type name */
2243 if (minfo->marshaltype || minfo->marshaltyperef) {
2244 if (minfo->marshaltyperef) {
2245 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2246 if (!is_ok (error)) {
2247 sigbuffer_free (&buf);
2248 return 0;
2250 str = type_get_fully_qualified_name (marshaltype);
2251 } else
2252 str = mono_string_to_utf8 (minfo->marshaltype);
2253 len = strlen (str);
2254 sigbuffer_add_value (&buf, len);
2255 sigbuffer_add_mem (&buf, str, len);
2256 g_free (str);
2257 } else {
2258 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2259 sigbuffer_add_value (&buf, 0);
2261 if (minfo->mcookie) {
2262 str = mono_string_to_utf8 (minfo->mcookie);
2263 len = strlen (str);
2264 sigbuffer_add_value (&buf, len);
2265 sigbuffer_add_mem (&buf, str, len);
2266 g_free (str);
2267 } else {
2268 sigbuffer_add_value (&buf, 0);
2270 break;
2271 default:
2272 break;
2274 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2275 sigbuffer_free (&buf);
2276 return idx;
2279 static void
2280 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2282 MONO_REQ_GC_UNSAFE_MODE;
2284 mono_error_init (error);
2286 MonoDynamicTable *table;
2287 guint32 *values;
2289 /* maybe this fixup should be done in the C# code */
2290 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2291 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2292 table = &assembly->tables [MONO_TABLE_FIELD];
2293 fb->table_idx = table->next_idx ++;
2294 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2295 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2296 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2297 values [MONO_FIELD_FLAGS] = fb->attrs;
2298 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2299 return_if_nok (error);
2302 if (fb->offset != -1) {
2303 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2304 table->rows ++;
2305 alloc_table (table, table->rows);
2306 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2307 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2308 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2310 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2311 MonoTypeEnum field_type = (MonoTypeEnum)0;
2312 table = &assembly->tables [MONO_TABLE_CONSTANT];
2313 table->rows ++;
2314 alloc_table (table, table->rows);
2315 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2316 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2317 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2318 values [MONO_CONSTANT_TYPE] = field_type;
2319 values [MONO_CONSTANT_PADDING] = 0;
2321 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2322 guint32 rva_idx;
2323 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2324 table->rows ++;
2325 alloc_table (table, table->rows);
2326 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2327 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2329 * We store it in the code section because it's simpler for now.
2331 if (fb->rva_data) {
2332 if (mono_array_length (fb->rva_data) >= 10)
2333 stream_data_align (&assembly->code);
2334 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2335 } else
2336 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2337 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2339 if (fb->marshal_info) {
2340 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2341 table->rows ++;
2342 alloc_table (table, table->rows);
2343 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2344 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2345 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2346 return_if_nok (error);
2350 static guint32
2351 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2353 MONO_REQ_GC_UNSAFE_MODE;
2355 mono_error_init (error);
2357 SigBuffer buf;
2358 guint32 nparams = 0;
2359 MonoReflectionMethodBuilder *mb = fb->get_method;
2360 MonoReflectionMethodBuilder *smb = fb->set_method;
2361 guint32 idx, i;
2363 if (mb && mb->parameters)
2364 nparams = mono_array_length (mb->parameters);
2365 if (!mb && smb && smb->parameters)
2366 nparams = mono_array_length (smb->parameters) - 1;
2367 sigbuffer_init (&buf, 32);
2368 if (fb->call_conv & 0x20)
2369 sigbuffer_add_byte (&buf, 0x28);
2370 else
2371 sigbuffer_add_byte (&buf, 0x08);
2372 sigbuffer_add_value (&buf, nparams);
2373 if (mb) {
2374 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2375 if (!is_ok (error))
2376 goto fail;
2377 for (i = 0; i < nparams; ++i) {
2378 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2379 encode_reflection_type (assembly, pt, &buf, error);
2380 if (!is_ok (error))
2381 goto fail;
2383 } else if (smb && smb->parameters) {
2384 /* the property type is the last param */
2385 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2386 if (!is_ok (error))
2387 goto fail;
2389 for (i = 0; i < nparams; ++i) {
2390 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2391 encode_reflection_type (assembly, pt, &buf, error);
2392 if (!is_ok (error))
2393 goto fail;
2395 } else {
2396 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2397 if (!is_ok (error))
2398 goto fail;
2401 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2402 sigbuffer_free (&buf);
2403 return idx;
2404 fail:
2405 sigbuffer_free (&buf);
2406 return 0;
2409 static void
2410 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2412 MONO_REQ_GC_UNSAFE_MODE;
2414 mono_error_init (error);
2416 MonoDynamicTable *table;
2417 guint32 *values;
2418 guint num_methods = 0;
2419 guint32 semaidx;
2422 * we need to set things in the following tables:
2423 * PROPERTYMAP (info already filled in _get_type_info ())
2424 * PROPERTY (rows already preallocated in _get_type_info ())
2425 * METHOD (method info already done with the generic method code)
2426 * METHODSEMANTICS
2427 * CONSTANT
2429 table = &assembly->tables [MONO_TABLE_PROPERTY];
2430 pb->table_idx = table->next_idx ++;
2431 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2432 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2433 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2434 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2435 return_if_nok (error);
2438 /* FIXME: we still don't handle 'other' methods */
2439 if (pb->get_method) num_methods ++;
2440 if (pb->set_method) num_methods ++;
2442 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2443 table->rows += num_methods;
2444 alloc_table (table, table->rows);
2446 if (pb->get_method) {
2447 semaidx = table->next_idx ++;
2448 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2449 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2450 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2451 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2453 if (pb->set_method) {
2454 semaidx = table->next_idx ++;
2455 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2456 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2457 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2458 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2460 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2461 MonoTypeEnum field_type = (MonoTypeEnum)0;
2462 table = &assembly->tables [MONO_TABLE_CONSTANT];
2463 table->rows ++;
2464 alloc_table (table, table->rows);
2465 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2466 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2467 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2468 values [MONO_CONSTANT_TYPE] = field_type;
2469 values [MONO_CONSTANT_PADDING] = 0;
2473 static void
2474 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2476 MONO_REQ_GC_UNSAFE_MODE;
2478 MonoDynamicTable *table;
2479 guint32 *values;
2480 guint num_methods = 0;
2481 guint32 semaidx;
2484 * we need to set things in the following tables:
2485 * EVENTMAP (info already filled in _get_type_info ())
2486 * EVENT (rows already preallocated in _get_type_info ())
2487 * METHOD (method info already done with the generic method code)
2488 * METHODSEMANTICS
2490 table = &assembly->tables [MONO_TABLE_EVENT];
2491 eb->table_idx = table->next_idx ++;
2492 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2493 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2494 values [MONO_EVENT_FLAGS] = eb->attrs;
2495 MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2496 return_if_nok (error);
2497 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2500 * FIXME: we still don't handle 'other' methods
2502 if (eb->add_method) num_methods ++;
2503 if (eb->remove_method) num_methods ++;
2504 if (eb->raise_method) num_methods ++;
2506 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2507 table->rows += num_methods;
2508 alloc_table (table, table->rows);
2510 if (eb->add_method) {
2511 semaidx = table->next_idx ++;
2512 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2513 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2514 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2515 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2517 if (eb->remove_method) {
2518 semaidx = table->next_idx ++;
2519 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2520 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2521 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2522 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2524 if (eb->raise_method) {
2525 semaidx = table->next_idx ++;
2526 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2527 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2528 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2529 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2533 static void
2534 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2536 MONO_REQ_GC_UNSAFE_MODE;
2538 mono_error_init (error);
2540 MonoDynamicTable *table;
2541 guint32 num_constraints, i;
2542 guint32 *values;
2543 guint32 table_idx;
2545 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2546 num_constraints = gparam->iface_constraints ?
2547 mono_array_length (gparam->iface_constraints) : 0;
2548 table->rows += num_constraints;
2549 if (gparam->base_type)
2550 table->rows++;
2551 alloc_table (table, table->rows);
2553 if (gparam->base_type) {
2554 table_idx = table->next_idx ++;
2555 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2557 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2558 return_if_nok (error);
2559 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2560 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2563 for (i = 0; i < num_constraints; i++) {
2564 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2565 gparam->iface_constraints, gpointer, i);
2567 table_idx = table->next_idx ++;
2568 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2570 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2571 return_if_nok (error);
2573 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2574 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2578 static void
2579 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2581 MONO_REQ_GC_UNSAFE_MODE;
2583 GenericParamTableEntry *entry;
2586 * The GenericParam table must be sorted according to the `owner' field.
2587 * We need to do this sorting prior to writing the GenericParamConstraint
2588 * table, since we have to use the final GenericParam table indices there
2589 * and they must also be sorted.
2592 entry = g_new0 (GenericParamTableEntry, 1);
2593 entry->owner = owner;
2594 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2595 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2596 entry->gparam = gparam;
2598 g_ptr_array_add (assembly->gen_params, entry);
2601 static gboolean
2602 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2604 MONO_REQ_GC_UNSAFE_MODE;
2606 MonoDynamicTable *table;
2607 MonoGenericParam *param;
2608 guint32 *values;
2609 guint32 table_idx;
2611 mono_error_init (error);
2613 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2614 table_idx = table->next_idx ++;
2615 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2617 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2618 return_val_if_nok (error, FALSE);
2620 param = gparam_type->data.generic_param;
2622 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2623 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2624 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2625 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2627 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2628 return FALSE;
2630 encode_constraints (entry->gparam, table_idx, assembly, error);
2631 return_val_if_nok (error, FALSE);
2633 return TRUE;
2636 static guint32
2637 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2639 MONO_REQ_GC_UNSAFE_MODE;
2641 MonoDynamicTable *table;
2642 guint32 token;
2643 guint32 *values;
2644 guint32 cols [MONO_ASSEMBLY_SIZE];
2645 const char *pubkey;
2646 guint32 publen;
2648 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2649 return token;
2651 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2652 table = &assembly->tables [MONO_TABLE_MODULEREF];
2653 token = table->next_idx ++;
2654 table->rows ++;
2655 alloc_table (table, table->rows);
2656 values = table->values + token * MONO_MODULEREF_SIZE;
2657 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2659 token <<= MONO_RESOLUTION_SCOPE_BITS;
2660 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2661 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2663 return token;
2666 if (assembly_is_dynamic (image->assembly))
2667 /* FIXME: */
2668 memset (cols, 0, sizeof (cols));
2669 else {
2670 /* image->assembly->image is the manifest module */
2671 image = image->assembly->image;
2672 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2675 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2676 token = table->next_idx ++;
2677 table->rows ++;
2678 alloc_table (table, table->rows);
2679 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2680 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2681 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2682 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2683 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2684 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2685 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2686 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2687 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2689 if (strcmp ("", image->assembly->aname.culture)) {
2690 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2691 image->assembly->aname.culture);
2694 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2695 guchar pubtoken [9];
2696 pubtoken [0] = 8;
2697 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2698 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2699 } else {
2700 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2702 token <<= MONO_RESOLUTION_SCOPE_BITS;
2703 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2704 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2705 return token;
2708 static guint32
2709 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2711 MONO_REQ_GC_NEUTRAL_MODE;
2713 MonoDynamicTable *table;
2714 guint32 *values;
2715 guint32 token;
2716 SigBuffer buf;
2718 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2719 return token;
2721 sigbuffer_init (&buf, 32);
2722 switch (type->type) {
2723 case MONO_TYPE_FNPTR:
2724 case MONO_TYPE_PTR:
2725 case MONO_TYPE_SZARRAY:
2726 case MONO_TYPE_ARRAY:
2727 case MONO_TYPE_VAR:
2728 case MONO_TYPE_MVAR:
2729 case MONO_TYPE_GENERICINST:
2730 encode_type (assembly, type, &buf);
2731 break;
2732 case MONO_TYPE_CLASS:
2733 case MONO_TYPE_VALUETYPE: {
2734 MonoClass *k = mono_class_from_mono_type (type);
2735 if (!k || !k->generic_container) {
2736 sigbuffer_free (&buf);
2737 return 0;
2739 encode_type (assembly, type, &buf);
2740 break;
2742 default:
2743 sigbuffer_free (&buf);
2744 return 0;
2747 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2748 if (assembly->save) {
2749 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2750 alloc_table (table, table->rows + 1);
2751 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2752 values [MONO_TYPESPEC_SIGNATURE] = token;
2754 sigbuffer_free (&buf);
2756 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2757 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2758 table->next_idx ++;
2759 return token;
2762 static guint32
2763 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2765 MONO_REQ_GC_UNSAFE_MODE;
2767 MonoDynamicTable *table;
2768 guint32 *values;
2769 guint32 token, scope, enclosing;
2770 MonoClass *klass;
2772 /* if the type requires a typespec, we must try that first*/
2773 if (try_typespec && (token = create_typespec (assembly, type)))
2774 return token;
2775 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2776 if (token)
2777 return token;
2778 klass = mono_class_from_mono_type (type);
2779 if (!klass)
2780 klass = mono_class_from_mono_type (type);
2783 * If it's in the same module and not a generic type parameter:
2785 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2786 (type->type != MONO_TYPE_MVAR)) {
2787 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2788 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2789 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2790 return token;
2793 if (klass->nested_in) {
2794 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2795 /* get the typeref idx of the enclosing type */
2796 enclosing >>= MONO_TYPEDEFORREF_BITS;
2797 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2798 } else {
2799 scope = resolution_scope_from_image (assembly, klass->image);
2801 table = &assembly->tables [MONO_TABLE_TYPEREF];
2802 if (assembly->save) {
2803 alloc_table (table, table->rows + 1);
2804 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2805 values [MONO_TYPEREF_SCOPE] = scope;
2806 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2807 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2809 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2810 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2811 table->next_idx ++;
2812 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2813 return token;
2817 * Despite the name, we handle also TypeSpec (with the above helper).
2819 static guint32
2820 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2822 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2825 #ifndef DISABLE_REFLECTION_EMIT
2826 static guint32
2827 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2829 MONO_REQ_GC_NEUTRAL_MODE;
2831 MonoDynamicTable *table;
2832 guint32 *values;
2833 guint32 token, pclass;
2835 switch (parent & MONO_TYPEDEFORREF_MASK) {
2836 case MONO_TYPEDEFORREF_TYPEREF:
2837 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2838 break;
2839 case MONO_TYPEDEFORREF_TYPESPEC:
2840 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2841 break;
2842 case MONO_TYPEDEFORREF_TYPEDEF:
2843 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2844 break;
2845 default:
2846 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2847 return 0;
2849 /* extract the index */
2850 parent >>= MONO_TYPEDEFORREF_BITS;
2852 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2854 if (assembly->save) {
2855 alloc_table (table, table->rows + 1);
2856 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2857 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2858 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2859 values [MONO_MEMBERREF_SIGNATURE] = sig;
2862 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2863 table->next_idx ++;
2865 return token;
2869 * Insert a memberef row into the metadata: the token that point to the memberref
2870 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2871 * mono_image_get_fieldref_token()).
2872 * The sig param is an index to an already built signature.
2874 static guint32
2875 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2877 MONO_REQ_GC_NEUTRAL_MODE;
2879 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2880 return mono_image_add_memberef_row (assembly, parent, name, sig);
2884 static guint32
2885 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2887 MONO_REQ_GC_NEUTRAL_MODE;
2889 guint32 token;
2890 MonoMethodSignature *sig;
2892 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2894 if (create_typespec) {
2895 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2896 if (token)
2897 return token;
2900 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2901 if (token && !create_typespec)
2902 return token;
2904 g_assert (!method->is_inflated);
2905 if (!token) {
2907 * A methodref signature can't contain an unmanaged calling convention.
2909 sig = mono_metadata_signature_dup (mono_method_signature (method));
2910 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2911 sig->call_convention = MONO_CALL_DEFAULT;
2912 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2913 method->name, method_encode_signature (assembly, sig));
2914 g_free (sig);
2915 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2918 if (create_typespec) {
2919 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2920 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2921 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2923 if (assembly->save) {
2924 guint32 *values;
2926 alloc_table (table, table->rows + 1);
2927 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2928 values [MONO_METHODSPEC_METHOD] = token;
2929 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2932 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2933 table->next_idx ++;
2934 /*methodspec and memberef tokens are diferent, */
2935 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2936 return token;
2938 return token;
2941 static guint32
2942 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2944 guint32 token, parent, sig;
2945 ReflectionMethodBuilder rmb;
2946 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2948 mono_error_init (error);
2949 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2950 if (token)
2951 return token;
2953 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2954 return 0;
2957 * A methodref signature can't contain an unmanaged calling convention.
2958 * Since some flags are encoded as part of call_conv, we need to check against it.
2960 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2961 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2963 sig = method_builder_encode_signature (assembly, &rmb, error);
2964 return_val_if_nok (error, 0);
2966 if (tb->generic_params) {
2967 parent = create_generic_typespec (assembly, tb, error);
2968 return_val_if_nok (error, 0);
2969 } else {
2970 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2971 return_val_if_nok (error, 0);
2973 parent = mono_image_typedef_or_ref (assembly, t);
2976 char *name = mono_string_to_utf8 (method->name);
2978 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2979 g_free (name);
2981 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2983 return token;
2986 static guint32
2987 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2988 const gchar *name, guint32 sig)
2990 MonoDynamicTable *table;
2991 guint32 token;
2992 guint32 *values;
2994 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2996 if (assembly->save) {
2997 alloc_table (table, table->rows + 1);
2998 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2999 values [MONO_MEMBERREF_CLASS] = original;
3000 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3001 values [MONO_MEMBERREF_SIGNATURE] = sig;
3004 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3005 table->next_idx ++;
3007 return token;
3010 static guint32
3011 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3013 SigBuffer buf;
3014 int i;
3015 guint32 nparams = mono_array_length (mb->generic_params);
3016 guint32 idx;
3018 if (!assembly->save)
3019 return 0;
3021 sigbuffer_init (&buf, 32);
3023 sigbuffer_add_value (&buf, 0xa);
3024 sigbuffer_add_value (&buf, nparams);
3026 for (i = 0; i < nparams; i++) {
3027 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3028 sigbuffer_add_value (&buf, i);
3031 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3032 sigbuffer_free (&buf);
3033 return idx;
3036 static guint32
3037 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3039 MonoDynamicTable *table;
3040 guint32 *values;
3041 guint32 token, mtoken = 0;
3043 mono_error_init (error);
3044 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3045 if (token)
3046 return token;
3048 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3050 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3051 if (!mono_error_ok (error))
3052 return 0;
3054 switch (mono_metadata_token_table (mtoken)) {
3055 case MONO_TABLE_MEMBERREF:
3056 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3057 break;
3058 case MONO_TABLE_METHOD:
3059 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3060 break;
3061 default:
3062 g_assert_not_reached ();
3065 if (assembly->save) {
3066 alloc_table (table, table->rows + 1);
3067 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3068 values [MONO_METHODSPEC_METHOD] = mtoken;
3069 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3072 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3073 table->next_idx ++;
3075 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3076 return token;
3079 static guint32
3080 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3082 guint32 token;
3084 mono_error_init (error);
3086 if (mb->generic_params && create_methodspec)
3087 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3089 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3090 if (token)
3091 return token;
3093 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3094 if (!mono_error_ok (error))
3095 return 0;
3096 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3097 return token;
3100 static guint32
3101 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3103 guint32 token, parent, sig;
3104 ReflectionMethodBuilder rmb;
3105 char *name;
3106 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3108 mono_error_init (error);
3110 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3111 if (token)
3112 return token;
3114 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3115 return 0;
3117 if (tb->generic_params) {
3118 parent = create_generic_typespec (assembly, tb, error);
3119 return_val_if_nok (error, 0);
3120 } else {
3121 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3122 return_val_if_nok (error, 0);
3123 parent = mono_image_typedef_or_ref (assembly, type);
3126 name = mono_string_to_utf8 (rmb.name);
3127 sig = method_builder_encode_signature (assembly, &rmb, error);
3128 return_val_if_nok (error, 0);
3130 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3132 g_free (name);
3133 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3134 return token;
3136 #endif
3138 static gboolean
3139 is_field_on_inst (MonoClassField *field)
3141 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3145 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3147 static MonoType*
3148 get_field_on_inst_generic_type (MonoClassField *field)
3150 MonoClass *klass, *gtd;
3151 MonoDynamicGenericClass *dgclass;
3152 int field_index;
3154 g_assert (is_field_on_inst (field));
3156 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3158 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3159 field_index = field - dgclass->fields;
3160 return dgclass->field_generic_types [field_index];
3163 klass = field->parent;
3164 gtd = klass->generic_class->container_class;
3166 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3167 field_index = field - klass->fields;
3168 return gtd->fields [field_index].type;
3171 g_assert_not_reached ();
3172 return 0;
3175 #ifndef DISABLE_REFLECTION_EMIT
3176 static guint32
3177 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3179 MonoType *type;
3180 guint32 token;
3182 g_assert (field);
3183 g_assert (field->parent);
3185 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3186 if (token)
3187 return token;
3189 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3190 int index = field - field->parent->fields;
3191 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3192 } else {
3193 if (is_field_on_inst (field))
3194 type = get_field_on_inst_generic_type (field);
3195 else
3196 type = mono_field_get_type (field);
3198 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3199 mono_field_get_name (field),
3200 fieldref_encode_signature (assembly, field->parent->image, type));
3201 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3202 return token;
3205 static guint32
3206 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3208 guint32 token;
3209 MonoClass *klass;
3210 MonoGenericClass *gclass;
3211 MonoType *type;
3212 char *name;
3214 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3215 if (token)
3216 return token;
3217 if (is_sre_field_builder (mono_object_class (f->fb))) {
3218 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3219 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3220 return_val_if_nok (error, 0);
3221 klass = mono_class_from_mono_type (type);
3222 gclass = type->data.generic_class;
3223 g_assert (gclass->is_dynamic);
3225 guint32 sig_token = field_encode_signature (assembly, fb, error);
3226 return_val_if_nok (error, 0);
3227 name = mono_string_to_utf8 (fb->name);
3228 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3229 g_free (name);
3230 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3231 guint32 sig;
3232 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3234 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3235 return_val_if_nok (error, 0);
3236 klass = mono_class_from_mono_type (type);
3238 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3239 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3240 } else {
3241 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3242 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3245 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3246 return token;
3249 static guint32
3250 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3252 guint32 sig, token;
3253 MonoClass *klass;
3254 MonoGenericClass *gclass;
3255 MonoType *type;
3257 mono_error_init (error);
3259 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3261 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3262 if (token)
3263 return token;
3265 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3266 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3267 ReflectionMethodBuilder rmb;
3268 char *name;
3270 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3271 return_val_if_nok (error, 0);
3272 klass = mono_class_from_mono_type (type);
3274 gclass = type->data.generic_class;
3275 g_assert (gclass->is_dynamic);
3277 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3278 return 0;
3280 sig = method_builder_encode_signature (assembly, &rmb, error);
3281 return_val_if_nok (error, 0);
3283 name = mono_string_to_utf8 (rmb.name);
3285 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3286 g_free (name);
3287 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3288 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3290 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3291 return_val_if_nok (error, 0);
3292 klass = mono_class_from_mono_type (type);
3294 sig = method_encode_signature (assembly, mono_method_signature (mm));
3295 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3296 } else {
3297 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3298 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3302 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3303 return token;
3306 static MonoMethod*
3307 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3309 MonoClass *klass;
3310 MonoGenericContext tmp_context;
3311 MonoType **type_argv;
3312 MonoGenericInst *ginst;
3313 MonoMethod *method, *inflated;
3314 int count, i;
3316 mono_error_init (error);
3318 init_type_builder_generics ((MonoObject*)m->inst);
3320 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3321 return_val_if_nok (error, NULL);
3323 klass = method->klass;
3325 if (m->method_args == NULL)
3326 return method;
3328 if (method->is_inflated)
3329 method = ((MonoMethodInflated *) method)->declaring;
3331 count = mono_array_length (m->method_args);
3333 type_argv = g_new0 (MonoType *, count);
3334 for (i = 0; i < count; i++) {
3335 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3336 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3337 return_val_if_nok (error, NULL);
3339 ginst = mono_metadata_get_generic_inst (count, type_argv);
3340 g_free (type_argv);
3342 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3343 tmp_context.method_inst = ginst;
3345 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3346 mono_error_assert_ok (error);
3347 return inflated;
3350 static guint32
3351 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3353 guint32 sig, token = 0;
3354 MonoType *type;
3355 MonoClass *klass;
3357 mono_error_init (error);
3359 if (m->method_args) {
3360 MonoMethod *inflated;
3362 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3363 return_val_if_nok (error, 0);
3365 if (create_methodspec)
3366 token = mono_image_get_methodspec_token (assembly, inflated);
3367 else
3368 token = mono_image_get_inflated_method_token (assembly, inflated);
3369 return token;
3372 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3373 if (token)
3374 return token;
3376 if (is_sre_method_builder (mono_object_class (m->mb))) {
3377 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3378 MonoGenericClass *gclass;
3379 ReflectionMethodBuilder rmb;
3380 char *name;
3382 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3383 return_val_if_nok (error, 0);
3384 klass = mono_class_from_mono_type (type);
3385 gclass = type->data.generic_class;
3386 g_assert (gclass->is_dynamic);
3388 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3389 return 0;
3391 sig = method_builder_encode_signature (assembly, &rmb, error);
3392 return_val_if_nok (error, 0);
3394 name = mono_string_to_utf8 (rmb.name);
3396 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3397 g_free (name);
3398 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3399 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3401 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3402 return_val_if_nok (error, 0);
3403 klass = mono_class_from_mono_type (type);
3405 sig = method_encode_signature (assembly, mono_method_signature (mm));
3406 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3407 } else {
3408 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3409 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3412 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3413 return token;
3416 static guint32
3417 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3419 SigBuffer buf;
3420 int i;
3421 guint32 nparams = context->method_inst->type_argc;
3422 guint32 idx;
3424 if (!assembly->save)
3425 return 0;
3427 sigbuffer_init (&buf, 32);
3429 * FIXME: vararg, explicit_this, differenc call_conv values...
3431 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3432 sigbuffer_add_value (&buf, nparams);
3434 for (i = 0; i < nparams; i++)
3435 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3437 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3438 sigbuffer_free (&buf);
3439 return idx;
3442 static guint32
3443 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3445 MonoDynamicTable *table;
3446 guint32 *values;
3447 guint32 token, mtoken = 0, sig;
3448 MonoMethodInflated *imethod;
3449 MonoMethod *declaring;
3451 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3453 g_assert (method->is_inflated);
3454 imethod = (MonoMethodInflated *) method;
3455 declaring = imethod->declaring;
3457 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3458 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3460 if (!mono_method_signature (declaring)->generic_param_count)
3461 return mtoken;
3463 switch (mono_metadata_token_table (mtoken)) {
3464 case MONO_TABLE_MEMBERREF:
3465 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3466 break;
3467 case MONO_TABLE_METHOD:
3468 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3469 break;
3470 default:
3471 g_assert_not_reached ();
3474 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3476 if (assembly->save) {
3477 alloc_table (table, table->rows + 1);
3478 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3479 values [MONO_METHODSPEC_METHOD] = mtoken;
3480 values [MONO_METHODSPEC_SIGNATURE] = sig;
3483 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3484 table->next_idx ++;
3486 return token;
3489 static guint32
3490 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3492 MonoMethodInflated *imethod;
3493 guint32 token;
3495 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3496 if (token)
3497 return token;
3499 g_assert (method->is_inflated);
3500 imethod = (MonoMethodInflated *) method;
3502 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3503 token = method_encode_methodspec (assembly, method);
3504 } else {
3505 guint32 sig = method_encode_signature (
3506 assembly, mono_method_signature (imethod->declaring));
3507 token = mono_image_get_memberref_token (
3508 assembly, &method->klass->byval_arg, method->name, sig);
3511 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3512 return token;
3515 static guint32
3516 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3518 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3519 guint32 sig, token;
3521 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3522 token = mono_image_get_memberref_token (
3523 assembly, &m->klass->byval_arg, m->name, sig);
3525 return token;
3528 static guint32
3529 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3531 MonoDynamicTable *table;
3532 MonoClass *klass;
3533 MonoType *type;
3534 guint32 *values;
3535 guint32 token;
3536 SigBuffer buf;
3537 int count, i;
3540 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3541 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3542 * Because of this, we must not insert it into the `typeref' hash table.
3544 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3545 return_val_if_nok (error, 0);
3546 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3547 if (token)
3548 return token;
3550 sigbuffer_init (&buf, 32);
3552 g_assert (tb->generic_params);
3553 klass = mono_class_from_mono_type (type);
3555 if (tb->generic_container)
3556 mono_reflection_create_generic_class (tb);
3558 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3559 g_assert (klass->generic_container);
3560 sigbuffer_add_value (&buf, klass->byval_arg.type);
3561 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3563 count = mono_array_length (tb->generic_params);
3564 sigbuffer_add_value (&buf, count);
3565 for (i = 0; i < count; i++) {
3566 MonoReflectionGenericParam *gparam;
3568 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3569 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3570 if (!is_ok (error))
3571 goto fail;
3573 encode_type (assembly, gparam_type, &buf);
3576 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3578 if (assembly->save) {
3579 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3580 alloc_table (table, table->rows + 1);
3581 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3582 values [MONO_TYPESPEC_SIGNATURE] = token;
3584 sigbuffer_free (&buf);
3586 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3587 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3588 table->next_idx ++;
3589 return token;
3590 fail:
3591 sigbuffer_free (&buf);
3592 return 0;
3596 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3598 static MonoType*
3599 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3601 int i, count, len, pos;
3602 MonoType *t;
3604 mono_error_init (error);
3606 count = 0;
3607 if (modreq)
3608 count += mono_array_length (modreq);
3609 if (modopt)
3610 count += mono_array_length (modopt);
3612 if (count == 0)
3613 return mono_metadata_type_dup (NULL, type);
3615 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3616 t = (MonoType *)g_malloc (len);
3617 memcpy (t, type, MONO_SIZEOF_TYPE);
3619 t->num_mods = count;
3620 pos = 0;
3621 if (modreq) {
3622 for (i = 0; i < mono_array_length (modreq); ++i) {
3623 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3624 if (!is_ok (error))
3625 goto fail;
3626 t->modifiers [pos].required = 1;
3627 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3628 pos ++;
3631 if (modopt) {
3632 for (i = 0; i < mono_array_length (modopt); ++i) {
3633 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3634 if (!is_ok (error))
3635 goto fail;
3636 t->modifiers [pos].required = 0;
3637 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3638 pos ++;
3642 return t;
3643 fail:
3644 g_free (t);
3645 return NULL;
3648 static void
3649 init_type_builder_generics (MonoObject *type)
3651 MonoReflectionTypeBuilder *tb;
3653 if (!is_sre_type_builder(mono_object_class (type)))
3654 return;
3655 tb = (MonoReflectionTypeBuilder *)type;
3657 if (tb && tb->generic_container)
3658 mono_reflection_create_generic_class (tb);
3661 static guint32
3662 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3664 MonoDynamicTable *table;
3665 MonoType *custom = NULL, *type;
3666 guint32 *values;
3667 guint32 token, pclass, parent, sig;
3668 gchar *name;
3670 mono_error_init (error);
3672 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3673 if (token)
3674 return token;
3676 MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3677 return_val_if_nok (error, 0);
3678 /* FIXME: is this call necessary? */
3679 mono_class_from_mono_type (typeb);
3681 /*FIXME this is one more layer of ugliness due how types are created.*/
3682 init_type_builder_generics (fb->type);
3684 /* fb->type does not include the custom modifiers */
3685 /* FIXME: We should do this in one place when a fieldbuilder is created */
3686 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3687 return_val_if_nok (error, 0);
3689 if (fb->modreq || fb->modopt) {
3690 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3691 return_val_if_nok (error, 0);
3694 sig = fieldref_encode_signature (assembly, NULL, type);
3695 g_free (custom);
3697 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3698 return_val_if_nok (error, 0);
3699 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3701 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3702 parent >>= MONO_TYPEDEFORREF_BITS;
3704 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3706 name = mono_string_to_utf8 (fb->name);
3708 if (assembly->save) {
3709 alloc_table (table, table->rows + 1);
3710 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3711 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3712 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3713 values [MONO_MEMBERREF_SIGNATURE] = sig;
3716 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3717 table->next_idx ++;
3718 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3719 g_free (name);
3720 return token;
3723 static guint32
3724 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3726 SigBuffer buf;
3727 guint32 nargs;
3728 guint32 i, idx;
3730 mono_error_init (error);
3732 if (!assembly->save)
3733 return 0;
3735 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3736 g_assert (helper->type == 2);
3738 if (helper->arguments)
3739 nargs = mono_array_length (helper->arguments);
3740 else
3741 nargs = 0;
3743 sigbuffer_init (&buf, 32);
3745 /* Encode calling convention */
3746 /* Change Any to Standard */
3747 if ((helper->call_conv & 0x03) == 0x03)
3748 helper->call_conv = 0x01;
3749 /* explicit_this implies has_this */
3750 if (helper->call_conv & 0x40)
3751 helper->call_conv &= 0x20;
3753 if (helper->call_conv == 0) { /* Unmanaged */
3754 idx = helper->unmanaged_call_conv - 1;
3755 } else {
3756 /* Managed */
3757 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3758 if (helper->call_conv & 0x02) /* varargs */
3759 idx += 0x05;
3762 sigbuffer_add_byte (&buf, idx);
3763 sigbuffer_add_value (&buf, nargs);
3764 encode_reflection_type (assembly, helper->return_type, &buf, error);
3765 if (!is_ok (error))
3766 goto fail;
3767 for (i = 0; i < nargs; ++i) {
3768 MonoArray *modreqs = NULL;
3769 MonoArray *modopts = NULL;
3770 MonoReflectionType *pt;
3772 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3773 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3774 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3775 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3777 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3778 if (!is_ok (error))
3779 goto fail;
3780 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3781 encode_reflection_type (assembly, pt, &buf, error);
3782 if (!is_ok (error))
3783 goto fail;
3785 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3786 sigbuffer_free (&buf);
3788 return idx;
3789 fail:
3790 sigbuffer_free (&buf);
3791 return 0;
3794 static guint32
3795 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3797 guint32 idx;
3798 MonoDynamicTable *table;
3799 guint32 *values;
3801 mono_error_init (error);
3803 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3804 idx = table->next_idx ++;
3805 table->rows ++;
3806 alloc_table (table, table->rows);
3807 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3809 values [MONO_STAND_ALONE_SIGNATURE] =
3810 mono_reflection_encode_sighelper (assembly, helper, error);
3811 return_val_if_nok (error, 0);
3813 return idx;
3816 static int
3817 reflection_cc_to_file (int call_conv) {
3818 switch (call_conv & 0x3) {
3819 case 0:
3820 case 1: return MONO_CALL_DEFAULT;
3821 case 2: return MONO_CALL_VARARG;
3822 default:
3823 g_assert_not_reached ();
3825 return 0;
3827 #endif /* !DISABLE_REFLECTION_EMIT */
3829 typedef struct {
3830 MonoType *parent;
3831 MonoMethodSignature *sig;
3832 char *name;
3833 guint32 token;
3834 } ArrayMethod;
3836 #ifndef DISABLE_REFLECTION_EMIT
3837 static guint32
3838 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3840 guint32 nparams, i;
3841 GList *tmp;
3842 char *name = NULL;
3843 MonoMethodSignature *sig;
3844 ArrayMethod *am = NULL;
3845 MonoType *mtype;
3847 mono_error_init (error);
3849 nparams = mono_array_length (m->parameters);
3850 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3851 sig->hasthis = 1;
3852 sig->sentinelpos = -1;
3853 sig->call_convention = reflection_cc_to_file (m->call_conv);
3854 sig->param_count = nparams;
3855 if (m->ret) {
3856 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3857 if (!is_ok (error))
3858 goto fail;
3859 } else
3860 sig->ret = &mono_defaults.void_class->byval_arg;
3862 mtype = mono_reflection_type_get_handle (m->parent, error);
3863 if (!is_ok (error))
3864 goto fail;
3866 for (i = 0; i < nparams; ++i) {
3867 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3868 if (!is_ok (error))
3869 goto fail;
3872 name = mono_string_to_utf8 (m->name);
3873 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3874 am = (ArrayMethod *)tmp->data;
3875 if (strcmp (name, am->name) == 0 &&
3876 mono_metadata_type_equal (am->parent, mtype) &&
3877 mono_metadata_signature_equal (am->sig, sig)) {
3878 g_free (name);
3879 g_free (sig);
3880 m->table_idx = am->token & 0xffffff;
3881 return am->token;
3884 am = g_new0 (ArrayMethod, 1);
3885 am->name = name;
3886 am->sig = sig;
3887 am->parent = mtype;
3888 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3889 method_encode_signature (assembly, sig));
3890 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3891 m->table_idx = am->token & 0xffffff;
3892 return am->token;
3893 fail:
3894 g_free (am);
3895 g_free (name);
3896 g_free (sig);
3897 return 0;
3902 * Insert into the metadata tables all the info about the TypeBuilder tb.
3903 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3905 static gboolean
3906 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3908 MonoDynamicTable *table;
3909 guint *values;
3910 int i, is_object = 0, is_system = 0;
3911 char *n;
3913 mono_error_init (error);
3915 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3916 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3917 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3918 n = mono_string_to_utf8 (tb->name);
3919 if (strcmp (n, "Object") == 0)
3920 is_object++;
3921 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3922 g_free (n);
3923 n = mono_string_to_utf8 (tb->nspace);
3924 if (strcmp (n, "System") == 0)
3925 is_system++;
3926 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3927 g_free (n);
3928 if (tb->parent && !(is_system && is_object) &&
3929 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3930 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3931 return_val_if_nok (error, FALSE);
3932 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3933 } else {
3934 values [MONO_TYPEDEF_EXTENDS] = 0;
3936 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3937 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3940 * if we have explicitlayout or sequentiallayouts, output data in the
3941 * ClassLayout table.
3943 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3944 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3945 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3946 table->rows++;
3947 alloc_table (table, table->rows);
3948 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3949 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3950 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3951 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3954 /* handle interfaces */
3955 if (tb->interfaces) {
3956 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3957 i = table->rows;
3958 table->rows += mono_array_length (tb->interfaces);
3959 alloc_table (table, table->rows);
3960 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3961 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3962 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3963 MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3964 return_val_if_nok (error, FALSE);
3965 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3966 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3967 values += MONO_INTERFACEIMPL_SIZE;
3971 /* handle fields */
3972 if (tb->fields) {
3973 table = &assembly->tables [MONO_TABLE_FIELD];
3974 table->rows += tb->num_fields;
3975 alloc_table (table, table->rows);
3976 for (i = 0; i < tb->num_fields; ++i) {
3977 mono_image_get_field_info (
3978 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3979 return_val_if_nok (error, FALSE);
3983 /* handle constructors */
3984 if (tb->ctors) {
3985 table = &assembly->tables [MONO_TABLE_METHOD];
3986 table->rows += mono_array_length (tb->ctors);
3987 alloc_table (table, table->rows);
3988 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3989 if (!mono_image_get_ctor_info (domain,
3990 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3991 assembly, error))
3992 return FALSE;
3996 /* handle methods */
3997 if (tb->methods) {
3998 table = &assembly->tables [MONO_TABLE_METHOD];
3999 table->rows += tb->num_methods;
4000 alloc_table (table, table->rows);
4001 for (i = 0; i < tb->num_methods; ++i) {
4002 if (!mono_image_get_method_info (
4003 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4004 return FALSE;
4008 /* Do the same with properties etc.. */
4009 if (tb->events && mono_array_length (tb->events)) {
4010 table = &assembly->tables [MONO_TABLE_EVENT];
4011 table->rows += mono_array_length (tb->events);
4012 alloc_table (table, table->rows);
4013 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4014 table->rows ++;
4015 alloc_table (table, table->rows);
4016 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4017 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4018 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4019 for (i = 0; i < mono_array_length (tb->events); ++i) {
4020 mono_image_get_event_info (
4021 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4022 return_val_if_nok (error, FALSE);
4025 if (tb->properties && mono_array_length (tb->properties)) {
4026 table = &assembly->tables [MONO_TABLE_PROPERTY];
4027 table->rows += mono_array_length (tb->properties);
4028 alloc_table (table, table->rows);
4029 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4030 table->rows ++;
4031 alloc_table (table, table->rows);
4032 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4033 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4034 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4035 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4036 mono_image_get_property_info (
4037 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4038 return_val_if_nok (error, FALSE);
4042 /* handle generic parameters */
4043 if (tb->generic_params) {
4044 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4045 table->rows += mono_array_length (tb->generic_params);
4046 alloc_table (table, table->rows);
4047 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4048 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4050 mono_image_get_generic_param_info (
4051 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4055 mono_image_add_decl_security (assembly,
4056 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4058 if (tb->subtypes) {
4059 MonoDynamicTable *ntable;
4061 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4062 ntable->rows += mono_array_length (tb->subtypes);
4063 alloc_table (ntable, ntable->rows);
4064 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4066 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4067 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4069 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4070 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4071 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4072 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4073 mono_string_to_utf8 (tb->name), tb->table_idx,
4074 ntable->next_idx, ntable->rows);*/
4075 values += MONO_NESTED_CLASS_SIZE;
4076 ntable->next_idx++;
4080 return TRUE;
4082 #endif
4084 static void
4085 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4087 int i;
4089 mono_ptr_array_append (*types, type);
4091 if (!type->subtypes)
4092 return;
4094 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4095 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4096 collect_types (types, subtype);
4100 static gint
4101 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4103 if ((*type1)->table_idx < (*type2)->table_idx)
4104 return -1;
4105 else
4106 if ((*type1)->table_idx > (*type2)->table_idx)
4107 return 1;
4108 else
4109 return 0;
4112 static gboolean
4113 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4114 int i;
4116 mono_error_init (error);
4117 if (!pinfo)
4118 return TRUE;
4119 for (i = 0; i < mono_array_length (pinfo); ++i) {
4120 MonoReflectionParamBuilder *pb;
4121 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4122 if (!pb)
4123 continue;
4124 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4125 return FALSE;
4128 return TRUE;
4131 static gboolean
4132 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4133 int i;
4135 mono_error_init (error);
4137 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4138 return FALSE;
4139 if (tb->fields) {
4140 for (i = 0; i < tb->num_fields; ++i) {
4141 MonoReflectionFieldBuilder* fb;
4142 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4143 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4144 return FALSE;
4147 if (tb->events) {
4148 for (i = 0; i < mono_array_length (tb->events); ++i) {
4149 MonoReflectionEventBuilder* eb;
4150 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4151 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4152 return FALSE;
4155 if (tb->properties) {
4156 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4157 MonoReflectionPropertyBuilder* pb;
4158 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4159 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4160 return FALSE;
4163 if (tb->ctors) {
4164 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4165 MonoReflectionCtorBuilder* cb;
4166 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4167 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4168 !params_add_cattrs (assembly, cb->pinfo, error))
4169 return FALSE;
4173 if (tb->methods) {
4174 for (i = 0; i < tb->num_methods; ++i) {
4175 MonoReflectionMethodBuilder* mb;
4176 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4177 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4178 !params_add_cattrs (assembly, mb->pinfo, error))
4179 return FALSE;
4183 if (tb->subtypes) {
4184 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4185 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4186 return FALSE;
4190 return TRUE;
4193 static gboolean
4194 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4196 int i;
4198 mono_error_init (error);
4200 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4201 return FALSE;
4203 if (moduleb->global_methods) {
4204 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4205 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4206 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4207 !params_add_cattrs (assembly, mb->pinfo, error))
4208 return FALSE;
4212 if (moduleb->global_fields) {
4213 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4214 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4215 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4216 return FALSE;
4220 if (moduleb->types) {
4221 for (i = 0; i < moduleb->num_types; ++i) {
4222 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4223 return FALSE;
4227 return TRUE;
4230 static void
4231 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4233 MonoDynamicTable *table;
4234 guint32 *values;
4235 char blob_size [6];
4236 guchar hash [20];
4237 char *b = blob_size;
4238 char *dir, *path;
4240 table = &assembly->tables [MONO_TABLE_FILE];
4241 table->rows++;
4242 alloc_table (table, table->rows);
4243 values = table->values + table->next_idx * MONO_FILE_SIZE;
4244 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4245 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4246 if (image_is_dynamic (module->image)) {
4247 /* This depends on the fact that the main module is emitted last */
4248 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4249 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4250 } else {
4251 dir = NULL;
4252 path = g_strdup (module->image->name);
4254 mono_sha1_get_digest_from_file (path, hash);
4255 g_free (dir);
4256 g_free (path);
4257 mono_metadata_encode_value (20, b, &b);
4258 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4259 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4260 table->next_idx ++;
4263 static void
4264 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4266 MonoDynamicTable *table;
4267 int i;
4269 table = &assembly->tables [MONO_TABLE_MODULE];
4270 mb->table_idx = table->next_idx ++;
4271 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4272 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4273 i /= 16;
4274 ++i;
4275 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4276 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4277 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4278 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4281 static guint32
4282 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4283 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4285 MonoDynamicTable *table;
4286 guint32 *values;
4287 guint32 visib, res;
4289 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4290 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4291 return 0;
4293 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4294 table->rows++;
4295 alloc_table (table, table->rows);
4296 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4298 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4299 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4300 if (klass->nested_in)
4301 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4302 else
4303 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4304 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4305 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4307 res = table->next_idx;
4309 table->next_idx ++;
4311 /* Emit nested types */
4312 if (klass->ext && klass->ext->nested_classes) {
4313 GList *tmp;
4315 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4316 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4319 return res;
4322 static void
4323 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4324 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4325 MonoError *error)
4327 MonoClass *klass;
4328 guint32 idx, i;
4330 mono_error_init (error);
4332 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4333 return_if_nok (error);
4335 klass = mono_class_from_mono_type (t);
4337 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4339 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4340 parent_index, assembly);
4343 * Emit nested types
4344 * We need to do this ourselves since klass->nested_classes is not set up.
4346 if (tb->subtypes) {
4347 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4348 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4349 return_if_nok (error);
4354 static void
4355 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4356 guint32 module_index, MonoDynamicImage *assembly)
4358 MonoImage *image = module->image;
4359 MonoTableInfo *t;
4360 guint32 i;
4362 t = &image->tables [MONO_TABLE_TYPEDEF];
4364 for (i = 0; i < t->rows; ++i) {
4365 MonoError error;
4366 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4367 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4369 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4370 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4374 static void
4375 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4377 MonoDynamicTable *table;
4378 guint32 *values;
4379 guint32 scope, scope_idx, impl, current_idx;
4380 gboolean forwarder = TRUE;
4381 gpointer iter = NULL;
4382 MonoClass *nested;
4384 if (klass->nested_in) {
4385 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4386 forwarder = FALSE;
4387 } else {
4388 scope = resolution_scope_from_image (assembly, klass->image);
4389 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4390 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4391 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4394 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4396 table->rows++;
4397 alloc_table (table, table->rows);
4398 current_idx = table->next_idx;
4399 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4401 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4402 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4403 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4404 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4405 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4407 table->next_idx++;
4409 while ((nested = mono_class_get_nested_types (klass, &iter)))
4410 add_exported_type (assemblyb, assembly, nested, current_idx);
4413 static void
4414 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4416 MonoError error;
4417 MonoClass *klass;
4418 int i;
4420 if (!assemblyb->type_forwarders)
4421 return;
4423 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4424 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4425 MonoType *type;
4426 if (!t)
4427 continue;
4429 type = mono_reflection_type_get_handle (t, &error);
4430 mono_error_assert_ok (&error);
4431 g_assert (type);
4433 klass = mono_class_from_mono_type (type);
4435 add_exported_type (assemblyb, assembly, klass, 0);
4439 #define align_pointer(base,p)\
4440 do {\
4441 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4442 if (__diff & 3)\
4443 (p) += 4 - (__diff & 3);\
4444 } while (0)
4446 static int
4447 compare_constants (const void *a, const void *b)
4449 const guint32 *a_values = (const guint32 *)a;
4450 const guint32 *b_values = (const guint32 *)b;
4451 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4454 static int
4455 compare_semantics (const void *a, const void *b)
4457 const guint32 *a_values = (const guint32 *)a;
4458 const guint32 *b_values = (const guint32 *)b;
4459 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4460 if (assoc)
4461 return assoc;
4462 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4465 static int
4466 compare_custom_attrs (const void *a, const void *b)
4468 const guint32 *a_values = (const guint32 *)a;
4469 const guint32 *b_values = (const guint32 *)b;
4471 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4474 static int
4475 compare_field_marshal (const void *a, const void *b)
4477 const guint32 *a_values = (const guint32 *)a;
4478 const guint32 *b_values = (const guint32 *)b;
4480 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4483 static int
4484 compare_nested (const void *a, const void *b)
4486 const guint32 *a_values = (const guint32 *)a;
4487 const guint32 *b_values = (const guint32 *)b;
4489 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4492 static int
4493 compare_genericparam (const void *a, const void *b)
4495 MonoError error;
4496 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4497 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4499 if ((*b_entry)->owner == (*a_entry)->owner) {
4500 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4501 mono_error_assert_ok (&error);
4502 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4503 mono_error_assert_ok (&error);
4504 return
4505 mono_type_get_generic_param_num (a_type) -
4506 mono_type_get_generic_param_num (b_type);
4507 } else
4508 return (*a_entry)->owner - (*b_entry)->owner;
4511 static int
4512 compare_declsecurity_attrs (const void *a, const void *b)
4514 const guint32 *a_values = (const guint32 *)a;
4515 const guint32 *b_values = (const guint32 *)b;
4517 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4520 static int
4521 compare_interface_impl (const void *a, const void *b)
4523 const guint32 *a_values = (const guint32 *)a;
4524 const guint32 *b_values = (const guint32 *)b;
4526 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4527 if (klass)
4528 return klass;
4530 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4533 static void
4534 pad_heap (MonoDynamicStream *sh)
4536 if (sh->index & 3) {
4537 int sz = 4 - (sh->index & 3);
4538 memset (sh->data + sh->index, 0, sz);
4539 sh->index += sz;
4543 struct StreamDesc {
4544 const char *name;
4545 MonoDynamicStream *stream;
4549 * build_compressed_metadata() fills in the blob of data that represents the
4550 * raw metadata as it will be saved in the PE file. The five streams are output
4551 * and the metadata tables are comnpressed from the guint32 array representation,
4552 * to the compressed on-disk format.
4554 static gboolean
4555 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4557 MonoDynamicTable *table;
4558 int i;
4559 guint64 valid_mask = 0;
4560 guint64 sorted_mask;
4561 guint32 heapt_size = 0;
4562 guint32 meta_size = 256; /* allow for header and other stuff */
4563 guint32 table_offset;
4564 guint32 ntables = 0;
4565 guint64 *int64val;
4566 guint32 *int32val;
4567 guint16 *int16val;
4568 MonoImage *meta;
4569 unsigned char *p;
4570 struct StreamDesc stream_desc [5];
4572 mono_error_init (error);
4574 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4575 for (i = 0; i < assembly->gen_params->len; i++) {
4576 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4577 if (!write_generic_param_entry (assembly, entry, error))
4578 return FALSE;
4581 stream_desc [0].name = "#~";
4582 stream_desc [0].stream = &assembly->tstream;
4583 stream_desc [1].name = "#Strings";
4584 stream_desc [1].stream = &assembly->sheap;
4585 stream_desc [2].name = "#US";
4586 stream_desc [2].stream = &assembly->us;
4587 stream_desc [3].name = "#Blob";
4588 stream_desc [3].stream = &assembly->blob;
4589 stream_desc [4].name = "#GUID";
4590 stream_desc [4].stream = &assembly->guid;
4592 /* tables that are sorted */
4593 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4594 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4595 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4596 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4597 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4598 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4599 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4601 /* Compute table sizes */
4602 /* the MonoImage has already been created in mono_image_basic_init() */
4603 meta = &assembly->image;
4605 /* sizes should be multiple of 4 */
4606 pad_heap (&assembly->blob);
4607 pad_heap (&assembly->guid);
4608 pad_heap (&assembly->sheap);
4609 pad_heap (&assembly->us);
4611 /* Setup the info used by compute_sizes () */
4612 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4613 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4614 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4616 meta_size += assembly->blob.index;
4617 meta_size += assembly->guid.index;
4618 meta_size += assembly->sheap.index;
4619 meta_size += assembly->us.index;
4621 for (i=0; i < MONO_TABLE_NUM; ++i)
4622 meta->tables [i].rows = assembly->tables [i].rows;
4624 for (i = 0; i < MONO_TABLE_NUM; i++){
4625 if (meta->tables [i].rows == 0)
4626 continue;
4627 valid_mask |= (guint64)1 << i;
4628 ntables ++;
4629 meta->tables [i].row_size = mono_metadata_compute_size (
4630 meta, i, &meta->tables [i].size_bitfield);
4631 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4633 heapt_size += 24; /* #~ header size */
4634 heapt_size += ntables * 4;
4635 /* make multiple of 4 */
4636 heapt_size += 3;
4637 heapt_size &= ~3;
4638 meta_size += heapt_size;
4639 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4640 p = (unsigned char*)meta->raw_metadata;
4641 /* the metadata signature */
4642 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4643 /* version numbers and 4 bytes reserved */
4644 int16val = (guint16*)p;
4645 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4646 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4647 p += 8;
4648 /* version string */
4649 int32val = (guint32*)p;
4650 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4651 p += 4;
4652 memcpy (p, meta->version, strlen (meta->version));
4653 p += GUINT32_FROM_LE (*int32val);
4654 align_pointer (meta->raw_metadata, p);
4655 int16val = (guint16*)p;
4656 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4657 *int16val = GUINT16_TO_LE (5); /* number of streams */
4658 p += 4;
4661 * write the stream info.
4663 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4664 table_offset += 3; table_offset &= ~3;
4666 assembly->tstream.index = heapt_size;
4667 for (i = 0; i < 5; ++i) {
4668 int32val = (guint32*)p;
4669 stream_desc [i].stream->offset = table_offset;
4670 *int32val++ = GUINT32_TO_LE (table_offset);
4671 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4672 table_offset += GUINT32_FROM_LE (*int32val);
4673 table_offset += 3; table_offset &= ~3;
4674 p += 8;
4675 strcpy ((char*)p, stream_desc [i].name);
4676 p += strlen (stream_desc [i].name) + 1;
4677 align_pointer (meta->raw_metadata, p);
4680 * now copy the data, the table stream header and contents goes first.
4682 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4683 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4684 int32val = (guint32*)p;
4685 *int32val = GUINT32_TO_LE (0); /* reserved */
4686 p += 4;
4688 *p++ = 2; /* version */
4689 *p++ = 0;
4691 if (meta->idx_string_wide)
4692 *p |= 0x01;
4693 if (meta->idx_guid_wide)
4694 *p |= 0x02;
4695 if (meta->idx_blob_wide)
4696 *p |= 0x04;
4697 ++p;
4698 *p++ = 1; /* reserved */
4699 int64val = (guint64*)p;
4700 *int64val++ = GUINT64_TO_LE (valid_mask);
4701 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4702 p += 16;
4703 int32val = (guint32*)p;
4704 for (i = 0; i < MONO_TABLE_NUM; i++){
4705 if (meta->tables [i].rows == 0)
4706 continue;
4707 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4709 p = (unsigned char*)int32val;
4711 /* sort the tables that still need sorting */
4712 table = &assembly->tables [MONO_TABLE_CONSTANT];
4713 if (table->rows)
4714 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4715 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4716 if (table->rows)
4717 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4718 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4719 if (table->rows)
4720 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4721 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4722 if (table->rows)
4723 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4724 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4725 if (table->rows)
4726 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4727 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4728 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4729 if (table->rows)
4730 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4731 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4732 if (table->rows)
4733 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4735 /* compress the tables */
4736 for (i = 0; i < MONO_TABLE_NUM; i++){
4737 int row, col;
4738 guint32 *values;
4739 guint32 bitfield = meta->tables [i].size_bitfield;
4740 if (!meta->tables [i].rows)
4741 continue;
4742 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4743 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4744 meta->tables [i].base = (char*)p;
4745 for (row = 1; row <= meta->tables [i].rows; ++row) {
4746 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4747 for (col = 0; col < assembly->tables [i].columns; ++col) {
4748 switch (mono_metadata_table_size (bitfield, col)) {
4749 case 1:
4750 *p++ = values [col];
4751 break;
4752 case 2:
4753 *p++ = values [col] & 0xff;
4754 *p++ = (values [col] >> 8) & 0xff;
4755 break;
4756 case 4:
4757 *p++ = values [col] & 0xff;
4758 *p++ = (values [col] >> 8) & 0xff;
4759 *p++ = (values [col] >> 16) & 0xff;
4760 *p++ = (values [col] >> 24) & 0xff;
4761 break;
4762 default:
4763 g_assert_not_reached ();
4767 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4770 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4771 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4772 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4773 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4774 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4776 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4778 return TRUE;
4782 * Some tables in metadata need to be sorted according to some criteria, but
4783 * when methods and fields are first created with reflection, they may be assigned a token
4784 * that doesn't correspond to the final token they will get assigned after the sorting.
4785 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4786 * with the reflection objects that represent them. Once all the tables are set up, the
4787 * reflection objects will contains the correct table index. fixup_method() will fixup the
4788 * tokens for the method with ILGenerator @ilgen.
4790 static void
4791 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4793 guint32 code_idx = GPOINTER_TO_UINT (value);
4794 MonoReflectionILTokenInfo *iltoken;
4795 MonoReflectionFieldBuilder *field;
4796 MonoReflectionCtorBuilder *ctor;
4797 MonoReflectionMethodBuilder *method;
4798 MonoReflectionTypeBuilder *tb;
4799 MonoReflectionArrayMethod *am;
4800 guint32 i, idx = 0;
4801 unsigned char *target;
4803 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4804 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4805 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4806 switch (target [3]) {
4807 case MONO_TABLE_FIELD:
4808 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4809 field = (MonoReflectionFieldBuilder *)iltoken->member;
4810 idx = field->table_idx;
4811 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4812 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4813 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4814 } else {
4815 g_assert_not_reached ();
4817 break;
4818 case MONO_TABLE_METHOD:
4819 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4820 method = (MonoReflectionMethodBuilder *)iltoken->member;
4821 idx = method->table_idx;
4822 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4823 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4824 idx = ctor->table_idx;
4825 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4826 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4827 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4828 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4829 } else {
4830 g_assert_not_reached ();
4832 break;
4833 case MONO_TABLE_TYPEDEF:
4834 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4835 g_assert_not_reached ();
4836 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4837 idx = tb->table_idx;
4838 break;
4839 case MONO_TABLE_MEMBERREF:
4840 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4841 am = (MonoReflectionArrayMethod*)iltoken->member;
4842 idx = am->table_idx;
4843 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4844 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4845 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4846 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4847 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4848 g_assert (m->klass->generic_class || m->klass->generic_container);
4849 continue;
4850 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4851 continue;
4852 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4853 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4854 g_assert (is_field_on_inst (f));
4855 continue;
4856 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4857 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4858 continue;
4859 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4860 continue;
4861 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4862 continue;
4863 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4864 continue;
4865 } else {
4866 g_assert_not_reached ();
4868 break;
4869 case MONO_TABLE_METHODSPEC:
4870 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4871 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4872 g_assert (mono_method_signature (m)->generic_param_count);
4873 continue;
4874 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4875 continue;
4876 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4877 continue;
4878 } else {
4879 g_assert_not_reached ();
4881 break;
4882 default:
4883 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4885 target [0] = idx & 0xff;
4886 target [1] = (idx >> 8) & 0xff;
4887 target [2] = (idx >> 16) & 0xff;
4892 * fixup_cattrs:
4894 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4895 * value is not known when the table is emitted.
4897 static void
4898 fixup_cattrs (MonoDynamicImage *assembly)
4900 MonoDynamicTable *table;
4901 guint32 *values;
4902 guint32 type, i, idx, token;
4903 MonoObject *ctor;
4905 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4907 for (i = 0; i < table->rows; ++i) {
4908 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4910 type = values [MONO_CUSTOM_ATTR_TYPE];
4911 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4912 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4913 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4914 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4915 g_assert (ctor);
4917 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4918 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4919 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4920 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4921 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4922 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4923 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4924 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4930 static void
4931 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4933 MonoDynamicTable *table;
4934 guint32 *values;
4936 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4937 table->rows++;
4938 alloc_table (table, table->rows);
4939 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4940 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4941 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4942 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4943 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4944 table->next_idx++;
4947 static void
4948 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4950 MonoDynamicTable *table;
4951 guint32 *values;
4952 char blob_size [6];
4953 guchar hash [20];
4954 char *b = blob_size;
4955 char *name, *sname;
4956 guint32 idx, offset;
4958 if (rsrc->filename) {
4959 name = mono_string_to_utf8 (rsrc->filename);
4960 sname = g_path_get_basename (name);
4962 table = &assembly->tables [MONO_TABLE_FILE];
4963 table->rows++;
4964 alloc_table (table, table->rows);
4965 values = table->values + table->next_idx * MONO_FILE_SIZE;
4966 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4967 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4968 g_free (sname);
4970 mono_sha1_get_digest_from_file (name, hash);
4971 mono_metadata_encode_value (20, b, &b);
4972 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4973 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4974 g_free (name);
4975 idx = table->next_idx++;
4976 rsrc->offset = 0;
4977 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4978 } else {
4979 char sizebuf [4];
4980 char *data;
4981 guint len;
4982 if (rsrc->data) {
4983 data = mono_array_addr (rsrc->data, char, 0);
4984 len = mono_array_length (rsrc->data);
4985 } else {
4986 data = NULL;
4987 len = 0;
4989 offset = len;
4990 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4991 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4992 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4993 mono_image_add_stream_data (&assembly->resources, data, len);
4995 if (!mb->is_main)
4997 * The entry should be emitted into the MANIFESTRESOURCE table of
4998 * the main module, but that needs to reference the FILE table
4999 * which isn't emitted yet.
5001 return;
5002 else
5003 idx = 0;
5006 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5009 static void
5010 set_version_from_string (MonoString *version, guint32 *values)
5012 gchar *ver, *p, *str;
5013 guint32 i;
5015 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5016 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5017 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5018 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5019 if (!version)
5020 return;
5021 ver = str = mono_string_to_utf8 (version);
5022 for (i = 0; i < 4; ++i) {
5023 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5024 switch (*p) {
5025 case '.':
5026 p++;
5027 break;
5028 case '*':
5029 /* handle Revision and Build */
5030 p++;
5031 break;
5033 ver = p;
5035 g_free (str);
5038 static guint32
5039 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5040 gsize len;
5041 guint32 token = 0;
5042 char blob_size [6];
5043 char *b = blob_size;
5045 if (!pkey)
5046 return token;
5048 len = mono_array_length (pkey);
5049 mono_metadata_encode_value (len, b, &b);
5050 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5051 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5053 assembly->public_key = (guint8 *)g_malloc (len);
5054 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5055 assembly->public_key_len = len;
5057 /* Special case: check for ECMA key (16 bytes) */
5058 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5059 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5060 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5061 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5062 /* minimum key size (in 2.0) is 384 bits */
5063 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5064 } else {
5065 /* FIXME - verifier */
5066 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5067 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5069 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5071 return token;
5074 static void
5075 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5077 MonoDynamicTable *table;
5078 MonoDynamicImage *assembly;
5079 MonoReflectionAssemblyBuilder *assemblyb;
5080 MonoDomain *domain;
5081 guint32 *values;
5082 int i;
5083 guint32 module_index;
5085 mono_error_init (error);
5087 assemblyb = moduleb->assemblyb;
5088 assembly = moduleb->dynamic_image;
5089 domain = mono_object_domain (assemblyb);
5091 /* Emit ASSEMBLY table */
5092 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5093 alloc_table (table, 1);
5094 values = table->values + MONO_ASSEMBLY_SIZE;
5095 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5096 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5097 if (assemblyb->culture) {
5098 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5099 } else {
5100 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5102 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5103 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5104 set_version_from_string (assemblyb->version, values);
5106 /* Emit FILE + EXPORTED_TYPE table */
5107 module_index = 0;
5108 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5109 int j;
5110 MonoReflectionModuleBuilder *file_module =
5111 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5112 if (file_module != moduleb) {
5113 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5114 module_index ++;
5115 if (file_module->types) {
5116 for (j = 0; j < file_module->num_types; ++j) {
5117 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5118 mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5119 return_if_nok (error);
5124 if (assemblyb->loaded_modules) {
5125 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5126 MonoReflectionModule *file_module =
5127 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5128 mono_image_fill_file_table (domain, file_module, assembly);
5129 module_index ++;
5130 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5133 if (assemblyb->type_forwarders)
5134 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5136 /* Emit MANIFESTRESOURCE table */
5137 module_index = 0;
5138 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5139 int j;
5140 MonoReflectionModuleBuilder *file_module =
5141 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5142 /* The table for the main module is emitted later */
5143 if (file_module != moduleb) {
5144 module_index ++;
5145 if (file_module->resources) {
5146 int len = mono_array_length (file_module->resources);
5147 for (j = 0; j < len; ++j) {
5148 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5149 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5156 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5159 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5160 * for the modulebuilder @moduleb.
5161 * At the end of the process, method and field tokens are fixed up and the
5162 * on-disk compressed metadata representation is created.
5163 * Return TRUE on success, or FALSE on failure and sets @error
5165 gboolean
5166 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5168 MonoDynamicTable *table;
5169 MonoDynamicImage *assembly;
5170 MonoReflectionAssemblyBuilder *assemblyb;
5171 MonoDomain *domain;
5172 MonoPtrArray types;
5173 guint32 *values;
5174 int i, j;
5176 mono_error_init (error);
5178 assemblyb = moduleb->assemblyb;
5179 assembly = moduleb->dynamic_image;
5180 domain = mono_object_domain (assemblyb);
5182 if (assembly->text_rva)
5183 return TRUE;
5185 assembly->text_rva = START_TEXT_RVA;
5187 if (moduleb->is_main) {
5188 mono_image_emit_manifest (moduleb, error);
5189 return_val_if_nok (error, FALSE);
5192 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5193 table->rows = 1; /* .<Module> */
5194 table->next_idx++;
5195 alloc_table (table, table->rows);
5197 * Set the first entry.
5199 values = table->values + table->columns;
5200 values [MONO_TYPEDEF_FLAGS] = 0;
5201 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5202 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5203 values [MONO_TYPEDEF_EXTENDS] = 0;
5204 values [MONO_TYPEDEF_FIELD_LIST] = 1;
5205 values [MONO_TYPEDEF_METHOD_LIST] = 1;
5208 * handle global methods
5209 * FIXME: test what to do when global methods are defined in multiple modules.
5211 if (moduleb->global_methods) {
5212 table = &assembly->tables [MONO_TABLE_METHOD];
5213 table->rows += mono_array_length (moduleb->global_methods);
5214 alloc_table (table, table->rows);
5215 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5216 if (!mono_image_get_method_info (
5217 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5218 goto leave;
5221 if (moduleb->global_fields) {
5222 table = &assembly->tables [MONO_TABLE_FIELD];
5223 table->rows += mono_array_length (moduleb->global_fields);
5224 alloc_table (table, table->rows);
5225 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5226 mono_image_get_field_info (
5227 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5228 error);
5229 if (!is_ok (error))
5230 goto leave;
5234 table = &assembly->tables [MONO_TABLE_MODULE];
5235 alloc_table (table, 1);
5236 mono_image_fill_module_table (domain, moduleb, assembly);
5238 /* Collect all types into a list sorted by their table_idx */
5239 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5241 if (moduleb->types)
5242 for (i = 0; i < moduleb->num_types; ++i) {
5243 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5244 collect_types (&types, type);
5247 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5248 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5249 table->rows += mono_ptr_array_size (types);
5250 alloc_table (table, table->rows);
5253 * Emit type names + namespaces at one place inside the string heap,
5254 * so load_class_names () needs to touch fewer pages.
5256 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5257 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5258 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5260 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5261 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5262 string_heap_insert_mstring (&assembly->sheap, tb->name);
5265 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5266 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5267 if (!mono_image_get_type_info (domain, type, assembly, error))
5268 goto leave_types;
5272 * table->rows is already set above and in mono_image_fill_module_table.
5274 /* add all the custom attributes at the end, once all the indexes are stable */
5275 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5276 goto leave_types;
5278 /* CAS assembly permissions */
5279 if (assemblyb->permissions_minimum)
5280 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5281 if (assemblyb->permissions_optional)
5282 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5283 if (assemblyb->permissions_refused)
5284 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5286 if (!module_add_cattrs (assembly, moduleb, error))
5287 goto leave_types;
5289 /* fixup tokens */
5290 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5292 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5293 * the final tokens and don't need another fixup pass. */
5295 if (moduleb->global_methods) {
5296 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5297 MonoReflectionMethodBuilder *mb = mono_array_get (
5298 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5299 if (!mono_image_add_methodimpl (assembly, mb, error))
5300 goto leave_types;
5304 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5305 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5306 if (type->methods) {
5307 for (j = 0; j < type->num_methods; ++j) {
5308 MonoReflectionMethodBuilder *mb = mono_array_get (
5309 type->methods, MonoReflectionMethodBuilder*, j);
5311 if (!mono_image_add_methodimpl (assembly, mb, error))
5312 goto leave_types;
5317 fixup_cattrs (assembly);
5319 leave_types:
5320 mono_ptr_array_destroy (types);
5321 leave:
5323 return mono_error_ok (error);
5326 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5328 gboolean
5329 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5331 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5334 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5337 typedef struct {
5338 guint32 import_lookup_table;
5339 guint32 timestamp;
5340 guint32 forwarder;
5341 guint32 name_rva;
5342 guint32 import_address_table_rva;
5343 } MonoIDT;
5345 typedef struct {
5346 guint32 name_rva;
5347 guint32 flags;
5348 } MonoILT;
5350 #ifndef DISABLE_REFLECTION_EMIT
5353 * mono_image_insert_string:
5354 * @module: module builder object
5355 * @str: a string
5357 * Insert @str into the user string stream of @module.
5359 guint32
5360 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5362 MonoDynamicImage *assembly;
5363 guint32 idx;
5364 char buf [16];
5365 char *b = buf;
5367 if (!module->dynamic_image)
5368 mono_image_module_basic_init (module);
5370 assembly = module->dynamic_image;
5372 if (assembly->save) {
5373 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5374 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5375 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5377 char *swapped = g_malloc (2 * mono_string_length (str));
5378 const char *p = (const char*)mono_string_chars (str);
5380 swap_with_size (swapped, p, 2, mono_string_length (str));
5381 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5382 g_free (swapped);
5384 #else
5385 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5386 #endif
5387 mono_image_add_stream_data (&assembly->us, "", 1);
5388 } else {
5389 idx = assembly->us.index ++;
5392 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5394 return MONO_TOKEN_STRING | idx;
5397 guint32
5398 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5400 MonoClass *klass;
5401 guint32 token = 0;
5402 MonoMethodSignature *sig;
5404 mono_error_init (error);
5406 klass = obj->vtable->klass;
5407 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5408 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5409 MonoMethodSignature *old;
5410 guint32 sig_token, parent;
5411 int nargs, i;
5413 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5415 nargs = mono_array_length (opt_param_types);
5416 old = mono_method_signature (method);
5417 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5419 sig->hasthis = old->hasthis;
5420 sig->explicit_this = old->explicit_this;
5421 sig->call_convention = old->call_convention;
5422 sig->generic_param_count = old->generic_param_count;
5423 sig->param_count = old->param_count + nargs;
5424 sig->sentinelpos = old->param_count;
5425 sig->ret = old->ret;
5427 for (i = 0; i < old->param_count; i++)
5428 sig->params [i] = old->params [i];
5430 for (i = 0; i < nargs; i++) {
5431 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5432 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5433 if (!is_ok (error)) goto fail;
5436 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5437 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5438 parent >>= MONO_TYPEDEFORREF_BITS;
5440 parent <<= MONO_MEMBERREF_PARENT_BITS;
5441 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5443 sig_token = method_encode_signature (assembly, sig);
5444 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5445 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5446 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5447 ReflectionMethodBuilder rmb;
5448 guint32 parent, sig_token;
5449 int nopt_args, nparams, ngparams, i;
5451 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5452 goto fail;
5454 rmb.opt_types = opt_param_types;
5455 nopt_args = mono_array_length (opt_param_types);
5457 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5458 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5459 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5461 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5462 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5463 sig->call_convention = rmb.call_conv;
5464 sig->generic_param_count = ngparams;
5465 sig->param_count = nparams + nopt_args;
5466 sig->sentinelpos = nparams;
5467 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5468 if (!is_ok (error)) goto fail;
5470 for (i = 0; i < nparams; i++) {
5471 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5472 sig->params [i] = mono_reflection_type_get_handle (rt, error);
5473 if (!is_ok (error)) goto fail;
5476 for (i = 0; i < nopt_args; i++) {
5477 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5478 sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5479 if (!is_ok (error)) goto fail;
5482 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5483 if (!is_ok (error))
5484 goto fail;
5486 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5487 if (!mono_error_ok (error))
5488 goto fail;
5489 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5491 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5492 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5494 char *name = mono_string_to_utf8 (rmb.name);
5495 token = mono_image_get_varargs_method_token (
5496 assembly, parent, name, sig_token);
5497 g_free (name);
5498 } else {
5499 g_error ("requested method token for %s\n", klass->name);
5502 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5503 register_dyn_token (assembly, token, obj);
5504 return token;
5505 fail:
5506 g_assert (!mono_error_ok (error));
5507 return 0;
5511 * mono_image_create_token:
5512 * @assembly: a dynamic assembly
5513 * @obj:
5514 * @register_token: Whenever to register the token in the assembly->tokens hash.
5516 * Get a token to insert in the IL code stream for the given MemberInfo.
5517 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5518 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5519 * entry.
5521 guint32
5522 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5523 gboolean create_open_instance, gboolean register_token,
5524 MonoError *error)
5526 MonoClass *klass;
5527 guint32 token = 0;
5529 mono_error_init (error);
5531 klass = obj->vtable->klass;
5533 /* Check for user defined reflection objects */
5534 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5535 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5536 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5537 return 0;
5540 if (strcmp (klass->name, "MethodBuilder") == 0) {
5541 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5542 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5544 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5545 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5546 else {
5547 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5548 if (!mono_error_ok (error))
5549 return 0;
5551 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5552 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5553 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5554 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5556 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5557 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5558 else {
5559 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5560 if (!mono_error_ok (error))
5561 return 0;
5563 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5564 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5565 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5566 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5567 if (tb->generic_params) {
5568 token = mono_image_get_generic_field_token (assembly, fb, error);
5569 return_val_if_nok (error, 0);
5570 } else {
5571 if (tb->module->dynamic_image == assembly) {
5572 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5573 } else {
5574 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5577 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5578 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5579 if (create_open_instance && tb->generic_params) {
5580 MonoType *type;
5581 init_type_builder_generics (obj);
5582 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5583 return_val_if_nok (error, 0);
5584 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5585 token = mono_metadata_token_from_dor (token);
5586 } else if (tb->module->dynamic_image == assembly) {
5587 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5588 } else {
5589 MonoType *type;
5590 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5591 return_val_if_nok (error, 0);
5592 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5594 } else if (strcmp (klass->name, "MonoType") == 0) {
5595 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5596 return_val_if_nok (error, 0);
5597 MonoClass *mc = mono_class_from_mono_type (type);
5598 token = mono_metadata_token_from_dor (
5599 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5600 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5601 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5602 return_val_if_nok (error, 0);
5603 token = mono_metadata_token_from_dor (
5604 mono_image_typedef_or_ref (assembly, type));
5605 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5606 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5607 return_val_if_nok (error, 0);
5608 token = mono_metadata_token_from_dor (
5609 mono_image_typedef_or_ref (assembly, type));
5610 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5611 strcmp (klass->name, "MonoMethod") == 0 ||
5612 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5613 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5614 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5615 if (m->method->is_inflated) {
5616 if (create_open_instance)
5617 token = mono_image_get_methodspec_token (assembly, m->method);
5618 else
5619 token = mono_image_get_inflated_method_token (assembly, m->method);
5620 } else if ((m->method->klass->image == &assembly->image) &&
5621 !m->method->klass->generic_class) {
5622 static guint32 method_table_idx = 0xffffff;
5623 if (m->method->klass->wastypebuilder) {
5624 /* we use the same token as the one that was assigned
5625 * to the Methodbuilder.
5626 * FIXME: do the equivalent for Fields.
5628 token = m->method->token;
5629 } else {
5631 * Each token should have a unique index, but the indexes are
5632 * assigned by managed code, so we don't know about them. An
5633 * easy solution is to count backwards...
5635 method_table_idx --;
5636 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5638 } else {
5639 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5641 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5642 } else if (strcmp (klass->name, "MonoField") == 0) {
5643 MonoReflectionField *f = (MonoReflectionField *)obj;
5644 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5645 static guint32 field_table_idx = 0xffffff;
5646 field_table_idx --;
5647 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5648 } else {
5649 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5651 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5652 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5653 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5654 token = mono_image_get_array_token (assembly, m, error);
5655 return_val_if_nok (error, 0);
5656 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5657 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5658 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5659 return_val_if_nok (error, 0);
5660 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5661 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5662 return_val_if_nok (error, 0);
5663 token = mono_metadata_token_from_dor (
5664 mono_image_typedef_or_ref (assembly, type));
5665 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5666 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5667 token = mono_image_get_field_on_inst_token (assembly, f, error);
5668 return_val_if_nok (error, 0);
5669 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5670 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5671 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5672 if (!mono_error_ok (error))
5673 return 0;
5674 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5675 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5676 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5677 if (!mono_error_ok (error))
5678 return 0;
5679 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5680 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5681 return_val_if_nok (error, 0);
5682 token = mono_metadata_token_from_dor (
5683 mono_image_typedef_or_ref (assembly, type));
5684 } else {
5685 g_error ("requested token for %s\n", klass->name);
5688 if (register_token)
5689 mono_image_register_token (assembly, token, obj);
5691 return token;
5695 * mono_image_register_token:
5697 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5698 * the Module.ResolveXXXToken () methods to work.
5700 void
5701 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5703 MonoObject *prev;
5705 dynamic_image_lock (assembly);
5706 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5707 if (prev) {
5708 /* There could be multiple MethodInfo objects with the same token */
5709 //g_assert (prev == obj);
5710 } else {
5711 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5713 dynamic_image_unlock (assembly);
5716 static MonoDynamicImage*
5717 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5719 static const guchar entrycode [16] = {0xff, 0x25, 0};
5720 MonoDynamicImage *image;
5721 int i;
5723 const char *version;
5725 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5726 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5727 else
5728 version = mono_get_runtime_info ()->runtime_version;
5730 #if HAVE_BOEHM_GC
5731 /* The MonoGHashTable's need GC tracking */
5732 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5733 #else
5734 image = g_new0 (MonoDynamicImage, 1);
5735 #endif
5737 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5739 /*g_print ("created image %p\n", image);*/
5740 /* keep in sync with image.c */
5741 image->image.name = assembly_name;
5742 image->image.assembly_name = image->image.name; /* they may be different */
5743 image->image.module_name = module_name;
5744 image->image.version = g_strdup (version);
5745 image->image.md_version_major = 1;
5746 image->image.md_version_minor = 1;
5747 image->image.dynamic = TRUE;
5749 image->image.references = g_new0 (MonoAssembly*, 1);
5750 image->image.references [0] = NULL;
5752 mono_image_init (&image->image);
5754 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");
5755 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5756 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5757 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5758 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5759 image->handleref = g_hash_table_new (NULL, NULL);
5760 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");
5761 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5762 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");
5763 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");
5764 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5765 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5766 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5767 image->gen_params = g_ptr_array_new ();
5768 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5770 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5771 string_heap_init (&image->sheap);
5772 mono_image_add_stream_data (&image->us, "", 1);
5773 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5774 /* import tables... */
5775 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5776 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5777 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5778 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5779 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5780 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5781 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5782 stream_data_align (&image->code);
5784 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5786 for (i=0; i < MONO_TABLE_NUM; ++i) {
5787 image->tables [i].next_idx = 1;
5788 image->tables [i].columns = table_sizes [i];
5791 image->image.assembly = (MonoAssembly*)assembly;
5792 image->run = assembly->run;
5793 image->save = assembly->save;
5794 image->pe_kind = 0x1; /* ILOnly */
5795 image->machine = 0x14c; /* I386 */
5797 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5799 dynamic_images_lock ();
5801 if (!dynamic_images)
5802 dynamic_images = g_ptr_array_new ();
5804 g_ptr_array_add (dynamic_images, image);
5806 dynamic_images_unlock ();
5808 return image;
5810 #endif
5812 static void
5813 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5815 g_free (key);
5818 static void
5819 release_hashtable (MonoGHashTable **hash)
5821 if (*hash) {
5822 mono_g_hash_table_destroy (*hash);
5823 *hash = NULL;
5827 void
5828 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5830 release_hashtable (&image->token_fixups);
5831 release_hashtable (&image->handleref_managed);
5832 release_hashtable (&image->tokens);
5833 release_hashtable (&image->remapped_tokens);
5834 release_hashtable (&image->generic_def_objects);
5835 release_hashtable (&image->methodspec);
5838 // Free dynamic image pass one: Free resources but not image itself
5839 void
5840 mono_dynamic_image_free (MonoDynamicImage *image)
5842 MonoDynamicImage *di = image;
5843 GList *list;
5844 int i;
5846 if (di->methodspec)
5847 mono_g_hash_table_destroy (di->methodspec);
5848 if (di->typespec)
5849 g_hash_table_destroy (di->typespec);
5850 if (di->typeref)
5851 g_hash_table_destroy (di->typeref);
5852 if (di->handleref)
5853 g_hash_table_destroy (di->handleref);
5854 if (di->handleref_managed)
5855 mono_g_hash_table_destroy (di->handleref_managed);
5856 if (di->tokens)
5857 mono_g_hash_table_destroy (di->tokens);
5858 if (di->remapped_tokens)
5859 mono_g_hash_table_destroy (di->remapped_tokens);
5860 if (di->generic_def_objects)
5861 mono_g_hash_table_destroy (di->generic_def_objects);
5862 if (di->blob_cache) {
5863 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5864 g_hash_table_destroy (di->blob_cache);
5866 if (di->standalonesig_cache)
5867 g_hash_table_destroy (di->standalonesig_cache);
5868 for (list = di->array_methods; list; list = list->next) {
5869 ArrayMethod *am = (ArrayMethod *)list->data;
5870 g_free (am->sig);
5871 g_free (am->name);
5872 g_free (am);
5874 g_list_free (di->array_methods);
5875 if (di->gen_params) {
5876 for (i = 0; i < di->gen_params->len; i++) {
5877 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5878 mono_gc_deregister_root ((char*) &entry->gparam);
5879 g_free (entry);
5881 g_ptr_array_free (di->gen_params, TRUE);
5883 if (di->token_fixups)
5884 mono_g_hash_table_destroy (di->token_fixups);
5885 if (di->method_to_table_idx)
5886 g_hash_table_destroy (di->method_to_table_idx);
5887 if (di->field_to_table_idx)
5888 g_hash_table_destroy (di->field_to_table_idx);
5889 if (di->method_aux_hash)
5890 g_hash_table_destroy (di->method_aux_hash);
5891 if (di->vararg_aux_hash)
5892 g_hash_table_destroy (di->vararg_aux_hash);
5893 g_free (di->strong_name);
5894 g_free (di->win32_res);
5895 if (di->public_key)
5896 g_free (di->public_key);
5898 /*g_print ("string heap destroy for image %p\n", di);*/
5899 mono_dynamic_stream_reset (&di->sheap);
5900 mono_dynamic_stream_reset (&di->code);
5901 mono_dynamic_stream_reset (&di->resources);
5902 mono_dynamic_stream_reset (&di->us);
5903 mono_dynamic_stream_reset (&di->blob);
5904 mono_dynamic_stream_reset (&di->tstream);
5905 mono_dynamic_stream_reset (&di->guid);
5906 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5907 g_free (di->tables [i].values);
5910 dynamic_images_lock ();
5912 if (dynamic_images)
5913 g_ptr_array_remove (dynamic_images, di);
5915 dynamic_images_unlock ();
5918 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5919 void
5920 mono_dynamic_image_free_image (MonoDynamicImage *image)
5922 /* See create_dynamic_mono_image () */
5923 #if HAVE_BOEHM_GC
5924 /* Allocated using GC_MALLOC */
5925 #else
5926 g_free (image);
5927 #endif
5930 #ifndef DISABLE_REFLECTION_EMIT
5933 * mono_image_basic_init:
5934 * @assembly: an assembly builder object
5936 * Create the MonoImage that represents the assembly builder and setup some
5937 * of the helper hash table and the basic metadata streams.
5939 void
5940 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5942 MonoDynamicAssembly *assembly;
5943 MonoDynamicImage *image;
5944 MonoDomain *domain = mono_object_domain (assemblyb);
5946 if (assemblyb->dynamic_assembly)
5947 return;
5949 #if HAVE_BOEHM_GC
5950 /* assembly->assembly.image might be GC allocated */
5951 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5952 #else
5953 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5954 #endif
5956 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5958 assembly->assembly.ref_count = 1;
5959 assembly->assembly.dynamic = TRUE;
5960 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5961 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5962 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5963 if (assemblyb->culture)
5964 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5965 else
5966 assembly->assembly.aname.culture = g_strdup ("");
5968 if (assemblyb->version) {
5969 char *vstr = mono_string_to_utf8 (assemblyb->version);
5970 char **version = g_strsplit (vstr, ".", 4);
5971 char **parts = version;
5972 assembly->assembly.aname.major = atoi (*parts++);
5973 assembly->assembly.aname.minor = atoi (*parts++);
5974 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5975 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5977 g_strfreev (version);
5978 g_free (vstr);
5979 } else {
5980 assembly->assembly.aname.major = 0;
5981 assembly->assembly.aname.minor = 0;
5982 assembly->assembly.aname.build = 0;
5983 assembly->assembly.aname.revision = 0;
5986 assembly->run = assemblyb->access != 2;
5987 assembly->save = assemblyb->access != 1;
5988 assembly->domain = domain;
5990 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5991 image->initial_image = TRUE;
5992 assembly->assembly.aname.name = image->image.name;
5993 assembly->assembly.image = &image->image;
5994 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5995 /* -1 to correct for the trailing NULL byte */
5996 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5997 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5999 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
6002 mono_domain_assemblies_lock (domain);
6003 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6004 mono_domain_assemblies_unlock (domain);
6006 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6008 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6010 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6013 #endif /* !DISABLE_REFLECTION_EMIT */
6015 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6017 static int
6018 calc_section_size (MonoDynamicImage *assembly)
6020 int nsections = 0;
6022 /* alignment constraints */
6023 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6024 g_assert ((assembly->code.index % 4) == 0);
6025 assembly->meta_size += 3;
6026 assembly->meta_size &= ~3;
6027 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6028 g_assert ((assembly->resources.index % 4) == 0);
6030 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6031 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6032 nsections++;
6034 if (assembly->win32_res) {
6035 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6037 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6038 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6039 nsections++;
6042 assembly->sections [MONO_SECTION_RELOC].size = 12;
6043 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6044 nsections++;
6046 return nsections;
6049 typedef struct {
6050 guint32 id;
6051 guint32 offset;
6052 GSList *children;
6053 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6054 } ResTreeNode;
6056 static int
6057 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6059 ResTreeNode *t1 = (ResTreeNode*)a;
6060 ResTreeNode *t2 = (ResTreeNode*)b;
6062 return t1->id - t2->id;
6066 * resource_tree_create:
6068 * Organize the resources into a resource tree.
6070 static ResTreeNode *
6071 resource_tree_create (MonoArray *win32_resources)
6073 ResTreeNode *tree, *res_node, *type_node, *lang_node;
6074 GSList *l;
6075 int i;
6077 tree = g_new0 (ResTreeNode, 1);
6079 for (i = 0; i < mono_array_length (win32_resources); ++i) {
6080 MonoReflectionWin32Resource *win32_res =
6081 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6083 /* Create node */
6085 /* FIXME: BUG: this stores managed references in unmanaged memory */
6086 lang_node = g_new0 (ResTreeNode, 1);
6087 lang_node->id = win32_res->lang_id;
6088 lang_node->win32_res = win32_res;
6090 /* Create type node if neccesary */
6091 type_node = NULL;
6092 for (l = tree->children; l; l = l->next)
6093 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6094 type_node = (ResTreeNode*)l->data;
6095 break;
6098 if (!type_node) {
6099 type_node = g_new0 (ResTreeNode, 1);
6100 type_node->id = win32_res->res_type;
6103 * The resource types have to be sorted otherwise
6104 * Windows Explorer can't display the version information.
6106 tree->children = g_slist_insert_sorted (tree->children,
6107 type_node, resource_tree_compare_by_id);
6110 /* Create res node if neccesary */
6111 res_node = NULL;
6112 for (l = type_node->children; l; l = l->next)
6113 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6114 res_node = (ResTreeNode*)l->data;
6115 break;
6118 if (!res_node) {
6119 res_node = g_new0 (ResTreeNode, 1);
6120 res_node->id = win32_res->res_id;
6121 type_node->children = g_slist_append (type_node->children, res_node);
6124 res_node->children = g_slist_append (res_node->children, lang_node);
6127 return tree;
6131 * resource_tree_encode:
6133 * Encode the resource tree into the format used in the PE file.
6135 static void
6136 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6138 char *entries;
6139 MonoPEResourceDir dir;
6140 MonoPEResourceDirEntry dir_entry;
6141 MonoPEResourceDataEntry data_entry;
6142 GSList *l;
6143 guint32 res_id_entries;
6146 * For the format of the resource directory, see the article
6147 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6148 * Matt Pietrek
6151 memset (&dir, 0, sizeof (dir));
6152 memset (&dir_entry, 0, sizeof (dir_entry));
6153 memset (&data_entry, 0, sizeof (data_entry));
6155 g_assert (sizeof (dir) == 16);
6156 g_assert (sizeof (dir_entry) == 8);
6157 g_assert (sizeof (data_entry) == 16);
6159 node->offset = p - begin;
6161 /* IMAGE_RESOURCE_DIRECTORY */
6162 res_id_entries = g_slist_length (node->children);
6163 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6165 memcpy (p, &dir, sizeof (dir));
6166 p += sizeof (dir);
6168 /* Reserve space for entries */
6169 entries = p;
6170 p += sizeof (dir_entry) * res_id_entries;
6172 /* Write children */
6173 for (l = node->children; l; l = l->next) {
6174 ResTreeNode *child = (ResTreeNode*)l->data;
6176 if (child->win32_res) {
6177 guint32 size;
6179 child->offset = p - begin;
6181 /* IMAGE_RESOURCE_DATA_ENTRY */
6182 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6183 size = mono_array_length (child->win32_res->res_data);
6184 data_entry.rde_size = GUINT32_TO_LE (size);
6186 memcpy (p, &data_entry, sizeof (data_entry));
6187 p += sizeof (data_entry);
6189 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6190 p += size;
6191 } else {
6192 resource_tree_encode (child, begin, p, &p);
6196 /* IMAGE_RESOURCE_ENTRY */
6197 for (l = node->children; l; l = l->next) {
6198 ResTreeNode *child = (ResTreeNode*)l->data;
6200 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6201 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6203 memcpy (entries, &dir_entry, sizeof (dir_entry));
6204 entries += sizeof (dir_entry);
6207 *endbuf = p;
6210 static void
6211 resource_tree_free (ResTreeNode * node)
6213 GSList * list;
6214 for (list = node->children; list; list = list->next)
6215 resource_tree_free ((ResTreeNode*)list->data);
6216 g_slist_free(node->children);
6217 g_free (node);
6220 static void
6221 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6223 char *buf;
6224 char *p;
6225 guint32 size, i;
6226 MonoReflectionWin32Resource *win32_res;
6227 ResTreeNode *tree;
6229 if (!assemblyb->win32_resources)
6230 return;
6233 * Resources are stored in a three level tree inside the PE file.
6234 * - level one contains a node for each type of resource
6235 * - level two contains a node for each resource
6236 * - level three contains a node for each instance of a resource for a
6237 * specific language.
6240 tree = resource_tree_create (assemblyb->win32_resources);
6242 /* Estimate the size of the encoded tree */
6243 size = 0;
6244 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6245 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6246 size += mono_array_length (win32_res->res_data);
6248 /* Directory structure */
6249 size += mono_array_length (assemblyb->win32_resources) * 256;
6250 p = buf = (char *)g_malloc (size);
6252 resource_tree_encode (tree, p, p, &p);
6254 g_assert (p - buf <= size);
6256 assembly->win32_res = (char *)g_malloc (p - buf);
6257 assembly->win32_res_size = p - buf;
6258 memcpy (assembly->win32_res, buf, p - buf);
6260 g_free (buf);
6261 resource_tree_free (tree);
6264 static void
6265 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6267 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6268 int i;
6270 p += sizeof (MonoPEResourceDir);
6271 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6272 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6273 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6274 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6275 fixup_resource_directory (res_section, child, rva);
6276 } else {
6277 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6278 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6281 p += sizeof (MonoPEResourceDirEntry);
6285 static void
6286 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6288 guint32 dummy;
6289 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6290 g_error ("WriteFile returned %d\n", GetLastError ());
6294 * mono_image_create_pefile:
6295 * @mb: a module builder object
6297 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6298 * assembly->pefile where it can be easily retrieved later in chunks.
6300 gboolean
6301 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6303 MonoMSDOSHeader *msdos;
6304 MonoDotNetHeader *header;
6305 MonoSectionTable *section;
6306 MonoCLIHeader *cli_header;
6307 guint32 size, image_size, virtual_base, text_offset;
6308 guint32 header_start, section_start, file_offset, virtual_offset;
6309 MonoDynamicImage *assembly;
6310 MonoReflectionAssemblyBuilder *assemblyb;
6311 MonoDynamicStream pefile_stream = {0};
6312 MonoDynamicStream *pefile = &pefile_stream;
6313 int i, nsections;
6314 guint32 *rva, value;
6315 guchar *p;
6316 static const unsigned char msheader[] = {
6317 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6318 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6321 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6322 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6323 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6324 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6327 mono_error_init (error);
6329 assemblyb = mb->assemblyb;
6331 mono_image_basic_init (assemblyb);
6332 assembly = mb->dynamic_image;
6334 assembly->pe_kind = assemblyb->pe_kind;
6335 assembly->machine = assemblyb->machine;
6336 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6337 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6339 if (!mono_image_build_metadata (mb, error))
6340 return FALSE;
6343 if (mb->is_main && assemblyb->resources) {
6344 int len = mono_array_length (assemblyb->resources);
6345 for (i = 0; i < len; ++i)
6346 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6349 if (mb->resources) {
6350 int len = mono_array_length (mb->resources);
6351 for (i = 0; i < len; ++i)
6352 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6355 if (!build_compressed_metadata (assembly, error))
6356 return FALSE;
6358 if (mb->is_main)
6359 assembly_add_win32_resources (assembly, assemblyb);
6361 nsections = calc_section_size (assembly);
6363 /* The DOS header and stub */
6364 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6365 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6367 /* the dotnet header */
6368 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6370 /* the section tables */
6371 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6373 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6374 virtual_offset = VIRT_ALIGN;
6375 image_size = 0;
6377 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6378 if (!assembly->sections [i].size)
6379 continue;
6380 /* align offsets */
6381 file_offset += FILE_ALIGN - 1;
6382 file_offset &= ~(FILE_ALIGN - 1);
6383 virtual_offset += VIRT_ALIGN - 1;
6384 virtual_offset &= ~(VIRT_ALIGN - 1);
6386 assembly->sections [i].offset = file_offset;
6387 assembly->sections [i].rva = virtual_offset;
6389 file_offset += assembly->sections [i].size;
6390 virtual_offset += assembly->sections [i].size;
6391 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6394 file_offset += FILE_ALIGN - 1;
6395 file_offset &= ~(FILE_ALIGN - 1);
6397 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6399 /* back-patch info */
6400 msdos = (MonoMSDOSHeader*)pefile->data;
6401 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6403 header = (MonoDotNetHeader*)(pefile->data + header_start);
6404 header->pesig [0] = 'P';
6405 header->pesig [1] = 'E';
6407 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6408 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6409 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6410 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6411 if (assemblyb->pekind == 1) {
6412 /* it's a dll */
6413 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6414 } else {
6415 /* it's an exe */
6416 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6419 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6421 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6422 header->pe.pe_major = 6;
6423 header->pe.pe_minor = 0;
6424 size = assembly->sections [MONO_SECTION_TEXT].size;
6425 size += FILE_ALIGN - 1;
6426 size &= ~(FILE_ALIGN - 1);
6427 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6428 size = assembly->sections [MONO_SECTION_RSRC].size;
6429 size += FILE_ALIGN - 1;
6430 size &= ~(FILE_ALIGN - 1);
6431 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6432 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6433 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6434 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6435 /* pe_rva_entry_point always at the beginning of the text section */
6436 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6438 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6439 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6440 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6441 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6442 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6443 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6444 size = section_start;
6445 size += FILE_ALIGN - 1;
6446 size &= ~(FILE_ALIGN - 1);
6447 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6448 size = image_size;
6449 size += VIRT_ALIGN - 1;
6450 size &= ~(VIRT_ALIGN - 1);
6451 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6454 // Translate the PEFileKind value to the value expected by the Windows loader
6457 short kind;
6460 // PEFileKinds.Dll == 1
6461 // PEFileKinds.ConsoleApplication == 2
6462 // PEFileKinds.WindowApplication == 3
6464 // need to get:
6465 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6466 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6468 if (assemblyb->pekind == 3)
6469 kind = 2;
6470 else
6471 kind = 3;
6473 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6475 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6476 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6477 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6478 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6479 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6480 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6482 /* fill data directory entries */
6484 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6485 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6487 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6488 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6490 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6491 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6492 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6493 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6494 /* patch entrypoint name */
6495 if (assemblyb->pekind == 1)
6496 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6497 else
6498 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6499 /* patch imported function RVA name */
6500 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6501 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6503 /* the import table */
6504 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6505 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6506 /* patch imported dll RVA name and other entries in the dir */
6507 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6508 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6509 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6510 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6511 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6512 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6514 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6515 value = (assembly->text_rva + assembly->imp_names_offset);
6516 *p++ = (value) & 0xff;
6517 *p++ = (value >> 8) & (0xff);
6518 *p++ = (value >> 16) & (0xff);
6519 *p++ = (value >> 24) & (0xff);
6521 /* the CLI header info */
6522 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6523 cli_header->ch_size = GUINT32_FROM_LE (72);
6524 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6525 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6526 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6527 if (assemblyb->entry_point) {
6528 guint32 table_idx = 0;
6529 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6530 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6531 table_idx = methodb->table_idx;
6532 } else {
6533 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6535 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6536 } else {
6537 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6539 /* The embedded managed resources */
6540 text_offset = assembly->text_rva + assembly->code.index;
6541 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6542 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6543 text_offset += assembly->resources.index;
6544 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6545 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6546 text_offset += assembly->meta_size;
6547 if (assembly->strong_name_size) {
6548 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6549 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6550 text_offset += assembly->strong_name_size;
6553 /* write the section tables and section content */
6554 section = (MonoSectionTable*)(pefile->data + section_start);
6555 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6556 static const char section_names [][7] = {
6557 ".text", ".rsrc", ".reloc"
6559 if (!assembly->sections [i].size)
6560 continue;
6561 strcpy (section->st_name, section_names [i]);
6562 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6563 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6564 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6565 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6566 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6567 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6568 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6569 section ++;
6572 checked_write_file (file, pefile->data, pefile->index);
6574 mono_dynamic_stream_reset (pefile);
6576 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6577 if (!assembly->sections [i].size)
6578 continue;
6580 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6581 g_error ("SetFilePointer returned %d\n", GetLastError ());
6583 switch (i) {
6584 case MONO_SECTION_TEXT:
6585 /* patch entry point */
6586 p = (guchar*)(assembly->code.data + 2);
6587 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6588 *p++ = (value) & 0xff;
6589 *p++ = (value >> 8) & 0xff;
6590 *p++ = (value >> 16) & 0xff;
6591 *p++ = (value >> 24) & 0xff;
6593 checked_write_file (file, assembly->code.data, assembly->code.index);
6594 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6595 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6596 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6599 g_free (assembly->image.raw_metadata);
6600 break;
6601 case MONO_SECTION_RELOC: {
6602 struct {
6603 guint32 page_rva;
6604 guint32 block_size;
6605 guint16 type_and_offset;
6606 guint16 term;
6607 } reloc;
6609 g_assert (sizeof (reloc) == 12);
6611 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6612 reloc.block_size = GUINT32_FROM_LE (12);
6615 * the entrypoint is always at the start of the text section
6616 * 3 is IMAGE_REL_BASED_HIGHLOW
6617 * 2 is patch_size_rva - text_rva
6619 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6620 reloc.term = 0;
6622 checked_write_file (file, &reloc, sizeof (reloc));
6624 break;
6626 case MONO_SECTION_RSRC:
6627 if (assembly->win32_res) {
6629 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6630 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6631 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6633 break;
6634 default:
6635 g_assert_not_reached ();
6639 /* check that the file is properly padded */
6640 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6641 g_error ("SetFilePointer returned %d\n", GetLastError ());
6642 if (! SetEndOfFile (file))
6643 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6645 mono_dynamic_stream_reset (&assembly->code);
6646 mono_dynamic_stream_reset (&assembly->us);
6647 mono_dynamic_stream_reset (&assembly->blob);
6648 mono_dynamic_stream_reset (&assembly->guid);
6649 mono_dynamic_stream_reset (&assembly->sheap);
6651 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6652 g_hash_table_destroy (assembly->blob_cache);
6653 assembly->blob_cache = NULL;
6655 return TRUE;
6658 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6660 gboolean
6661 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6663 g_assert_not_reached ();
6666 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6668 #ifndef DISABLE_REFLECTION_EMIT
6670 MonoReflectionModule *
6671 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6673 char *name;
6674 MonoImage *image;
6675 MonoImageOpenStatus status;
6676 MonoDynamicAssembly *assembly;
6677 guint32 module_count;
6678 MonoImage **new_modules;
6679 gboolean *new_modules_loaded;
6681 mono_error_init (error);
6683 name = mono_string_to_utf8 (fileName);
6685 image = mono_image_open (name, &status);
6686 if (!image) {
6687 if (status == MONO_IMAGE_ERROR_ERRNO)
6688 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6689 else
6690 mono_error_set_bad_image_name (error, name, NULL);
6691 g_free (name);
6692 return NULL;
6695 g_free (name);
6697 assembly = ab->dynamic_assembly;
6698 image->assembly = (MonoAssembly*)assembly;
6700 module_count = image->assembly->image->module_count;
6701 new_modules = g_new0 (MonoImage *, module_count + 1);
6702 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6704 if (image->assembly->image->modules)
6705 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6706 if (image->assembly->image->modules_loaded)
6707 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6708 new_modules [module_count] = image;
6709 new_modules_loaded [module_count] = TRUE;
6710 mono_image_addref (image);
6712 g_free (image->assembly->image->modules);
6713 image->assembly->image->modules = new_modules;
6714 image->assembly->image->modules_loaded = new_modules_loaded;
6715 image->assembly->image->module_count ++;
6717 mono_assembly_load_references (image, &status);
6718 if (status) {
6719 mono_image_close (image);
6720 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6721 return NULL;
6724 return mono_module_get_object_checked (mono_domain_get (), image, error);
6727 #endif /* DISABLE_REFLECTION_EMIT */
6730 * We need to return always the same object for MethodInfo, FieldInfo etc..
6731 * but we need to consider the reflected type.
6732 * type uses a different hash, since it uses custom hash/equal functions.
6735 typedef struct {
6736 gpointer item;
6737 MonoClass *refclass;
6738 } ReflectedEntry;
6740 static gboolean
6741 reflected_equal (gconstpointer a, gconstpointer b) {
6742 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6743 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6745 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6748 static guint
6749 reflected_hash (gconstpointer a) {
6750 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6751 return mono_aligned_addr_hash (ea->item);
6754 #define CHECK_OBJECT(t,p,k) \
6755 do { \
6756 t _obj; \
6757 ReflectedEntry e; \
6758 e.item = (p); \
6759 e.refclass = (k); \
6760 mono_domain_lock (domain); \
6761 if (!domain->refobject_hash) \
6762 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"); \
6763 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6764 mono_domain_unlock (domain); \
6765 return _obj; \
6767 mono_domain_unlock (domain); \
6768 } while (0)
6770 #ifdef HAVE_BOEHM_GC
6771 /* ReflectedEntry doesn't need to be GC tracked */
6772 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6773 #define FREE_REFENTRY(entry) g_free ((entry))
6774 #define REFENTRY_REQUIRES_CLEANUP
6775 #else
6776 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6777 /* FIXME: */
6778 #define FREE_REFENTRY(entry)
6779 #endif
6781 #define CACHE_OBJECT(t,p,o,k) \
6782 do { \
6783 t _obj; \
6784 ReflectedEntry pe; \
6785 pe.item = (p); \
6786 pe.refclass = (k); \
6787 mono_domain_lock (domain); \
6788 if (!domain->refobject_hash) \
6789 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"); \
6790 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6791 if (!_obj) { \
6792 ReflectedEntry *e = ALLOC_REFENTRY; \
6793 e->item = (p); \
6794 e->refclass = (k); \
6795 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6796 _obj = o; \
6798 mono_domain_unlock (domain); \
6799 return _obj; \
6800 } while (0)
6802 static void
6803 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6805 mono_domain_lock (domain);
6806 if (domain->refobject_hash) {
6807 ReflectedEntry pe;
6808 gpointer orig_pe, orig_value;
6810 pe.item = o;
6811 pe.refclass = klass;
6812 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6813 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6814 FREE_REFENTRY (orig_pe);
6817 mono_domain_unlock (domain);
6820 #ifdef REFENTRY_REQUIRES_CLEANUP
6821 static void
6822 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6824 FREE_REFENTRY (key);
6826 #endif
6828 void
6829 mono_reflection_cleanup_domain (MonoDomain *domain)
6831 if (domain->refobject_hash) {
6832 /*let's avoid scanning the whole hashtable if not needed*/
6833 #ifdef REFENTRY_REQUIRES_CLEANUP
6834 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6835 #endif
6836 mono_g_hash_table_destroy (domain->refobject_hash);
6837 domain->refobject_hash = NULL;
6841 #ifndef DISABLE_REFLECTION_EMIT
6842 static gpointer
6843 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6845 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6848 static gpointer
6849 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6851 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6854 void
6855 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6857 MonoDynamicImage *image = moduleb->dynamic_image;
6858 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6859 if (!image) {
6860 MonoError error;
6861 int module_count;
6862 MonoImage **new_modules;
6863 MonoImage *ass;
6864 char *name, *fqname;
6866 * FIXME: we already created an image in mono_image_basic_init (), but
6867 * we don't know which module it belongs to, since that is only
6868 * determined at assembly save time.
6870 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6871 name = mono_string_to_utf8 (ab->name);
6872 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6873 if (!mono_error_ok (&error)) {
6874 g_free (name);
6875 mono_error_raise_exception (&error);
6877 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6879 moduleb->module.image = &image->image;
6880 moduleb->dynamic_image = image;
6881 register_module (mono_object_domain (moduleb), moduleb, image);
6883 /* register the module with the assembly */
6884 ass = ab->dynamic_assembly->assembly.image;
6885 module_count = ass->module_count;
6886 new_modules = g_new0 (MonoImage *, module_count + 1);
6888 if (ass->modules)
6889 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6890 new_modules [module_count] = &image->image;
6891 mono_image_addref (&image->image);
6893 g_free (ass->modules);
6894 ass->modules = new_modules;
6895 ass->module_count ++;
6899 void
6900 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6902 MonoDynamicImage *image = moduleb->dynamic_image;
6904 g_assert (type->type);
6905 image->wrappers_type = mono_class_from_mono_type (type->type);
6908 #endif
6911 * mono_assembly_get_object:
6912 * @domain: an app domain
6913 * @assembly: an assembly
6915 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6917 MonoReflectionAssembly*
6918 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6920 MonoError error;
6921 MonoReflectionAssembly *result;
6922 result = mono_assembly_get_object_checked (domain, assembly, &error);
6923 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6924 return result;
6927 * mono_assembly_get_object_checked:
6928 * @domain: an app domain
6929 * @assembly: an assembly
6931 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6933 MonoReflectionAssembly*
6934 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6936 MonoReflectionAssembly *res;
6938 mono_error_init (error);
6940 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6941 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6942 if (!res)
6943 return NULL;
6944 res->assembly = assembly;
6946 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6951 MonoReflectionModule*
6952 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6954 MonoError error;
6955 MonoReflectionModule *result;
6956 result = mono_module_get_object_checked (domain, image, &error);
6957 mono_error_raise_exception (&error);
6958 return result;
6961 MonoReflectionModule*
6962 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6964 MonoReflectionModule *res;
6965 char* basename;
6967 mono_error_init (error);
6968 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6969 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6970 if (!res)
6971 return NULL;
6973 res->image = image;
6974 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6975 if (!assm_obj)
6976 return NULL;
6977 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6979 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6980 basename = g_path_get_basename (image->name);
6981 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6982 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6984 g_free (basename);
6986 if (image->assembly->image == image) {
6987 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6988 } else {
6989 int i;
6990 res->token = 0;
6991 if (image->assembly->image->modules) {
6992 for (i = 0; i < image->assembly->image->module_count; i++) {
6993 if (image->assembly->image->modules [i] == image)
6994 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6996 g_assert (res->token);
7000 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7003 MonoReflectionModule*
7004 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7006 MonoError error;
7007 MonoReflectionModule *result;
7008 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7009 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7010 return result;
7013 MonoReflectionModule*
7014 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7016 MonoReflectionModule *res;
7017 MonoTableInfo *table;
7018 guint32 cols [MONO_FILE_SIZE];
7019 const char *name;
7020 guint32 i, name_idx;
7021 const char *val;
7023 mono_error_init (error);
7025 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7026 if (!res)
7027 return NULL;
7029 table = &image->tables [MONO_TABLE_FILE];
7030 g_assert (table_index < table->rows);
7031 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7033 res->image = NULL;
7034 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7035 if (!assm_obj)
7036 return NULL;
7037 MONO_OBJECT_SETREF (res, assembly, assm_obj);
7038 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7040 /* Check whenever the row has a corresponding row in the moduleref table */
7041 table = &image->tables [MONO_TABLE_MODULEREF];
7042 for (i = 0; i < table->rows; ++i) {
7043 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7044 val = mono_metadata_string_heap (image, name_idx);
7045 if (strcmp (val, name) == 0)
7046 res->image = image->modules [i];
7049 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7050 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7051 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7052 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7053 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7055 return res;
7058 static gboolean
7059 verify_safe_for_managed_space (MonoType *type)
7061 switch (type->type) {
7062 #ifdef DEBUG_HARDER
7063 case MONO_TYPE_ARRAY:
7064 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7065 case MONO_TYPE_PTR:
7066 return verify_safe_for_managed_space (type->data.type);
7067 case MONO_TYPE_SZARRAY:
7068 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7069 case MONO_TYPE_GENERICINST: {
7070 MonoGenericInst *inst = type->data.generic_class->inst;
7071 int i;
7072 if (!inst->is_open)
7073 break;
7074 for (i = 0; i < inst->type_argc; ++i)
7075 if (!verify_safe_for_managed_space (inst->type_argv [i]))
7076 return FALSE;
7077 return TRUE;
7079 #endif
7080 case MONO_TYPE_VAR:
7081 case MONO_TYPE_MVAR:
7082 return TRUE;
7083 default:
7084 return TRUE;
7088 static MonoType*
7089 mono_type_normalize (MonoType *type)
7091 int i;
7092 MonoGenericClass *gclass;
7093 MonoGenericInst *ginst;
7094 MonoClass *gtd;
7095 MonoGenericContainer *gcontainer;
7096 MonoType **argv = NULL;
7097 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7099 if (type->type != MONO_TYPE_GENERICINST)
7100 return type;
7102 gclass = type->data.generic_class;
7103 ginst = gclass->context.class_inst;
7104 if (!ginst->is_open)
7105 return type;
7107 gtd = gclass->container_class;
7108 gcontainer = gtd->generic_container;
7109 argv = g_newa (MonoType*, ginst->type_argc);
7111 for (i = 0; i < ginst->type_argc; ++i) {
7112 MonoType *t = ginst->type_argv [i], *norm;
7113 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7114 is_denorm_gtd = FALSE;
7115 norm = mono_type_normalize (t);
7116 argv [i] = norm;
7117 if (norm != t)
7118 requires_rebind = TRUE;
7121 if (is_denorm_gtd)
7122 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7124 if (requires_rebind) {
7125 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7126 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7129 return type;
7132 * mono_type_get_object:
7133 * @domain: an app domain
7134 * @type: a type
7136 * Return an System.MonoType object representing the type @type.
7138 MonoReflectionType*
7139 mono_type_get_object (MonoDomain *domain, MonoType *type)
7141 MonoError error;
7142 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7143 mono_error_raise_exception (&error);
7145 return ret;
7148 MonoReflectionType*
7149 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7151 MonoType *norm_type;
7152 MonoReflectionType *res;
7153 MonoClass *klass;
7155 mono_error_init (error);
7157 klass = mono_class_from_mono_type (type);
7159 /*we must avoid using @type as it might have come
7160 * from a mono_metadata_type_dup and the caller
7161 * expects that is can be freed.
7162 * Using the right type from
7164 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7166 /* void is very common */
7167 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7168 return (MonoReflectionType*)domain->typeof_void;
7171 * If the vtable of the given class was already created, we can use
7172 * the MonoType from there and avoid all locking and hash table lookups.
7174 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7175 * that the resulting object is different.
7177 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7178 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7179 if (vtable && vtable->type)
7180 return (MonoReflectionType *)vtable->type;
7183 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7184 mono_domain_lock (domain);
7185 if (!domain->type_hash)
7186 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
7187 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7188 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7189 mono_domain_unlock (domain);
7190 mono_loader_unlock ();
7191 return res;
7194 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7195 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7196 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7197 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7198 * artifact of how generics are encoded and should be transparent to managed code so we
7199 * need to weed out this diference when retrieving managed System.Type objects.
7201 norm_type = mono_type_normalize (type);
7202 if (norm_type != type) {
7203 res = mono_type_get_object_checked (domain, norm_type, error);
7204 if (!mono_error_ok (error))
7205 return NULL;
7206 mono_g_hash_table_insert (domain->type_hash, type, res);
7207 mono_domain_unlock (domain);
7208 mono_loader_unlock ();
7209 return res;
7212 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7213 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7214 g_assert (0);
7216 if (!verify_safe_for_managed_space (type)) {
7217 mono_domain_unlock (domain);
7218 mono_loader_unlock ();
7219 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7220 return NULL;
7223 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7224 gboolean is_type_done = TRUE;
7225 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7226 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7227 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7229 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7230 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7232 if (gparam->owner && gparam->owner->is_method) {
7233 MonoMethod *method = gparam->owner->owner.method;
7234 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7235 is_type_done = FALSE;
7236 } else if (gparam->owner && !gparam->owner->is_method) {
7237 MonoClass *klass = gparam->owner->owner.klass;
7238 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7239 is_type_done = FALSE;
7243 /* g_assert_not_reached (); */
7244 /* should this be considered an error condition? */
7245 if (is_type_done && !type->byref) {
7246 mono_domain_unlock (domain);
7247 mono_loader_unlock ();
7248 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7251 /* This is stored in vtables/JITted code so it has to be pinned */
7252 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7253 if (!mono_error_ok (error))
7254 return NULL;
7256 res->type = type;
7257 mono_g_hash_table_insert (domain->type_hash, type, res);
7259 if (type->type == MONO_TYPE_VOID)
7260 domain->typeof_void = (MonoObject*)res;
7262 mono_domain_unlock (domain);
7263 mono_loader_unlock ();
7264 return res;
7268 * mono_method_get_object:
7269 * @domain: an app domain
7270 * @method: a method
7271 * @refclass: the reflected type (can be NULL)
7273 * Return an System.Reflection.MonoMethod object representing the method @method.
7275 MonoReflectionMethod*
7276 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7278 MonoError error;
7279 MonoReflectionMethod *ret = NULL;
7280 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7281 mono_error_raise_exception (&error);
7282 return ret;
7286 * mono_method_get_object_checked:
7287 * @domain: an app domain
7288 * @method: a method
7289 * @refclass: the reflected type (can be NULL)
7290 * @error: set on error.
7292 * Return an System.Reflection.MonoMethod object representing the method @method.
7293 * Returns NULL and sets @error on error.
7295 MonoReflectionMethod*
7296 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7299 * We use the same C representation for methods and constructors, but the type
7300 * name in C# is different.
7302 MonoReflectionType *rt;
7303 MonoClass *klass;
7304 MonoReflectionMethod *ret;
7306 mono_error_init (error);
7308 if (method->is_inflated) {
7309 MonoReflectionGenericMethod *gret;
7311 if (!refclass)
7312 refclass = method->klass;
7313 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7314 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7315 klass = mono_class_get_mono_generic_cmethod_class ();
7316 } else {
7317 klass = mono_class_get_mono_generic_method_class ();
7319 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7320 if (!mono_error_ok (error))
7321 goto leave;
7322 gret->method.method = method;
7324 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7326 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7327 if (!mono_error_ok (error))
7328 goto leave;
7330 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7332 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7335 if (!refclass)
7336 refclass = method->klass;
7338 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7339 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7340 klass = mono_class_get_mono_cmethod_class ();
7342 else {
7343 klass = mono_class_get_mono_method_class ();
7345 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7346 if (!mono_error_ok (error))
7347 goto leave;
7348 ret->method = method;
7350 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7351 if (!mono_error_ok (error))
7352 goto leave;
7354 MONO_OBJECT_SETREF (ret, reftype, rt);
7356 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7358 leave:
7359 g_assert (!mono_error_ok (error));
7360 return NULL;
7364 * mono_method_clear_object:
7366 * Clear the cached reflection objects for the dynamic method METHOD.
7368 void
7369 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7371 MonoClass *klass;
7372 g_assert (method_is_dynamic (method));
7374 klass = method->klass;
7375 while (klass) {
7376 clear_cached_object (domain, method, klass);
7377 klass = klass->parent;
7379 /* Added by mono_param_get_objects () */
7380 clear_cached_object (domain, &(method->signature), NULL);
7381 klass = method->klass;
7382 while (klass) {
7383 clear_cached_object (domain, &(method->signature), klass);
7384 klass = klass->parent;
7389 * mono_field_get_object:
7390 * @domain: an app domain
7391 * @klass: a type
7392 * @field: a field
7394 * Return an System.Reflection.MonoField object representing the field @field
7395 * in class @klass.
7397 MonoReflectionField*
7398 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7400 MonoError error;
7401 MonoReflectionField *result;
7402 result = mono_field_get_object_checked (domain, klass, field, &error);
7403 mono_error_raise_exception (&error);
7404 return result;
7408 * mono_field_get_object_checked:
7409 * @domain: an app domain
7410 * @klass: a type
7411 * @field: a field
7412 * @error: set on error
7414 * Return an System.Reflection.MonoField object representing the field @field
7415 * in class @klass. On error, returns NULL and sets @error.
7417 MonoReflectionField*
7418 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7420 MonoReflectionType *rt;
7421 MonoReflectionField *res;
7423 mono_error_init (error);
7425 CHECK_OBJECT (MonoReflectionField *, field, klass);
7426 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7427 if (!res)
7428 return NULL;
7429 res->klass = klass;
7430 res->field = field;
7431 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7433 if (is_field_on_inst (field)) {
7434 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7436 rt = mono_type_get_object_checked (domain, field->type, error);
7437 if (!mono_error_ok (error))
7438 return NULL;
7440 MONO_OBJECT_SETREF (res, type, rt);
7441 } else {
7442 if (field->type) {
7443 rt = mono_type_get_object_checked (domain, field->type, error);
7444 if (!mono_error_ok (error))
7445 return NULL;
7447 MONO_OBJECT_SETREF (res, type, rt);
7449 res->attrs = mono_field_get_flags (field);
7451 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7455 * mono_property_get_object:
7456 * @domain: an app domain
7457 * @klass: a type
7458 * @property: a property
7460 * Return an System.Reflection.MonoProperty object representing the property @property
7461 * in class @klass.
7463 MonoReflectionProperty*
7464 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7466 MonoError error;
7467 MonoReflectionProperty *result;
7468 result = mono_property_get_object_checked (domain, klass, property, &error);
7469 mono_error_raise_exception (&error);
7470 return result;
7474 * mono_property_get_object:
7475 * @domain: an app domain
7476 * @klass: a type
7477 * @property: a property
7478 * @error: set on error
7480 * Return an System.Reflection.MonoProperty object representing the property @property
7481 * in class @klass. On error returns NULL and sets @error.
7483 MonoReflectionProperty*
7484 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7486 MonoReflectionProperty *res;
7488 mono_error_init (error);
7490 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7491 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7492 if (!res)
7493 return NULL;
7494 res->klass = klass;
7495 res->property = property;
7496 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7500 * mono_event_get_object:
7501 * @domain: an app domain
7502 * @klass: a type
7503 * @event: a event
7505 * Return an System.Reflection.MonoEvent object representing the event @event
7506 * in class @klass.
7508 MonoReflectionEvent*
7509 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7511 MonoError error;
7512 MonoReflectionEvent *result;
7513 result = mono_event_get_object_checked (domain, klass, event, &error);
7514 mono_error_raise_exception (&error);
7515 return result;
7519 * mono_event_get_object_checked:
7520 * @domain: an app domain
7521 * @klass: a type
7522 * @event: a event
7523 * @error: set on error
7525 * Return an System.Reflection.MonoEvent object representing the event @event
7526 * in class @klass. On failure sets @error and returns NULL
7528 MonoReflectionEvent*
7529 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7531 MonoReflectionEvent *res;
7532 MonoReflectionMonoEvent *mono_event;
7534 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7535 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7536 if (!mono_event)
7537 return NULL;
7538 mono_event->klass = klass;
7539 mono_event->event = event;
7540 res = (MonoReflectionEvent*)mono_event;
7541 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7545 * mono_get_reflection_missing_object:
7546 * @domain: Domain where the object lives
7548 * Returns the System.Reflection.Missing.Value singleton object
7549 * (of type System.Reflection.Missing).
7551 * Used as the value for ParameterInfo.DefaultValue when Optional
7552 * is present
7554 static MonoObject *
7555 mono_get_reflection_missing_object (MonoDomain *domain)
7557 MonoError error;
7558 MonoObject *obj;
7559 static MonoClassField *missing_value_field = NULL;
7561 if (!missing_value_field) {
7562 MonoClass *missing_klass;
7563 missing_klass = mono_class_get_missing_class ();
7564 mono_class_init (missing_klass);
7565 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7566 g_assert (missing_value_field);
7568 obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7569 mono_error_assert_ok (&error);
7570 return obj;
7573 static MonoObject*
7574 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7576 if (!*dbnull)
7577 *dbnull = mono_get_dbnull_object (domain);
7578 return *dbnull;
7581 static MonoObject*
7582 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7584 if (!*reflection_missing)
7585 *reflection_missing = mono_get_reflection_missing_object (domain);
7586 return *reflection_missing;
7590 * mono_param_get_objects:
7591 * @domain: an app domain
7592 * @method: a method
7594 * Return an System.Reflection.ParameterInfo array object representing the parameters
7595 * in the method @method.
7597 MonoArray*
7598 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7600 static MonoClass *System_Reflection_ParameterInfo;
7601 static MonoClass *System_Reflection_ParameterInfo_array;
7602 MonoArray *res = NULL;
7603 MonoReflectionMethod *member = NULL;
7604 MonoReflectionParameter *param = NULL;
7605 char **names = NULL, **blobs = NULL;
7606 guint32 *types = NULL;
7607 MonoType *type = NULL;
7608 MonoObject *dbnull = NULL;
7609 MonoObject *missing = NULL;
7610 MonoMarshalSpec **mspecs = NULL;
7611 MonoMethodSignature *sig = NULL;
7612 MonoVTable *pinfo_vtable;
7613 MonoReflectionType *rt;
7614 int i;
7616 mono_error_init (error);
7618 if (!System_Reflection_ParameterInfo_array) {
7619 MonoClass *klass;
7621 klass = mono_class_get_mono_parameter_info_class ();
7623 mono_memory_barrier ();
7624 System_Reflection_ParameterInfo = klass;
7627 klass = mono_array_class_get (klass, 1);
7628 mono_memory_barrier ();
7629 System_Reflection_ParameterInfo_array = klass;
7632 sig = mono_method_signature_checked (method, error);
7633 if (!mono_error_ok (error))
7634 goto leave;
7636 if (!sig->param_count) {
7637 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7638 if (!res)
7639 goto leave;
7641 return res;
7644 /* Note: the cache is based on the address of the signature into the method
7645 * since we already cache MethodInfos with the method as keys.
7647 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7649 member = mono_method_get_object_checked (domain, method, refclass, error);
7650 if (!member)
7651 goto leave;
7652 names = g_new (char *, sig->param_count);
7653 mono_method_get_param_names (method, (const char **) names);
7655 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7656 mono_method_get_marshal_info (method, mspecs);
7658 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7659 if (!res)
7660 goto leave;
7662 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7663 for (i = 0; i < sig->param_count; ++i) {
7664 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7665 if (!param)
7666 goto leave;
7668 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7669 if (!rt)
7670 goto leave;
7672 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7674 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7676 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7678 param->PositionImpl = i;
7679 param->AttrsImpl = sig->params [i]->attrs;
7681 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7682 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7683 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7684 else
7685 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7686 } else {
7688 if (!blobs) {
7689 blobs = g_new0 (char *, sig->param_count);
7690 types = g_new0 (guint32, sig->param_count);
7691 get_default_param_value_blobs (method, blobs, types);
7694 /* Build MonoType for the type from the Constant Table */
7695 if (!type)
7696 type = g_new0 (MonoType, 1);
7697 type->type = (MonoTypeEnum)types [i];
7698 type->data.klass = NULL;
7699 if (types [i] == MONO_TYPE_CLASS)
7700 type->data.klass = mono_defaults.object_class;
7701 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7702 /* For enums, types [i] contains the base type */
7704 type->type = MONO_TYPE_VALUETYPE;
7705 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7706 } else
7707 type->data.klass = mono_class_from_mono_type (type);
7709 MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7710 if (!is_ok (error))
7711 goto leave;
7712 MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7714 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7715 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7716 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7717 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7718 else
7719 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7724 if (mspecs [i + 1]) {
7725 MonoReflectionMarshalAsAttribute* mobj;
7726 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7727 if (!mobj)
7728 goto leave;
7729 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7732 mono_array_setref (res, i, param);
7735 leave:
7736 g_free (names);
7737 g_free (blobs);
7738 g_free (types);
7739 g_free (type);
7741 if (sig) {
7742 for (i = sig->param_count; i >= 0; i--) {
7743 if (mspecs [i])
7744 mono_metadata_free_marshal_spec (mspecs [i]);
7747 g_free (mspecs);
7749 if (!is_ok (error))
7750 return NULL;
7752 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7755 MonoArray*
7756 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7758 MonoError error;
7759 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7760 mono_error_assert_ok (&error);
7761 return result;
7765 * mono_method_body_get_object:
7766 * @domain: an app domain
7767 * @method: a method
7769 * Return an System.Reflection.MethodBody object representing the method @method.
7771 MonoReflectionMethodBody*
7772 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7774 MonoError error;
7775 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7776 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7777 return result;
7781 * mono_method_body_get_object_checked:
7782 * @domain: an app domain
7783 * @method: a method
7784 * @error: set on error
7786 * Return an System.Reflection.MethodBody object representing the
7787 * method @method. On failure, returns NULL and sets @error.
7789 MonoReflectionMethodBody*
7790 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7792 MonoReflectionMethodBody *ret;
7793 MonoMethodHeader *header;
7794 MonoImage *image;
7795 MonoReflectionType *rt;
7796 guint32 method_rva, local_var_sig_token;
7797 char *ptr;
7798 unsigned char format, flags;
7799 int i;
7801 mono_error_init (error);
7803 /* for compatibility with .net */
7804 if (method_is_dynamic (method)) {
7805 mono_error_set_exception_instance (error, mono_get_exception_invalid_operation (NULL));
7806 return NULL;
7809 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7811 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7812 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7813 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7814 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7815 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7816 return NULL;
7818 image = method->klass->image;
7819 header = mono_method_get_header_checked (method, error);
7820 return_val_if_nok (error, NULL);
7822 if (!image_is_dynamic (image)) {
7823 /* Obtain local vars signature token */
7824 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7825 ptr = mono_image_rva_map (image, method_rva);
7826 flags = *(const unsigned char *) ptr;
7827 format = flags & METHOD_HEADER_FORMAT_MASK;
7828 switch (format){
7829 case METHOD_HEADER_TINY_FORMAT:
7830 local_var_sig_token = 0;
7831 break;
7832 case METHOD_HEADER_FAT_FORMAT:
7833 ptr += 2;
7834 ptr += 2;
7835 ptr += 4;
7836 local_var_sig_token = read32 (ptr);
7837 break;
7838 default:
7839 g_assert_not_reached ();
7841 } else
7842 local_var_sig_token = 0; //FIXME
7844 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7845 return_val_if_nok (error, NULL);
7847 ret->init_locals = header->init_locals;
7848 ret->max_stack = header->max_stack;
7849 ret->local_var_sig_token = local_var_sig_token;
7850 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7851 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7853 /* Locals */
7854 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7855 for (i = 0; i < header->num_locals; ++i) {
7856 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7857 return_val_if_nok (error, NULL);
7859 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7860 return_val_if_nok (error, NULL);
7862 MONO_OBJECT_SETREF (info, local_type, rt);
7864 info->is_pinned = header->locals [i]->pinned;
7865 info->local_index = i;
7866 mono_array_setref (ret->locals, i, info);
7869 /* Exceptions */
7870 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7871 for (i = 0; i < header->num_clauses; ++i) {
7872 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7873 return_val_if_nok (error, NULL);
7874 MonoExceptionClause *clause = &header->clauses [i];
7876 info->flags = clause->flags;
7877 info->try_offset = clause->try_offset;
7878 info->try_length = clause->try_len;
7879 info->handler_offset = clause->handler_offset;
7880 info->handler_length = clause->handler_len;
7881 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7882 info->filter_offset = clause->data.filter_offset;
7883 else if (clause->data.catch_class) {
7884 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7885 return_val_if_nok (error, NULL);
7887 MONO_OBJECT_SETREF (info, catch_type, rt);
7890 mono_array_setref (ret->clauses, i, info);
7893 mono_metadata_free_mh (header);
7894 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7895 return ret;
7899 * mono_get_dbnull_object:
7900 * @domain: Domain where the object lives
7902 * Returns the System.DBNull.Value singleton object
7904 * Used as the value for ParameterInfo.DefaultValue
7906 MonoObject *
7907 mono_get_dbnull_object (MonoDomain *domain)
7909 MonoError error;
7910 MonoObject *obj;
7911 static MonoClassField *dbnull_value_field = NULL;
7913 if (!dbnull_value_field) {
7914 MonoClass *dbnull_klass;
7915 dbnull_klass = mono_class_get_dbnull_class ();
7916 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7917 g_assert (dbnull_value_field);
7919 obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
7920 mono_error_assert_ok (&error);
7921 return obj;
7924 static void
7925 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7927 guint32 param_index, i, lastp, crow = 0;
7928 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7929 gint32 idx;
7931 MonoClass *klass = method->klass;
7932 MonoImage *image = klass->image;
7933 MonoMethodSignature *methodsig = mono_method_signature (method);
7935 MonoTableInfo *constt;
7936 MonoTableInfo *methodt;
7937 MonoTableInfo *paramt;
7939 if (!methodsig->param_count)
7940 return;
7942 mono_class_init (klass);
7944 if (image_is_dynamic (klass->image)) {
7945 MonoReflectionMethodAux *aux;
7946 if (method->is_inflated)
7947 method = ((MonoMethodInflated*)method)->declaring;
7948 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7949 if (aux && aux->param_defaults) {
7950 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7951 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7953 return;
7956 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7957 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7958 constt = &image->tables [MONO_TABLE_CONSTANT];
7960 idx = mono_method_get_index (method) - 1;
7961 g_assert (idx != -1);
7963 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7964 if (idx + 1 < methodt->rows)
7965 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7966 else
7967 lastp = paramt->rows + 1;
7969 for (i = param_index; i < lastp; ++i) {
7970 guint32 paramseq;
7972 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7973 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7975 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7976 continue;
7978 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7979 if (!crow) {
7980 continue;
7983 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7984 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7985 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7988 return;
7991 MonoObject *
7992 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
7994 void *retval;
7995 MonoClass *klass;
7996 MonoObject *object;
7997 MonoType *basetype = type;
7999 mono_error_init (error);
8001 if (!blob)
8002 return NULL;
8004 klass = mono_class_from_mono_type (type);
8005 if (klass->valuetype) {
8006 object = mono_object_new_checked (domain, klass, error);
8007 return_val_if_nok (error, NULL);
8008 retval = ((gchar *) object + sizeof (MonoObject));
8009 if (klass->enumtype)
8010 basetype = mono_class_enum_basetype (klass);
8011 } else {
8012 retval = &object;
8015 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
8016 return object;
8017 else
8018 return NULL;
8021 static int
8022 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8023 int found_sep;
8024 char *s;
8025 gboolean quoted = FALSE;
8027 memset (assembly, 0, sizeof (MonoAssemblyName));
8028 assembly->culture = "";
8029 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8031 if (*p == '"') {
8032 quoted = TRUE;
8033 p++;
8035 assembly->name = p;
8036 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8037 p++;
8038 if (quoted) {
8039 if (*p != '"')
8040 return 1;
8041 *p = 0;
8042 p++;
8044 if (*p != ',')
8045 return 1;
8046 *p = 0;
8047 /* Remove trailing whitespace */
8048 s = p - 1;
8049 while (*s && g_ascii_isspace (*s))
8050 *s-- = 0;
8051 p ++;
8052 while (g_ascii_isspace (*p))
8053 p++;
8054 while (*p) {
8055 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8056 p += 8;
8057 assembly->major = strtoul (p, &s, 10);
8058 if (s == p || *s != '.')
8059 return 1;
8060 p = ++s;
8061 assembly->minor = strtoul (p, &s, 10);
8062 if (s == p || *s != '.')
8063 return 1;
8064 p = ++s;
8065 assembly->build = strtoul (p, &s, 10);
8066 if (s == p || *s != '.')
8067 return 1;
8068 p = ++s;
8069 assembly->revision = strtoul (p, &s, 10);
8070 if (s == p)
8071 return 1;
8072 p = s;
8073 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8074 p += 8;
8075 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8076 assembly->culture = "";
8077 p += 7;
8078 } else {
8079 assembly->culture = p;
8080 while (*p && *p != ',') {
8081 p++;
8084 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8085 p += 15;
8086 if (strncmp (p, "null", 4) == 0) {
8087 p += 4;
8088 } else {
8089 int len;
8090 gchar *start = p;
8091 while (*p && *p != ',') {
8092 p++;
8094 len = (p - start + 1);
8095 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8096 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8097 g_strlcpy ((char*)assembly->public_key_token, start, len);
8099 } else {
8100 while (*p && *p != ',')
8101 p++;
8103 found_sep = 0;
8104 while (g_ascii_isspace (*p) || *p == ',') {
8105 *p++ = 0;
8106 found_sep = 1;
8107 continue;
8109 /* failed */
8110 if (!found_sep)
8111 return 1;
8114 return 0;
8118 * mono_reflection_parse_type:
8119 * @name: type name
8121 * Parse a type name as accepted by the GetType () method and output the info
8122 * extracted in the info structure.
8123 * the name param will be mangled, so, make a copy before passing it to this function.
8124 * The fields in info will be valid until the memory pointed to by name is valid.
8126 * See also mono_type_get_name () below.
8128 * Returns: 0 on parse error.
8130 static int
8131 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8132 MonoTypeNameParse *info)
8134 char *start, *p, *w, *last_point, *startn;
8135 int in_modifiers = 0;
8136 int isbyref = 0, rank = 0, isptr = 0;
8138 start = p = w = name;
8140 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8141 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8142 info->name = info->name_space = NULL;
8143 info->nested = NULL;
8144 info->modifiers = NULL;
8145 info->type_arguments = NULL;
8147 /* last_point separates the namespace from the name */
8148 last_point = NULL;
8149 /* Skips spaces */
8150 while (*p == ' ') p++, start++, w++, name++;
8152 while (*p) {
8153 switch (*p) {
8154 case '+':
8155 *p = 0; /* NULL terminate the name */
8156 startn = p + 1;
8157 info->nested = g_list_append (info->nested, startn);
8158 /* we have parsed the nesting namespace + name */
8159 if (info->name)
8160 break;
8161 if (last_point) {
8162 info->name_space = start;
8163 *last_point = 0;
8164 info->name = last_point + 1;
8165 } else {
8166 info->name_space = (char *)"";
8167 info->name = start;
8169 break;
8170 case '.':
8171 last_point = p;
8172 break;
8173 case '\\':
8174 ++p;
8175 break;
8176 case '&':
8177 case '*':
8178 case '[':
8179 case ',':
8180 case ']':
8181 in_modifiers = 1;
8182 break;
8183 default:
8184 break;
8186 if (in_modifiers)
8187 break;
8188 // *w++ = *p++;
8189 p++;
8192 if (!info->name) {
8193 if (last_point) {
8194 info->name_space = start;
8195 *last_point = 0;
8196 info->name = last_point + 1;
8197 } else {
8198 info->name_space = (char *)"";
8199 info->name = start;
8202 while (*p) {
8203 switch (*p) {
8204 case '&':
8205 if (isbyref) /* only one level allowed by the spec */
8206 return 0;
8207 isbyref = 1;
8208 isptr = 0;
8209 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8210 *p++ = 0;
8211 break;
8212 case '*':
8213 if (isbyref) /* pointer to ref not okay */
8214 return 0;
8215 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8216 isptr = 1;
8217 *p++ = 0;
8218 break;
8219 case '[':
8220 if (isbyref) /* array of ref and generic ref are not okay */
8221 return 0;
8222 //Decide if it's an array of a generic argument list
8223 *p++ = 0;
8225 if (!*p) //XXX test
8226 return 0;
8227 if (*p == ',' || *p == '*' || *p == ']') { //array
8228 isptr = 0;
8229 rank = 1;
8230 while (*p) {
8231 if (*p == ']')
8232 break;
8233 if (*p == ',')
8234 rank++;
8235 else if (*p == '*') /* '*' means unknown lower bound */
8236 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8237 else
8238 return 0;
8239 ++p;
8241 if (*p++ != ']')
8242 return 0;
8243 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8244 } else {
8245 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8246 return 0;
8247 isptr = 0;
8248 info->type_arguments = g_ptr_array_new ();
8249 while (*p) {
8250 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8251 gboolean fqname = FALSE;
8253 g_ptr_array_add (info->type_arguments, subinfo);
8255 while (*p == ' ') p++;
8256 if (*p == '[') {
8257 p++;
8258 fqname = TRUE;
8261 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8262 return 0;
8264 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8265 if (fqname && (*p != ']')) {
8266 char *aname;
8268 if (*p != ',')
8269 return 0;
8270 *p++ = 0;
8272 aname = p;
8273 while (*p && (*p != ']'))
8274 p++;
8276 if (*p != ']')
8277 return 0;
8279 *p++ = 0;
8280 while (*aname) {
8281 if (g_ascii_isspace (*aname)) {
8282 ++aname;
8283 continue;
8285 break;
8287 if (!*aname ||
8288 !assembly_name_to_aname (&subinfo->assembly, aname))
8289 return 0;
8290 } else if (fqname && (*p == ']')) {
8291 *p++ = 0;
8293 if (*p == ']') {
8294 *p++ = 0;
8295 break;
8296 } else if (!*p) {
8297 return 0;
8299 *p++ = 0;
8302 break;
8303 case ']':
8304 if (is_recursed)
8305 goto end;
8306 return 0;
8307 case ',':
8308 if (is_recursed)
8309 goto end;
8310 *p++ = 0;
8311 while (*p) {
8312 if (g_ascii_isspace (*p)) {
8313 ++p;
8314 continue;
8316 break;
8318 if (!*p)
8319 return 0; /* missing assembly name */
8320 if (!assembly_name_to_aname (&info->assembly, p))
8321 return 0;
8322 break;
8323 default:
8324 return 0;
8326 if (info->assembly.name)
8327 break;
8329 // *w = 0; /* terminate class name */
8330 end:
8331 if (!info->name || !*info->name)
8332 return 0;
8333 if (endptr)
8334 *endptr = p;
8335 /* add other consistency checks */
8336 return 1;
8341 * mono_identifier_unescape_type_name_chars:
8342 * @identifier: the display name of a mono type
8344 * Returns:
8345 * The name in internal form, that is without escaping backslashes.
8347 * The string is modified in place!
8349 char*
8350 mono_identifier_unescape_type_name_chars(char* identifier)
8352 char *w, *r;
8353 if (!identifier)
8354 return NULL;
8355 for (w = r = identifier; *r != 0; r++)
8357 char c = *r;
8358 if (c == '\\') {
8359 r++;
8360 if (*r == 0)
8361 break;
8362 c = *r;
8364 *w = c;
8365 w++;
8367 if (w != r)
8368 *w = 0;
8369 return identifier;
8372 void
8373 mono_identifier_unescape_info (MonoTypeNameParse* info);
8375 static void
8376 unescape_each_type_argument(void* data, void* user_data)
8378 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8379 mono_identifier_unescape_info (info);
8382 static void
8383 unescape_each_nested_name (void* data, void* user_data)
8385 char* nested_name = (char*) data;
8386 mono_identifier_unescape_type_name_chars(nested_name);
8390 * mono_identifier_unescape_info:
8392 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8394 * Returns: nothing.
8396 * Destructively updates the info by unescaping the identifiers that
8397 * comprise the type namespace, name, nested types (if any) and
8398 * generic type arguments (if any).
8400 * The resulting info has the names in internal form.
8403 void
8404 mono_identifier_unescape_info (MonoTypeNameParse *info)
8406 if (!info)
8407 return;
8408 mono_identifier_unescape_type_name_chars(info->name_space);
8409 mono_identifier_unescape_type_name_chars(info->name);
8410 // but don't escape info->assembly
8411 if (info->type_arguments)
8412 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8413 if (info->nested)
8414 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8418 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8420 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8421 if (ok) {
8422 mono_identifier_unescape_info (info);
8424 return ok;
8427 static MonoType*
8428 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8430 gboolean type_resolve = FALSE;
8431 MonoType *type;
8432 MonoImage *rootimage = image;
8434 mono_error_init (error);
8436 if (info->assembly.name) {
8437 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8438 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8440 * This could happen in the AOT compiler case when the search hook is not
8441 * installed.
8443 assembly = image->assembly;
8444 if (!assembly) {
8445 /* then we must load the assembly ourselve - see #60439 */
8446 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8447 if (!assembly)
8448 return NULL;
8450 image = assembly->image;
8451 } else if (!image) {
8452 image = mono_defaults.corlib;
8455 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8456 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8457 mono_error_cleanup (error);
8458 image = mono_defaults.corlib;
8459 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8462 return type;
8466 * mono_reflection_get_type_internal:
8468 * Returns: may return NULL on success, sets error on failure.
8470 static MonoType*
8471 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8473 MonoClass *klass;
8474 GList *mod;
8475 int modval;
8476 gboolean bounded = FALSE;
8478 mono_error_init (error);
8479 if (!image)
8480 image = mono_defaults.corlib;
8482 if (!rootimage)
8483 rootimage = mono_defaults.corlib;
8485 if (ignorecase)
8486 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8487 else
8488 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8490 if (!klass)
8491 return NULL;
8493 for (mod = info->nested; mod; mod = mod->next) {
8494 gpointer iter = NULL;
8495 MonoClass *parent;
8497 parent = klass;
8498 mono_class_init (parent);
8500 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8501 char *lastp;
8502 char *nested_name, *nested_nspace;
8503 gboolean match = TRUE;
8505 lastp = strrchr ((const char *)mod->data, '.');
8506 if (lastp) {
8507 /* Nested classes can have namespaces */
8508 int nspace_len;
8510 nested_name = g_strdup (lastp + 1);
8511 nspace_len = lastp - (char*)mod->data;
8512 nested_nspace = (char *)g_malloc (nspace_len + 1);
8513 memcpy (nested_nspace, mod->data, nspace_len);
8514 nested_nspace [nspace_len] = '\0';
8516 } else {
8517 nested_name = (char *)mod->data;
8518 nested_nspace = NULL;
8521 if (nested_nspace) {
8522 if (ignorecase) {
8523 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8524 match = FALSE;
8525 } else {
8526 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8527 match = FALSE;
8530 if (match) {
8531 if (ignorecase) {
8532 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8533 match = FALSE;
8534 } else {
8535 if (strcmp (klass->name, nested_name) != 0)
8536 match = FALSE;
8539 if (lastp) {
8540 g_free (nested_name);
8541 g_free (nested_nspace);
8543 if (match)
8544 break;
8547 if (!klass)
8548 break;
8550 if (!klass)
8551 return NULL;
8553 if (info->type_arguments) {
8554 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8555 MonoReflectionType *the_type;
8556 MonoType *instance;
8557 int i;
8559 for (i = 0; i < info->type_arguments->len; i++) {
8560 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8562 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8563 if (!type_args [i]) {
8564 g_free (type_args);
8565 return NULL;
8569 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8570 if (!the_type)
8571 return NULL;
8573 instance = mono_reflection_bind_generic_parameters (
8574 the_type, info->type_arguments->len, type_args, error);
8576 g_free (type_args);
8577 if (!instance)
8578 return NULL;
8580 klass = mono_class_from_mono_type (instance);
8583 for (mod = info->modifiers; mod; mod = mod->next) {
8584 modval = GPOINTER_TO_UINT (mod->data);
8585 if (!modval) { /* byref: must be last modifier */
8586 return &klass->this_arg;
8587 } else if (modval == -1) {
8588 klass = mono_ptr_class_get (&klass->byval_arg);
8589 } else if (modval == -2) {
8590 bounded = TRUE;
8591 } else { /* array rank */
8592 klass = mono_bounded_array_class_get (klass, modval, bounded);
8596 return &klass->byval_arg;
8600 * mono_reflection_get_type:
8601 * @image: a metadata context
8602 * @info: type description structure
8603 * @ignorecase: flag for case-insensitive string compares
8604 * @type_resolve: whenever type resolve was already tried
8606 * Build a MonoType from the type description in @info.
8610 MonoType*
8611 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8612 MonoError error;
8613 MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8614 mono_error_cleanup (&error);
8615 return result;
8619 * mono_reflection_get_type_checked:
8620 * @image: a metadata context
8621 * @info: type description structure
8622 * @ignorecase: flag for case-insensitive string compares
8623 * @type_resolve: whenever type resolve was already tried
8624 * @error: set on error.
8626 * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8629 MonoType*
8630 mono_reflection_get_type_checked (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8631 mono_error_init (error);
8632 return mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, error);
8636 static MonoType*
8637 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8639 MonoReflectionAssemblyBuilder *abuilder;
8640 MonoType *type;
8641 int i;
8643 mono_error_init (error);
8644 g_assert (assembly_is_dynamic (assembly));
8645 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8646 if (!abuilder)
8647 return NULL;
8649 /* Enumerate all modules */
8651 type = NULL;
8652 if (abuilder->modules) {
8653 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8654 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8655 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8656 if (type)
8657 break;
8658 if (!mono_error_ok (error))
8659 return NULL;
8663 if (!type && abuilder->loaded_modules) {
8664 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8665 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8666 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8667 if (type)
8668 break;
8669 if (!mono_error_ok (error))
8670 return NULL;
8674 return type;
8677 MonoType*
8678 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8680 MonoType *type;
8681 MonoReflectionAssembly *assembly;
8682 GString *fullName;
8683 GList *mod;
8685 mono_error_init (error);
8687 if (image && image_is_dynamic (image))
8688 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8689 else {
8690 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8692 return_val_if_nok (error, NULL);
8694 if (type)
8695 return type;
8696 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8697 return NULL;
8699 if (type_resolve) {
8700 if (*type_resolve)
8701 return NULL;
8702 else
8703 *type_resolve = TRUE;
8706 /* Reconstruct the type name */
8707 fullName = g_string_new ("");
8708 if (info->name_space && (info->name_space [0] != '\0'))
8709 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8710 else
8711 g_string_printf (fullName, "%s", info->name);
8712 for (mod = info->nested; mod; mod = mod->next)
8713 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8715 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8716 if (!is_ok (error)) {
8717 g_string_free (fullName, TRUE);
8718 return NULL;
8721 if (assembly) {
8722 if (assembly_is_dynamic (assembly->assembly))
8723 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8724 info, ignorecase, error);
8725 else
8726 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8727 info, ignorecase, error);
8729 g_string_free (fullName, TRUE);
8730 return_val_if_nok (error, NULL);
8731 return type;
8734 void
8735 mono_reflection_free_type_info (MonoTypeNameParse *info)
8737 g_list_free (info->modifiers);
8738 g_list_free (info->nested);
8740 if (info->type_arguments) {
8741 int i;
8743 for (i = 0; i < info->type_arguments->len; i++) {
8744 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8746 mono_reflection_free_type_info (subinfo);
8747 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8748 g_free (subinfo);
8751 g_ptr_array_free (info->type_arguments, TRUE);
8756 * mono_reflection_type_from_name:
8757 * @name: type name.
8758 * @image: a metadata context (can be NULL).
8760 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8761 * it defaults to get the type from @image or, if @image is NULL or loading
8762 * from it fails, uses corlib.
8765 MonoType*
8766 mono_reflection_type_from_name (char *name, MonoImage *image)
8768 MonoError error;
8769 MonoType *result = mono_reflection_type_from_name_checked (name, image, &error);
8770 mono_error_cleanup (&error);
8771 return result;
8775 * mono_reflection_type_from_name_checked:
8776 * @name: type name.
8777 * @image: a metadata context (can be NULL).
8778 * @error: set on errror.
8780 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8781 * it defaults to get the type from @image or, if @image is NULL or loading
8782 * from it fails, uses corlib. On failure returns NULL and sets @error.
8785 MonoType*
8786 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8788 MonoType *type = NULL;
8789 MonoTypeNameParse info;
8790 char *tmp;
8792 mono_error_init (error);
8793 /* Make a copy since parse_type modifies its argument */
8794 tmp = g_strdup (name);
8796 /*g_print ("requested type %s\n", str);*/
8797 if (mono_reflection_parse_type (tmp, &info)) {
8798 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8799 if (!is_ok (error)) {
8800 g_free (tmp);
8801 mono_reflection_free_type_info (&info);
8802 return NULL;
8806 g_free (tmp);
8807 mono_reflection_free_type_info (&info);
8808 return type;
8812 * mono_reflection_get_token:
8814 * Return the metadata token of OBJ which should be an object
8815 * representing a metadata element.
8817 guint32
8818 mono_reflection_get_token (MonoObject *obj)
8820 MonoError error;
8821 guint32 result = mono_reflection_get_token_checked (obj, &error);
8822 mono_error_assert_ok (&error);
8823 return result;
8827 * mono_reflection_get_token_checked:
8828 * @obj: the object
8829 * @error: set on error
8831 * Return the metadata token of @obj which should be an object
8832 * representing a metadata element. On failure sets @error.
8834 guint32
8835 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8837 MonoClass *klass;
8838 guint32 token = 0;
8840 mono_error_init (error);
8842 klass = obj->vtable->klass;
8844 if (strcmp (klass->name, "MethodBuilder") == 0) {
8845 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8847 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8848 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8849 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8851 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8852 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8853 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8855 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8856 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8857 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8858 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8859 } else if (strcmp (klass->name, "MonoType") == 0) {
8860 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8861 return_val_if_nok (error, 0);
8862 MonoClass *mc = mono_class_from_mono_type (type);
8863 if (!mono_class_init (mc)) {
8864 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8865 return 0;
8868 token = mc->type_token;
8869 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8870 strcmp (klass->name, "MonoMethod") == 0 ||
8871 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8872 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8873 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8874 if (m->method->is_inflated) {
8875 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8876 return inflated->declaring->token;
8877 } else {
8878 token = m->method->token;
8880 } else if (strcmp (klass->name, "MonoField") == 0) {
8881 MonoReflectionField *f = (MonoReflectionField*)obj;
8883 if (is_field_on_inst (f->field)) {
8884 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8886 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8887 int field_index = f->field - dgclass->fields;
8888 MonoObject *obj;
8890 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8891 obj = dgclass->field_objects [field_index];
8892 return mono_reflection_get_token_checked (obj, error);
8895 token = mono_class_get_field_token (f->field);
8896 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8897 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8899 token = mono_class_get_property_token (p->property);
8900 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8901 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8903 token = mono_class_get_event_token (p->event);
8904 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8905 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8906 MonoClass *member_class = mono_object_class (p->MemberImpl);
8907 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8909 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8910 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8911 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8913 token = m->token;
8914 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8915 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8916 } else {
8917 mono_error_set_generic_error (error, "System", "NotImplementedException",
8918 "MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8919 return 0;
8922 return token;
8925 static MonoClass*
8926 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8928 char *n;
8929 MonoType *t;
8930 int slen = mono_metadata_decode_value (p, &p);
8932 mono_error_init (error);
8934 n = (char *)g_memdup (p, slen + 1);
8935 n [slen] = 0;
8936 t = mono_reflection_type_from_name_checked (n, image, error);
8937 if (!t) {
8938 char *msg = g_strdup (mono_error_get_message (error));
8939 mono_error_cleanup (error);
8940 /* We don't free n, it's consumed by mono_error */
8941 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8942 g_free (msg);
8943 return NULL;
8945 g_free (n);
8946 p += slen;
8947 *end = p;
8948 return mono_class_from_mono_type (t);
8951 static void*
8952 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8954 int slen, type = t->type;
8955 MonoClass *tklass = t->data.klass;
8957 mono_error_init (error);
8959 handle_enum:
8960 switch (type) {
8961 case MONO_TYPE_U1:
8962 case MONO_TYPE_I1:
8963 case MONO_TYPE_BOOLEAN: {
8964 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8965 *bval = *p;
8966 *end = p + 1;
8967 return bval;
8969 case MONO_TYPE_CHAR:
8970 case MONO_TYPE_U2:
8971 case MONO_TYPE_I2: {
8972 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8973 *val = read16 (p);
8974 *end = p + 2;
8975 return val;
8977 #if SIZEOF_VOID_P == 4
8978 case MONO_TYPE_U:
8979 case MONO_TYPE_I:
8980 #endif
8981 case MONO_TYPE_R4:
8982 case MONO_TYPE_U4:
8983 case MONO_TYPE_I4: {
8984 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8985 *val = read32 (p);
8986 *end = p + 4;
8987 return val;
8989 #if SIZEOF_VOID_P == 8
8990 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8991 case MONO_TYPE_I:
8992 #endif
8993 case MONO_TYPE_U8:
8994 case MONO_TYPE_I8: {
8995 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8996 *val = read64 (p);
8997 *end = p + 8;
8998 return val;
9000 case MONO_TYPE_R8: {
9001 double *val = (double *)g_malloc (sizeof (double));
9002 readr8 (p, val);
9003 *end = p + 8;
9004 return val;
9006 case MONO_TYPE_VALUETYPE:
9007 if (t->data.klass->enumtype) {
9008 type = mono_class_enum_basetype (t->data.klass)->type;
9009 goto handle_enum;
9010 } else {
9011 MonoClass *k = t->data.klass;
9013 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9014 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9015 *val = read64 (p);
9016 *end = p + 8;
9017 return val;
9020 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9021 break;
9023 case MONO_TYPE_STRING:
9024 if (*p == (char)0xFF) {
9025 *end = p + 1;
9026 return NULL;
9028 slen = mono_metadata_decode_value (p, &p);
9029 *end = p + slen;
9030 return mono_string_new_len (mono_domain_get (), p, slen);
9031 case MONO_TYPE_CLASS: {
9032 MonoReflectionType *rt;
9033 char *n;
9034 MonoType *t;
9035 if (*p == (char)0xFF) {
9036 *end = p + 1;
9037 return NULL;
9039 handle_type:
9040 slen = mono_metadata_decode_value (p, &p);
9041 n = (char *)g_memdup (p, slen + 1);
9042 n [slen] = 0;
9043 t = mono_reflection_type_from_name_checked (n, image, error);
9044 if (!t) {
9045 char *msg = g_strdup (mono_error_get_message (error));
9046 mono_error_cleanup (error);
9047 /* We don't free n, it's consumed by mono_error */
9048 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
9049 g_free (msg);
9050 return NULL;
9052 g_free (n);
9053 *end = p + slen;
9055 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9056 if (!mono_error_ok (error))
9057 return NULL;
9059 return rt;
9061 case MONO_TYPE_OBJECT: {
9062 char subt = *p++;
9063 MonoObject *obj;
9064 MonoClass *subc = NULL;
9065 void *val;
9067 if (subt == 0x50) {
9068 goto handle_type;
9069 } else if (subt == 0x0E) {
9070 type = MONO_TYPE_STRING;
9071 goto handle_enum;
9072 } else if (subt == 0x1D) {
9073 MonoType simple_type = {{0}};
9074 int etype = *p;
9075 p ++;
9077 type = MONO_TYPE_SZARRAY;
9078 if (etype == 0x50) {
9079 tklass = mono_defaults.systemtype_class;
9080 } else if (etype == 0x55) {
9081 tklass = load_cattr_enum_type (image, p, &p, error);
9082 if (!mono_error_ok (error))
9083 return NULL;
9084 } else {
9085 if (etype == 0x51)
9086 /* See Partition II, Appendix B3 */
9087 etype = MONO_TYPE_OBJECT;
9088 simple_type.type = (MonoTypeEnum)etype;
9089 tklass = mono_class_from_mono_type (&simple_type);
9091 goto handle_enum;
9092 } else if (subt == 0x55) {
9093 char *n;
9094 MonoType *t;
9095 slen = mono_metadata_decode_value (p, &p);
9096 n = (char *)g_memdup (p, slen + 1);
9097 n [slen] = 0;
9098 t = mono_reflection_type_from_name_checked (n, image, error);
9099 if (!t) {
9100 char *msg = g_strdup (mono_error_get_message (error));
9101 mono_error_cleanup (error);
9102 /* We don't free n, it's consumed by mono_error */
9103 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
9104 g_free (msg);
9105 return NULL;
9107 g_free (n);
9108 p += slen;
9109 subc = mono_class_from_mono_type (t);
9110 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9111 MonoType simple_type = {{0}};
9112 simple_type.type = (MonoTypeEnum)subt;
9113 subc = mono_class_from_mono_type (&simple_type);
9114 } else {
9115 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9117 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9118 obj = NULL;
9119 if (mono_error_ok (error)) {
9120 obj = mono_object_new_checked (mono_domain_get (), subc, error);
9121 g_assert (!subc->has_references);
9122 if (mono_error_ok (error))
9123 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9126 g_free (val);
9127 return obj;
9129 case MONO_TYPE_SZARRAY: {
9130 MonoArray *arr;
9131 guint32 i, alen, basetype;
9132 alen = read32 (p);
9133 p += 4;
9134 if (alen == 0xffffffff) {
9135 *end = p;
9136 return NULL;
9138 arr = mono_array_new (mono_domain_get(), tklass, alen);
9139 basetype = tklass->byval_arg.type;
9140 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9141 basetype = mono_class_enum_basetype (tklass)->type;
9142 switch (basetype)
9144 case MONO_TYPE_U1:
9145 case MONO_TYPE_I1:
9146 case MONO_TYPE_BOOLEAN:
9147 for (i = 0; i < alen; i++) {
9148 MonoBoolean val = *p++;
9149 mono_array_set (arr, MonoBoolean, i, val);
9151 break;
9152 case MONO_TYPE_CHAR:
9153 case MONO_TYPE_U2:
9154 case MONO_TYPE_I2:
9155 for (i = 0; i < alen; i++) {
9156 guint16 val = read16 (p);
9157 mono_array_set (arr, guint16, i, val);
9158 p += 2;
9160 break;
9161 case MONO_TYPE_R4:
9162 case MONO_TYPE_U4:
9163 case MONO_TYPE_I4:
9164 for (i = 0; i < alen; i++) {
9165 guint32 val = read32 (p);
9166 mono_array_set (arr, guint32, i, val);
9167 p += 4;
9169 break;
9170 case MONO_TYPE_R8:
9171 for (i = 0; i < alen; i++) {
9172 double val;
9173 readr8 (p, &val);
9174 mono_array_set (arr, double, i, val);
9175 p += 8;
9177 break;
9178 case MONO_TYPE_U8:
9179 case MONO_TYPE_I8:
9180 for (i = 0; i < alen; i++) {
9181 guint64 val = read64 (p);
9182 mono_array_set (arr, guint64, i, val);
9183 p += 8;
9185 break;
9186 case MONO_TYPE_CLASS:
9187 case MONO_TYPE_OBJECT:
9188 case MONO_TYPE_STRING:
9189 case MONO_TYPE_SZARRAY:
9190 for (i = 0; i < alen; i++) {
9191 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9192 if (!mono_error_ok (error))
9193 return NULL;
9194 mono_array_setref (arr, i, item);
9196 break;
9197 default:
9198 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9200 *end=p;
9201 return arr;
9203 default:
9204 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9206 return NULL;
9209 static MonoObject*
9210 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9212 static MonoMethod *ctor;
9213 MonoObject *retval;
9214 void *params [2], *unboxed;
9216 mono_error_init (error);
9218 if (!ctor)
9219 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9221 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9222 return_val_if_nok (error, NULL);
9224 params [1] = val;
9225 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9226 return_val_if_nok (error, NULL);
9227 unboxed = mono_object_unbox (retval);
9229 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9230 return_val_if_nok (error, NULL);
9232 return retval;
9235 static MonoObject*
9236 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9238 static MonoMethod *ctor;
9239 MonoObject *retval;
9240 void *unboxed, *params [2];
9242 mono_error_init (error);
9244 if (!ctor)
9245 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9247 params [0] = minfo;
9248 params [1] = typedarg;
9249 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9250 return_val_if_nok (error, NULL);
9252 unboxed = mono_object_unbox (retval);
9254 mono_runtime_invoke_checked (ctor, unboxed, params, error);
9255 return_val_if_nok (error, NULL);
9257 return retval;
9260 static gboolean
9261 type_is_reference (MonoType *type)
9263 switch (type->type) {
9264 case MONO_TYPE_BOOLEAN:
9265 case MONO_TYPE_CHAR:
9266 case MONO_TYPE_U:
9267 case MONO_TYPE_I:
9268 case MONO_TYPE_U1:
9269 case MONO_TYPE_I1:
9270 case MONO_TYPE_U2:
9271 case MONO_TYPE_I2:
9272 case MONO_TYPE_U4:
9273 case MONO_TYPE_I4:
9274 case MONO_TYPE_U8:
9275 case MONO_TYPE_I8:
9276 case MONO_TYPE_R8:
9277 case MONO_TYPE_R4:
9278 case MONO_TYPE_VALUETYPE:
9279 return FALSE;
9280 default:
9281 return TRUE;
9285 static void
9286 free_param_data (MonoMethodSignature *sig, void **params) {
9287 int i;
9288 for (i = 0; i < sig->param_count; ++i) {
9289 if (!type_is_reference (sig->params [i]))
9290 g_free (params [i]);
9295 * Find the field index in the metadata FieldDef table.
9297 static guint32
9298 find_field_index (MonoClass *klass, MonoClassField *field) {
9299 int i;
9301 for (i = 0; i < klass->field.count; ++i) {
9302 if (field == &klass->fields [i])
9303 return klass->field.first + 1 + i;
9305 return 0;
9309 * Find the property index in the metadata Property table.
9311 static guint32
9312 find_property_index (MonoClass *klass, MonoProperty *property) {
9313 int i;
9315 for (i = 0; i < klass->ext->property.count; ++i) {
9316 if (property == &klass->ext->properties [i])
9317 return klass->ext->property.first + 1 + i;
9319 return 0;
9323 * Find the event index in the metadata Event table.
9325 static guint32
9326 find_event_index (MonoClass *klass, MonoEvent *event) {
9327 int i;
9329 for (i = 0; i < klass->ext->event.count; ++i) {
9330 if (event == &klass->ext->events [i])
9331 return klass->ext->event.first + 1 + i;
9333 return 0;
9336 static MonoObject*
9337 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9339 const char *p = (const char*)data;
9340 const char *named;
9341 guint32 i, j, num_named;
9342 MonoObject *attr;
9343 void *params_buf [32];
9344 void **params = NULL;
9345 MonoMethodSignature *sig;
9346 MonoObject *exc = NULL;
9348 mono_error_init (error);
9350 mono_class_init (method->klass);
9352 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9353 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9354 return NULL;
9357 if (len == 0) {
9358 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9359 if (!mono_error_ok (error)) return NULL;
9361 mono_runtime_invoke_checked (method, attr, NULL, error);
9362 if (!mono_error_ok (error))
9363 return NULL;
9365 return attr;
9368 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9369 return NULL;
9371 /*g_print ("got attr %s\n", method->klass->name);*/
9373 sig = mono_method_signature (method);
9374 if (sig->param_count < 32) {
9375 params = params_buf;
9376 memset (params, 0, sizeof (void*) * sig->param_count);
9377 } else {
9378 /* Allocate using GC so it gets GC tracking */
9379 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9382 /* skip prolog */
9383 p += 2;
9384 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9385 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9386 if (!mono_error_ok (error))
9387 goto fail;
9390 named = p;
9391 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9392 if (!mono_error_ok (error)) goto fail;
9394 mono_runtime_try_invoke (method, attr, params, &exc, error);
9395 if (!mono_error_ok (error))
9396 goto fail;
9397 if (exc)
9398 goto fail;
9400 num_named = read16 (named);
9401 named += 2;
9402 for (j = 0; j < num_named; j++) {
9403 gint name_len;
9404 char *name, named_type, data_type;
9405 named_type = *named++;
9406 data_type = *named++; /* type of data */
9407 if (data_type == MONO_TYPE_SZARRAY)
9408 data_type = *named++;
9409 if (data_type == MONO_TYPE_ENUM) {
9410 gint type_len;
9411 char *type_name;
9412 type_len = mono_metadata_decode_blob_size (named, &named);
9413 type_name = (char *)g_malloc (type_len + 1);
9414 memcpy (type_name, named, type_len);
9415 type_name [type_len] = 0;
9416 named += type_len;
9417 /* FIXME: lookup the type and check type consistency */
9418 g_free (type_name);
9420 name_len = mono_metadata_decode_blob_size (named, &named);
9421 name = (char *)g_malloc (name_len + 1);
9422 memcpy (name, named, name_len);
9423 name [name_len] = 0;
9424 named += name_len;
9425 if (named_type == 0x53) {
9426 MonoClassField *field;
9427 void *val;
9429 /* how this fail is a blackbox */
9430 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9431 if (!field) {
9432 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9433 g_free (name);
9434 goto fail;
9437 val = load_cattr_value (image, field->type, named, &named, error);
9438 if (!mono_error_ok (error)) {
9439 g_free (name);
9440 if (!type_is_reference (field->type))
9441 g_free (val);
9442 goto fail;
9445 mono_field_set_value (attr, field, val);
9446 if (!type_is_reference (field->type))
9447 g_free (val);
9448 } else if (named_type == 0x54) {
9449 MonoProperty *prop;
9450 void *pparams [1];
9451 MonoType *prop_type;
9453 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9455 if (!prop) {
9456 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9457 g_free (name);
9458 goto fail;
9461 if (!prop->set) {
9462 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9463 g_free (name);
9464 goto fail;
9467 /* can we have more that 1 arg in a custom attr named property? */
9468 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9469 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9471 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9472 if (!mono_error_ok (error)) {
9473 g_free (name);
9474 if (!type_is_reference (prop_type))
9475 g_free (pparams [0]);
9476 goto fail;
9480 mono_property_set_value (prop, attr, pparams, NULL);
9481 if (!type_is_reference (prop_type))
9482 g_free (pparams [0]);
9484 g_free (name);
9487 free_param_data (method->signature, params);
9488 if (params != params_buf)
9489 mono_gc_free_fixed (params);
9491 return attr;
9493 fail:
9494 free_param_data (method->signature, params);
9495 if (params != params_buf)
9496 mono_gc_free_fixed (params);
9497 if (exc)
9498 mono_raise_exception ((MonoException*)exc);
9499 return NULL;
9503 * mono_reflection_create_custom_attr_data_args:
9505 * Create an array of typed and named arguments from the cattr blob given by DATA.
9506 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9507 * NAMED_ARG_INFO will contain information about the named arguments.
9509 void
9510 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)
9512 MonoArray *typedargs, *namedargs;
9513 MonoClass *attrklass;
9514 MonoDomain *domain;
9515 const char *p = (const char*)data;
9516 const char *named;
9517 guint32 i, j, num_named;
9518 CattrNamedArg *arginfo = NULL;
9520 *typed_args = NULL;
9521 *named_args = NULL;
9522 *named_arg_info = NULL;
9524 mono_error_init (error);
9526 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9527 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9528 return;
9531 mono_class_init (method->klass);
9533 domain = mono_domain_get ();
9535 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9536 return;
9538 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9540 /* skip prolog */
9541 p += 2;
9542 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9543 MonoObject *obj;
9544 void *val;
9546 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9547 if (!mono_error_ok (error)) {
9548 if (!type_is_reference (mono_method_signature (method)->params [i]))
9549 g_free (val);
9550 return;
9553 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9554 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9555 mono_array_setref (typedargs, i, obj);
9557 if (!type_is_reference (mono_method_signature (method)->params [i]))
9558 g_free (val);
9561 named = p;
9562 num_named = read16 (named);
9563 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9564 named += 2;
9565 attrklass = method->klass;
9567 arginfo = g_new0 (CattrNamedArg, num_named);
9568 *named_arg_info = arginfo;
9570 for (j = 0; j < num_named; j++) {
9571 gint name_len;
9572 char *name, named_type, data_type;
9573 named_type = *named++;
9574 data_type = *named++; /* type of data */
9575 if (data_type == MONO_TYPE_SZARRAY)
9576 data_type = *named++;
9577 if (data_type == MONO_TYPE_ENUM) {
9578 gint type_len;
9579 char *type_name;
9580 type_len = mono_metadata_decode_blob_size (named, &named);
9581 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9582 goto fail;
9584 type_name = (char *)g_malloc (type_len + 1);
9585 memcpy (type_name, named, type_len);
9586 type_name [type_len] = 0;
9587 named += type_len;
9588 /* FIXME: lookup the type and check type consistency */
9589 g_free (type_name);
9591 name_len = mono_metadata_decode_blob_size (named, &named);
9592 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9593 goto fail;
9594 name = (char *)g_malloc (name_len + 1);
9595 memcpy (name, named, name_len);
9596 name [name_len] = 0;
9597 named += name_len;
9598 if (named_type == 0x53) {
9599 MonoObject *obj;
9600 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9601 void *val;
9603 if (!field) {
9604 g_free (name);
9605 goto fail;
9608 arginfo [j].type = field->type;
9609 arginfo [j].field = field;
9611 val = load_cattr_value (image, field->type, named, &named, error);
9612 if (!mono_error_ok (error)) {
9613 if (!type_is_reference (field->type))
9614 g_free (val);
9615 g_free (name);
9616 return;
9619 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9620 mono_array_setref (namedargs, j, obj);
9621 if (!type_is_reference (field->type))
9622 g_free (val);
9623 } else if (named_type == 0x54) {
9624 MonoObject *obj;
9625 MonoType *prop_type;
9626 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9627 void *val;
9629 if (!prop || !prop->set) {
9630 g_free (name);
9631 goto fail;
9634 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9635 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9637 arginfo [j].type = prop_type;
9638 arginfo [j].prop = prop;
9640 val = load_cattr_value (image, prop_type, named, &named, error);
9641 if (!mono_error_ok (error)) {
9642 if (!type_is_reference (prop_type))
9643 g_free (val);
9644 g_free (name);
9645 return;
9648 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9649 mono_array_setref (namedargs, j, obj);
9650 if (!type_is_reference (prop_type))
9651 g_free (val);
9653 g_free (name);
9656 *typed_args = typedargs;
9657 *named_args = namedargs;
9658 return;
9659 fail:
9660 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9661 g_free (arginfo);
9662 *named_arg_info = NULL;
9665 void
9666 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9668 MonoDomain *domain;
9669 MonoArray *typedargs, *namedargs;
9670 MonoImage *image;
9671 MonoMethod *method;
9672 CattrNamedArg *arginfo = NULL;
9673 MonoError error;
9674 int i;
9676 mono_error_init (&error);
9678 *ctor_args = NULL;
9679 *named_args = NULL;
9681 if (len == 0)
9682 return;
9684 image = assembly->assembly->image;
9685 method = ref_method->method;
9686 domain = mono_object_domain (ref_method);
9688 if (!mono_class_init (method->klass))
9689 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9691 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9692 if (!mono_error_ok (&error))
9693 goto leave;
9695 if (mono_loader_get_last_error ()) {
9696 mono_error_set_from_loader_error (&error);
9697 goto leave;
9700 if (!typedargs || !namedargs)
9701 goto leave;
9703 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9704 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9705 MonoObject *typedarg;
9707 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9708 if (!is_ok (&error))
9709 goto leave;
9710 mono_array_setref (typedargs, i, typedarg);
9713 for (i = 0; i < mono_array_length (namedargs); ++i) {
9714 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9715 MonoObject *typedarg, *namedarg, *minfo;
9717 if (arginfo [i].prop) {
9718 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9719 if (!minfo)
9720 goto leave;
9721 } else {
9722 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9723 if (!mono_error_ok (&error))
9724 goto leave;
9727 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9728 if (!is_ok (&error))
9729 goto leave;
9730 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9731 if (!is_ok (&error))
9732 goto leave;
9734 mono_array_setref (namedargs, i, namedarg);
9737 *ctor_args = typedargs;
9738 *named_args = namedargs;
9739 leave:
9740 g_free (arginfo);
9741 mono_error_raise_exception (&error);
9745 static MonoObject*
9746 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9748 static MonoMethod *ctor;
9750 MonoDomain *domain;
9751 MonoObject *attr;
9752 void *params [4];
9754 mono_error_init (error);
9756 g_assert (image->assembly);
9758 if (!ctor)
9759 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9761 domain = mono_domain_get ();
9762 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9763 return_val_if_nok (error, NULL);
9764 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9765 return_val_if_nok (error, NULL);
9766 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9767 return_val_if_nok (error, NULL);
9768 params [2] = (gpointer)&cattr->data;
9769 params [3] = &cattr->data_size;
9771 mono_runtime_invoke_checked (ctor, attr, params, error);
9772 return_val_if_nok (error, NULL);
9773 return attr;
9776 static MonoArray*
9777 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9779 MonoArray *result;
9780 MonoObject *attr;
9781 int i, n;
9783 mono_error_init (error);
9785 n = 0;
9786 for (i = 0; i < cinfo->num_attrs; ++i) {
9787 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9788 n ++;
9791 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9792 n = 0;
9793 for (i = 0; i < cinfo->num_attrs; ++i) {
9794 if (!cinfo->attrs [i].ctor) {
9795 /* The cattr type is not finished yet */
9796 /* We should include the type name but cinfo doesn't contain it */
9797 mono_error_set_type_load_name (error, NULL, NULL, "");
9798 return NULL;
9800 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9801 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9802 if (!mono_error_ok (error))
9803 return result;
9804 mono_array_setref (result, n, attr);
9805 n ++;
9808 return result;
9811 MonoArray*
9812 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9814 MonoError error;
9815 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9816 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9818 return result;
9821 static MonoArray*
9822 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9824 MonoArray *result;
9825 MonoObject *attr;
9826 int i;
9828 mono_error_init (error);
9829 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9830 for (i = 0; i < cinfo->num_attrs; ++i) {
9831 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9832 return_val_if_nok (error, NULL);
9833 mono_array_setref (result, i, attr);
9835 return result;
9839 * mono_custom_attrs_from_index:
9841 * Returns: NULL if no attributes are found or if a loading error occurs.
9843 MonoCustomAttrInfo*
9844 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9846 MonoError error;
9847 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9848 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9849 return result;
9852 * mono_custom_attrs_from_index_checked:
9854 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9856 MonoCustomAttrInfo*
9857 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9859 guint32 mtoken, i, len;
9860 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9861 MonoTableInfo *ca;
9862 MonoCustomAttrInfo *ainfo;
9863 GList *tmp, *list = NULL;
9864 const char *data;
9865 MonoCustomAttrEntry* attr;
9867 mono_error_init (error);
9869 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9871 i = mono_metadata_custom_attrs_from_index (image, idx);
9872 if (!i)
9873 return NULL;
9874 i --;
9875 while (i < ca->rows) {
9876 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9877 break;
9878 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9879 ++i;
9881 len = g_list_length (list);
9882 if (!len)
9883 return NULL;
9884 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9885 ainfo->num_attrs = len;
9886 ainfo->image = image;
9887 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9888 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9889 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9890 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9891 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9892 mtoken |= MONO_TOKEN_METHOD_DEF;
9893 break;
9894 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9895 mtoken |= MONO_TOKEN_MEMBER_REF;
9896 break;
9897 default:
9898 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9899 break;
9901 attr = &ainfo->attrs [i - 1];
9902 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9903 if (!attr->ctor) {
9904 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9905 g_list_free (list);
9906 g_free (ainfo);
9907 return NULL;
9910 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9911 /*FIXME raising an exception here doesn't make any sense*/
9912 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9913 g_list_free (list);
9914 g_free (ainfo);
9915 return NULL;
9917 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9918 attr->data_size = mono_metadata_decode_value (data, &data);
9919 attr->data = (guchar*)data;
9921 g_list_free (list);
9923 return ainfo;
9926 MonoCustomAttrInfo*
9927 mono_custom_attrs_from_method (MonoMethod *method)
9929 MonoError error;
9930 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9931 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9932 return result;
9935 MonoCustomAttrInfo*
9936 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9938 guint32 idx;
9940 mono_error_init (error);
9943 * An instantiated method has the same cattrs as the generic method definition.
9945 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9946 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9948 if (method->is_inflated)
9949 method = ((MonoMethodInflated *) method)->declaring;
9951 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9952 return lookup_custom_attr (method->klass->image, method);
9954 if (!method->token)
9955 /* Synthetic methods */
9956 return NULL;
9958 idx = mono_method_get_index (method);
9959 idx <<= MONO_CUSTOM_ATTR_BITS;
9960 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9961 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9964 MonoCustomAttrInfo*
9965 mono_custom_attrs_from_class (MonoClass *klass)
9967 MonoError error;
9968 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9969 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9970 return result;
9973 MonoCustomAttrInfo*
9974 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9976 guint32 idx;
9978 mono_error_init (error);
9980 if (klass->generic_class)
9981 klass = klass->generic_class->container_class;
9983 if (image_is_dynamic (klass->image))
9984 return lookup_custom_attr (klass->image, klass);
9986 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9987 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9988 idx <<= MONO_CUSTOM_ATTR_BITS;
9989 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9990 } else {
9991 idx = mono_metadata_token_index (klass->type_token);
9992 idx <<= MONO_CUSTOM_ATTR_BITS;
9993 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9995 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9998 MonoCustomAttrInfo*
9999 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10001 MonoError error;
10002 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10003 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10004 return result;
10007 MonoCustomAttrInfo*
10008 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10010 guint32 idx;
10012 mono_error_init (error);
10014 if (image_is_dynamic (assembly->image))
10015 return lookup_custom_attr (assembly->image, assembly);
10016 idx = 1; /* there is only one assembly */
10017 idx <<= MONO_CUSTOM_ATTR_BITS;
10018 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10019 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10022 static MonoCustomAttrInfo*
10023 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10025 guint32 idx;
10027 if (image_is_dynamic (image))
10028 return lookup_custom_attr (image, image);
10029 idx = 1; /* there is only one module */
10030 idx <<= MONO_CUSTOM_ATTR_BITS;
10031 idx |= MONO_CUSTOM_ATTR_MODULE;
10032 return mono_custom_attrs_from_index_checked (image, idx, error);
10035 MonoCustomAttrInfo*
10036 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10038 MonoError error;
10039 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10040 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10041 return result;
10044 MonoCustomAttrInfo*
10045 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10047 guint32 idx;
10049 if (image_is_dynamic (klass->image)) {
10050 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10051 return lookup_custom_attr (klass->image, property);
10053 idx = find_property_index (klass, property);
10054 idx <<= MONO_CUSTOM_ATTR_BITS;
10055 idx |= MONO_CUSTOM_ATTR_PROPERTY;
10056 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10059 MonoCustomAttrInfo*
10060 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10062 MonoError error;
10063 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10064 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10065 return result;
10068 MonoCustomAttrInfo*
10069 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10071 guint32 idx;
10073 if (image_is_dynamic (klass->image)) {
10074 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10075 return lookup_custom_attr (klass->image, event);
10077 idx = find_event_index (klass, event);
10078 idx <<= MONO_CUSTOM_ATTR_BITS;
10079 idx |= MONO_CUSTOM_ATTR_EVENT;
10080 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10083 MonoCustomAttrInfo*
10084 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10086 MonoError error;
10087 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10088 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10089 return result;
10092 MonoCustomAttrInfo*
10093 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10095 guint32 idx;
10096 mono_error_init (error);
10098 if (image_is_dynamic (klass->image)) {
10099 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10100 return lookup_custom_attr (klass->image, field);
10102 idx = find_field_index (klass, field);
10103 idx <<= MONO_CUSTOM_ATTR_BITS;
10104 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10105 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10109 * mono_custom_attrs_from_param:
10110 * @method: handle to the method that we want to retrieve custom parameter information from
10111 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10113 * The result must be released with mono_custom_attrs_free().
10115 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10117 MonoCustomAttrInfo*
10118 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10120 MonoError error;
10121 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10122 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10123 return result;
10127 * mono_custom_attrs_from_param_checked:
10128 * @method: handle to the method that we want to retrieve custom parameter information from
10129 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10130 * @error: set on error
10132 * The result must be released with mono_custom_attrs_free().
10134 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10136 MonoCustomAttrInfo*
10137 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10139 MonoTableInfo *ca;
10140 guint32 i, idx, method_index;
10141 guint32 param_list, param_last, param_pos, found;
10142 MonoImage *image;
10143 MonoReflectionMethodAux *aux;
10145 mono_error_init (error);
10148 * An instantiated method has the same cattrs as the generic method definition.
10150 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10151 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10153 if (method->is_inflated)
10154 method = ((MonoMethodInflated *) method)->declaring;
10156 if (image_is_dynamic (method->klass->image)) {
10157 MonoCustomAttrInfo *res, *ainfo;
10158 int size;
10160 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10161 if (!aux || !aux->param_cattr)
10162 return NULL;
10164 /* Need to copy since it will be freed later */
10165 ainfo = aux->param_cattr [param];
10166 if (!ainfo)
10167 return NULL;
10168 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10169 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10170 memcpy (res, ainfo, size);
10171 return res;
10174 image = method->klass->image;
10175 method_index = mono_method_get_index (method);
10176 if (!method_index)
10177 return NULL;
10178 ca = &image->tables [MONO_TABLE_METHOD];
10180 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10181 if (method_index == ca->rows) {
10182 ca = &image->tables [MONO_TABLE_PARAM];
10183 param_last = ca->rows + 1;
10184 } else {
10185 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10186 ca = &image->tables [MONO_TABLE_PARAM];
10188 found = FALSE;
10189 for (i = param_list; i < param_last; ++i) {
10190 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10191 if (param_pos == param) {
10192 found = TRUE;
10193 break;
10196 if (!found)
10197 return NULL;
10198 idx = i;
10199 idx <<= MONO_CUSTOM_ATTR_BITS;
10200 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10201 return mono_custom_attrs_from_index_checked (image, idx, error);
10204 gboolean
10205 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10207 int i;
10208 MonoClass *klass;
10209 for (i = 0; i < ainfo->num_attrs; ++i) {
10210 klass = ainfo->attrs [i].ctor->klass;
10211 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10212 return TRUE;
10214 return FALSE;
10217 MonoObject*
10218 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10220 MonoError error;
10221 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10222 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10223 return res;
10226 MonoObject*
10227 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10229 int i, attr_index;
10230 MonoClass *klass;
10231 MonoArray *attrs;
10233 mono_error_init (error);
10235 attr_index = -1;
10236 for (i = 0; i < ainfo->num_attrs; ++i) {
10237 klass = ainfo->attrs [i].ctor->klass;
10238 if (mono_class_has_parent (klass, attr_klass)) {
10239 attr_index = i;
10240 break;
10243 if (attr_index == -1)
10244 return NULL;
10246 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10247 if (!mono_error_ok (error))
10248 return NULL;
10249 return mono_array_get (attrs, MonoObject*, attr_index);
10253 * mono_reflection_get_custom_attrs_info:
10254 * @obj: a reflection object handle
10256 * Return the custom attribute info for attributes defined for the
10257 * reflection handle @obj. The objects.
10259 * FIXME this function leaks like a sieve for SRE objects.
10261 MonoCustomAttrInfo*
10262 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10264 MonoError error;
10265 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10266 mono_error_assert_ok (&error);
10267 return result;
10271 * mono_reflection_get_custom_attrs_info_checked:
10272 * @obj: a reflection object handle
10273 * @error: set on error
10275 * Return the custom attribute info for attributes defined for the
10276 * reflection handle @obj. The objects.
10278 * On failure returns NULL and sets @error.
10280 * FIXME this function leaks like a sieve for SRE objects.
10282 MonoCustomAttrInfo*
10283 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10285 MonoClass *klass;
10286 MonoCustomAttrInfo *cinfo = NULL;
10288 mono_error_init (error);
10290 klass = obj->vtable->klass;
10291 if (klass == mono_defaults.monotype_class) {
10292 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10293 return_val_if_nok (error, NULL);
10294 klass = mono_class_from_mono_type (type);
10295 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10296 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10297 return_val_if_nok (error, NULL);
10298 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10299 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10300 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10301 return_val_if_nok (error, NULL);
10302 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10303 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10304 cinfo = mono_custom_attrs_from_module (module->image, error);
10305 return_val_if_nok (error, NULL);
10306 } else if (strcmp ("MonoProperty", klass->name) == 0) {
10307 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10308 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10309 return_val_if_nok (error, NULL);
10310 } else if (strcmp ("MonoEvent", klass->name) == 0) {
10311 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10312 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10313 return_val_if_nok (error, NULL);
10314 } else if (strcmp ("MonoField", klass->name) == 0) {
10315 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10316 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10317 return_val_if_nok (error, NULL);
10318 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10319 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10320 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10321 return_val_if_nok (error, NULL);
10322 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10323 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10324 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10325 return_val_if_nok (error, NULL);
10326 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10327 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10328 MonoClass *member_class = mono_object_class (param->MemberImpl);
10329 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10330 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10331 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10332 return_val_if_nok (error, NULL);
10333 } else if (is_sr_mono_property (member_class)) {
10334 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10335 MonoMethod *method;
10336 if (!(method = prop->property->get))
10337 method = prop->property->set;
10338 g_assert (method);
10340 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10341 return_val_if_nok (error, NULL);
10343 #ifndef DISABLE_REFLECTION_EMIT
10344 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10345 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10346 return_val_if_nok (error, NULL);
10347 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10348 return_val_if_nok (error, NULL);
10349 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10350 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10351 MonoMethod *method = NULL;
10352 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10353 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10354 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10355 method = ((MonoReflectionMethod *)c->cb)->method;
10356 else
10357 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));
10359 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10360 return_val_if_nok (error, NULL);
10362 #endif
10363 else {
10364 char *type_name = mono_type_get_full_name (member_class);
10365 mono_error_set_generic_error (error, "System", "NotSupportedException",
10366 "Custom attributes on a ParamInfo with member %s are not supported",
10367 type_name);
10368 g_free (type_name);
10369 return NULL;
10371 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10372 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10373 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10374 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10375 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10376 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10377 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10378 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10379 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10380 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10381 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10382 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10383 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10384 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10385 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10386 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10387 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10388 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10389 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10390 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10391 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10392 return_val_if_nok (error, NULL);
10393 } else { /* handle other types here... */
10394 g_error ("get custom attrs not yet supported for %s", klass->name);
10397 return cinfo;
10401 * mono_reflection_get_custom_attrs_by_type:
10402 * @obj: a reflection object handle
10404 * Return an array with all the custom attributes defined of the
10405 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10406 * of that type are returned. The objects are fully build. Return NULL if a loading error
10407 * occurs.
10409 MonoArray*
10410 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10412 MonoArray *result;
10413 MonoCustomAttrInfo *cinfo;
10415 mono_error_init (error);
10417 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10418 return_val_if_nok (error, NULL);
10419 if (cinfo) {
10420 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10421 if (!result)
10422 return NULL;
10423 if (!cinfo->cached)
10424 mono_custom_attrs_free (cinfo);
10425 } else {
10426 mono_loader_assert_no_error ();
10427 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10430 return result;
10434 * mono_reflection_get_custom_attrs:
10435 * @obj: a reflection object handle
10437 * Return an array with all the custom attributes defined of the
10438 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10439 * occurs.
10441 MonoArray*
10442 mono_reflection_get_custom_attrs (MonoObject *obj)
10444 MonoError error;
10446 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10450 * mono_reflection_get_custom_attrs_data:
10451 * @obj: a reflection obj handle
10453 * Returns an array of System.Reflection.CustomAttributeData,
10454 * which include information about attributes reflected on
10455 * types loaded using the Reflection Only methods
10457 MonoArray*
10458 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10460 MonoError error;
10461 MonoArray* result;
10462 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10463 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10464 return result;
10468 * mono_reflection_get_custom_attrs_data_checked:
10469 * @obj: a reflection obj handle
10470 * @error: set on error
10472 * Returns an array of System.Reflection.CustomAttributeData,
10473 * which include information about attributes reflected on
10474 * types loaded using the Reflection Only methods
10476 MonoArray*
10477 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10479 MonoArray *result;
10480 MonoCustomAttrInfo *cinfo;
10482 mono_error_init (error);
10484 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10485 return_val_if_nok (error, NULL);
10486 if (cinfo) {
10487 result = mono_custom_attrs_data_construct (cinfo, error);
10488 return_val_if_nok (error, NULL);
10489 if (!cinfo->cached)
10490 mono_custom_attrs_free (cinfo);
10491 } else
10492 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10494 if (mono_loader_get_last_error ())
10495 mono_error_set_from_loader_error (error);
10497 return result;
10500 static MonoReflectionType*
10501 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10503 static MonoMethod *method_get_underlying_system_type = NULL;
10504 MonoReflectionType *rt;
10505 MonoMethod *usertype_method;
10507 mono_error_init (error);
10509 if (!method_get_underlying_system_type)
10510 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10512 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10514 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10516 return rt;
10520 static gboolean
10521 is_corlib_type (MonoClass *klass)
10523 return klass->image == mono_defaults.corlib;
10526 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10527 static MonoClass *cached_class; \
10528 if (cached_class) \
10529 return cached_class == _class; \
10530 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10531 cached_class = _class; \
10532 return TRUE; \
10534 return FALSE; \
10535 } while (0) \
10538 #ifndef DISABLE_REFLECTION_EMIT
10539 static gboolean
10540 is_sre_array (MonoClass *klass)
10542 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10545 static gboolean
10546 is_sre_byref (MonoClass *klass)
10548 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10551 static gboolean
10552 is_sre_pointer (MonoClass *klass)
10554 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10557 static gboolean
10558 is_sre_generic_instance (MonoClass *klass)
10560 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10563 static gboolean
10564 is_sre_type_builder (MonoClass *klass)
10566 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10569 static gboolean
10570 is_sre_method_builder (MonoClass *klass)
10572 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10575 static gboolean
10576 is_sre_ctor_builder (MonoClass *klass)
10578 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10581 static gboolean
10582 is_sre_field_builder (MonoClass *klass)
10584 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10587 static gboolean
10588 is_sre_method_on_tb_inst (MonoClass *klass)
10590 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10593 static gboolean
10594 is_sre_ctor_on_tb_inst (MonoClass *klass)
10596 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10599 MonoType*
10600 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10602 MonoClass *klass;
10603 mono_error_init (error);
10605 if (!ref)
10606 return NULL;
10607 if (ref->type)
10608 return ref->type;
10610 if (is_usertype (ref)) {
10611 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10612 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10613 return NULL;
10614 if (ref->type)
10615 return ref->type;
10618 klass = mono_object_class (ref);
10620 if (is_sre_array (klass)) {
10621 MonoType *res;
10622 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10623 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10624 return_val_if_nok (error, NULL);
10625 g_assert (base);
10626 if (sre_array->rank == 0) //single dimentional array
10627 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10628 else
10629 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10630 sre_array->type.type = res;
10631 return res;
10632 } else if (is_sre_byref (klass)) {
10633 MonoType *res;
10634 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10635 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10636 return_val_if_nok (error, NULL);
10637 g_assert (base);
10638 res = &mono_class_from_mono_type (base)->this_arg;
10639 sre_byref->type.type = res;
10640 return res;
10641 } else if (is_sre_pointer (klass)) {
10642 MonoType *res;
10643 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10644 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10645 return_val_if_nok (error, NULL);
10646 g_assert (base);
10647 res = &mono_ptr_class_get (base)->byval_arg;
10648 sre_pointer->type.type = res;
10649 return res;
10650 } else if (is_sre_generic_instance (klass)) {
10651 MonoType *res, **types;
10652 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10653 int i, count;
10655 count = mono_array_length (gclass->type_arguments);
10656 types = g_new0 (MonoType*, count);
10657 for (i = 0; i < count; ++i) {
10658 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10659 types [i] = mono_reflection_type_get_handle (t, error);
10660 if (!types[i] || !is_ok (error)) {
10661 g_free (types);
10662 return NULL;
10666 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10667 g_free (types);
10668 g_assert (res);
10669 gclass->type.type = res;
10670 return res;
10673 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10674 return NULL;
10677 void
10678 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10680 MonoError error;
10681 mono_reflection_type_get_handle (type, &error);
10682 mono_error_set_pending_exception (&error);
10685 void
10686 mono_reflection_register_with_runtime (MonoReflectionType *type)
10688 MonoError error;
10689 MonoType *res = mono_reflection_type_get_handle (type, &error);
10690 mono_error_raise_exception (&error); /* FIXME don't raise here */
10691 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10692 MonoClass *klass;
10694 if (!res)
10695 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10697 klass = mono_class_from_mono_type (res);
10699 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10700 mono_domain_lock (domain);
10702 if (!image_is_dynamic (klass->image)) {
10703 mono_class_setup_supertypes (klass);
10704 } else {
10705 if (!domain->type_hash)
10706 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10707 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10708 mono_g_hash_table_insert (domain->type_hash, res, type);
10710 mono_domain_unlock (domain);
10711 mono_loader_unlock ();
10715 * LOCKING: Assumes the loader lock is held.
10717 static MonoMethodSignature*
10718 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10719 MonoMethodSignature *sig;
10720 int count, i;
10722 mono_error_init (error);
10724 count = parameters? mono_array_length (parameters): 0;
10726 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10727 sig->param_count = count;
10728 sig->sentinelpos = -1; /* FIXME */
10729 for (i = 0; i < count; ++i) {
10730 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10731 if (!is_ok (error)) {
10732 image_g_free (image, sig);
10733 return NULL;
10736 return sig;
10740 * LOCKING: Assumes the loader lock is held.
10742 static MonoMethodSignature*
10743 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10744 MonoMethodSignature *sig;
10746 mono_error_init (error);
10748 sig = parameters_to_signature (image, ctor->parameters, error);
10749 return_val_if_nok (error, NULL);
10750 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10751 sig->ret = &mono_defaults.void_class->byval_arg;
10752 return sig;
10756 * LOCKING: Assumes the loader lock is held.
10758 static MonoMethodSignature*
10759 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10760 MonoMethodSignature *sig;
10762 mono_error_init (error);
10764 sig = parameters_to_signature (image, method->parameters, error);
10765 return_val_if_nok (error, NULL);
10766 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10767 if (method->rtype) {
10768 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10769 if (!is_ok (error)) {
10770 image_g_free (image, sig);
10771 return NULL;
10773 } else {
10774 sig->ret = &mono_defaults.void_class->byval_arg;
10776 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10777 return sig;
10780 static MonoMethodSignature*
10781 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10782 MonoMethodSignature *sig;
10784 mono_error_init (error);
10786 sig = parameters_to_signature (NULL, 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 (method->rtype, error);
10791 if (!is_ok (error)) {
10792 g_free (sig);
10793 return NULL;
10795 } else {
10796 sig->ret = &mono_defaults.void_class->byval_arg;
10798 sig->generic_param_count = 0;
10799 return sig;
10802 static void
10803 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10805 mono_error_init (error);
10806 MonoClass *klass = mono_object_class (prop);
10807 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10808 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10809 *name = mono_string_to_utf8 (pb->name);
10810 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10811 } else {
10812 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10813 *name = g_strdup (p->property->name);
10814 if (p->property->get)
10815 *type = mono_method_signature (p->property->get)->ret;
10816 else
10817 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10821 static void
10822 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10824 mono_error_init (error);
10825 MonoClass *klass = mono_object_class (field);
10826 if (strcmp (klass->name, "FieldBuilder") == 0) {
10827 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10828 *name = mono_string_to_utf8 (fb->name);
10829 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10830 } else {
10831 MonoReflectionField *f = (MonoReflectionField *)field;
10832 *name = g_strdup (mono_field_get_name (f->field));
10833 *type = f->field->type;
10837 #else /* DISABLE_REFLECTION_EMIT */
10839 void
10840 mono_reflection_register_with_runtime (MonoReflectionType *type)
10842 /* This is empty */
10845 static gboolean
10846 is_sre_type_builder (MonoClass *klass)
10848 return FALSE;
10851 static gboolean
10852 is_sre_generic_instance (MonoClass *klass)
10854 return FALSE;
10857 static void
10858 init_type_builder_generics (MonoObject *type)
10862 #endif /* !DISABLE_REFLECTION_EMIT */
10865 static gboolean
10866 is_sr_mono_field (MonoClass *klass)
10868 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10871 static gboolean
10872 is_sr_mono_property (MonoClass *klass)
10874 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10877 static gboolean
10878 is_sr_mono_method (MonoClass *klass)
10880 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10883 static gboolean
10884 is_sr_mono_cmethod (MonoClass *klass)
10886 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10889 static gboolean
10890 is_sr_mono_generic_method (MonoClass *klass)
10892 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10895 static gboolean
10896 is_sr_mono_generic_cmethod (MonoClass *klass)
10898 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10901 gboolean
10902 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10904 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10907 static gboolean
10908 is_usertype (MonoReflectionType *ref)
10910 MonoClass *klass = mono_object_class (ref);
10911 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10914 static MonoReflectionType*
10915 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10917 mono_error_init (error);
10918 if (!type || type->type)
10919 return type;
10921 if (is_usertype (type)) {
10922 type = mono_reflection_type_get_underlying_system_type (type, error);
10923 return_val_if_nok (error, NULL);
10924 if (is_usertype (type)) {
10925 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10926 return NULL;
10930 return type;
10933 * encode_cattr_value:
10934 * Encode a value in a custom attribute stream of bytes.
10935 * The value to encode is either supplied as an object in argument val
10936 * (valuetypes are boxed), or as a pointer to the data in the
10937 * argument argval.
10938 * @type represents the type of the value
10939 * @buffer is the start of the buffer
10940 * @p the current position in the buffer
10941 * @buflen contains the size of the buffer and is used to return the new buffer size
10942 * if this needs to be realloced.
10943 * @retbuffer and @retp return the start and the position of the buffer
10944 * @error set on error.
10946 static void
10947 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
10949 MonoTypeEnum simple_type;
10951 mono_error_init (error);
10952 if ((p-buffer) + 10 >= *buflen) {
10953 char *newbuf;
10954 *buflen *= 2;
10955 newbuf = (char *)g_realloc (buffer, *buflen);
10956 p = newbuf + (p-buffer);
10957 buffer = newbuf;
10959 if (!argval)
10960 argval = ((char*)arg + sizeof (MonoObject));
10961 simple_type = type->type;
10962 handle_enum:
10963 switch (simple_type) {
10964 case MONO_TYPE_BOOLEAN:
10965 case MONO_TYPE_U1:
10966 case MONO_TYPE_I1:
10967 *p++ = *argval;
10968 break;
10969 case MONO_TYPE_CHAR:
10970 case MONO_TYPE_U2:
10971 case MONO_TYPE_I2:
10972 swap_with_size (p, argval, 2, 1);
10973 p += 2;
10974 break;
10975 case MONO_TYPE_U4:
10976 case MONO_TYPE_I4:
10977 case MONO_TYPE_R4:
10978 swap_with_size (p, argval, 4, 1);
10979 p += 4;
10980 break;
10981 case MONO_TYPE_R8:
10982 swap_with_size (p, argval, 8, 1);
10983 p += 8;
10984 break;
10985 case MONO_TYPE_U8:
10986 case MONO_TYPE_I8:
10987 swap_with_size (p, argval, 8, 1);
10988 p += 8;
10989 break;
10990 case MONO_TYPE_VALUETYPE:
10991 if (type->data.klass->enumtype) {
10992 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10993 goto handle_enum;
10994 } else {
10995 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10997 break;
10998 case MONO_TYPE_STRING: {
10999 char *str;
11000 guint32 slen;
11001 if (!arg) {
11002 *p++ = 0xFF;
11003 break;
11005 str = mono_string_to_utf8 ((MonoString*)arg);
11006 slen = strlen (str);
11007 if ((p-buffer) + 10 + slen >= *buflen) {
11008 char *newbuf;
11009 *buflen *= 2;
11010 *buflen += slen;
11011 newbuf = (char *)g_realloc (buffer, *buflen);
11012 p = newbuf + (p-buffer);
11013 buffer = newbuf;
11015 mono_metadata_encode_value (slen, p, &p);
11016 memcpy (p, str, slen);
11017 p += slen;
11018 g_free (str);
11019 break;
11021 case MONO_TYPE_CLASS: {
11022 char *str;
11023 guint32 slen;
11024 MonoType *arg_type;
11025 if (!arg) {
11026 *p++ = 0xFF;
11027 break;
11029 handle_type:
11030 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11031 return_if_nok (error);
11033 str = type_get_qualified_name (arg_type, NULL);
11034 slen = strlen (str);
11035 if ((p-buffer) + 10 + slen >= *buflen) {
11036 char *newbuf;
11037 *buflen *= 2;
11038 *buflen += slen;
11039 newbuf = (char *)g_realloc (buffer, *buflen);
11040 p = newbuf + (p-buffer);
11041 buffer = newbuf;
11043 mono_metadata_encode_value (slen, p, &p);
11044 memcpy (p, str, slen);
11045 p += slen;
11046 g_free (str);
11047 break;
11049 case MONO_TYPE_SZARRAY: {
11050 int len, i;
11051 MonoClass *eclass, *arg_eclass;
11053 if (!arg) {
11054 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11055 break;
11057 len = mono_array_length ((MonoArray*)arg);
11058 *p++ = len & 0xff;
11059 *p++ = (len >> 8) & 0xff;
11060 *p++ = (len >> 16) & 0xff;
11061 *p++ = (len >> 24) & 0xff;
11062 *retp = p;
11063 *retbuffer = buffer;
11064 eclass = type->data.klass;
11065 arg_eclass = mono_object_class (arg)->element_class;
11067 if (!eclass) {
11068 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11069 eclass = mono_defaults.object_class;
11071 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11072 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11073 int elsize = mono_class_array_element_size (arg_eclass);
11074 for (i = 0; i < len; ++i) {
11075 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11076 return_if_nok (error);
11077 elptr += elsize;
11079 } else if (eclass->valuetype && arg_eclass->valuetype) {
11080 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11081 int elsize = mono_class_array_element_size (eclass);
11082 for (i = 0; i < len; ++i) {
11083 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11084 return_if_nok (error);
11085 elptr += elsize;
11087 } else {
11088 for (i = 0; i < len; ++i) {
11089 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11090 return_if_nok (error);
11093 break;
11095 case MONO_TYPE_OBJECT: {
11096 MonoClass *klass;
11097 char *str;
11098 guint32 slen;
11101 * The parameter type is 'object' but the type of the actual
11102 * argument is not. So we have to add type information to the blob
11103 * too. This is completely undocumented in the spec.
11106 if (arg == NULL) {
11107 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
11108 *p++ = 0xFF;
11109 break;
11112 klass = mono_object_class (arg);
11114 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
11115 *p++ = 0x50;
11116 goto handle_type;
11117 } else if (klass->enumtype) {
11118 *p++ = 0x55;
11119 } else if (klass == mono_defaults.string_class) {
11120 simple_type = MONO_TYPE_STRING;
11121 *p++ = 0x0E;
11122 goto handle_enum;
11123 } else if (klass->rank == 1) {
11124 *p++ = 0x1D;
11125 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11126 /* See Partition II, Appendix B3 */
11127 *p++ = 0x51;
11128 else
11129 *p++ = klass->element_class->byval_arg.type;
11130 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11131 return_if_nok (error);
11132 break;
11133 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11134 *p++ = simple_type = klass->byval_arg.type;
11135 goto handle_enum;
11136 } else {
11137 g_error ("unhandled type in custom attr");
11139 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11140 slen = strlen (str);
11141 if ((p-buffer) + 10 + slen >= *buflen) {
11142 char *newbuf;
11143 *buflen *= 2;
11144 *buflen += slen;
11145 newbuf = (char *)g_realloc (buffer, *buflen);
11146 p = newbuf + (p-buffer);
11147 buffer = newbuf;
11149 mono_metadata_encode_value (slen, p, &p);
11150 memcpy (p, str, slen);
11151 p += slen;
11152 g_free (str);
11153 simple_type = mono_class_enum_basetype (klass)->type;
11154 goto handle_enum;
11156 default:
11157 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11159 *retp = p;
11160 *retbuffer = buffer;
11163 static void
11164 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11166 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11167 char *str = type_get_qualified_name (type, NULL);
11168 int slen = strlen (str);
11170 *p++ = 0x55;
11172 * This seems to be optional...
11173 * *p++ = 0x80;
11175 mono_metadata_encode_value (slen, p, &p);
11176 memcpy (p, str, slen);
11177 p += slen;
11178 g_free (str);
11179 } else if (type->type == MONO_TYPE_OBJECT) {
11180 *p++ = 0x51;
11181 } else if (type->type == MONO_TYPE_CLASS) {
11182 /* it should be a type: encode_cattr_value () has the check */
11183 *p++ = 0x50;
11184 } else {
11185 mono_metadata_encode_value (type->type, p, &p);
11186 if (type->type == MONO_TYPE_SZARRAY)
11187 /* See the examples in Partition VI, Annex B */
11188 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11191 *retp = p;
11194 #ifndef DISABLE_REFLECTION_EMIT
11195 static void
11196 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11198 int len;
11200 mono_error_init (error);
11202 /* Preallocate a large enough buffer */
11203 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11204 char *str = type_get_qualified_name (type, NULL);
11205 len = strlen (str);
11206 g_free (str);
11207 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11208 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11209 len = strlen (str);
11210 g_free (str);
11211 } else {
11212 len = 0;
11214 len += strlen (name);
11216 if ((p-buffer) + 20 + len >= *buflen) {
11217 char *newbuf;
11218 *buflen *= 2;
11219 *buflen += len;
11220 newbuf = (char *)g_realloc (buffer, *buflen);
11221 p = newbuf + (p-buffer);
11222 buffer = newbuf;
11225 encode_field_or_prop_type (type, p, &p);
11227 len = strlen (name);
11228 mono_metadata_encode_value (len, p, &p);
11229 memcpy (p, name, len);
11230 p += len;
11231 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11232 return_if_nok (error);
11233 *retp = p;
11234 *retbuffer = buffer;
11238 * mono_reflection_get_custom_attrs_blob:
11239 * @ctor: custom attribute constructor
11240 * @ctorArgs: arguments o the constructor
11241 * @properties:
11242 * @propValues:
11243 * @fields:
11244 * @fieldValues:
11246 * Creates the blob of data that needs to be saved in the metadata and that represents
11247 * the custom attributed described by @ctor, @ctorArgs etc.
11248 * Returns: a Byte array representing the blob of data.
11250 MonoArray*
11251 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11253 MonoError error;
11254 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11255 mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
11256 return result;
11260 * mono_reflection_get_custom_attrs_blob_checked:
11261 * @ctor: custom attribute constructor
11262 * @ctorArgs: arguments o the constructor
11263 * @properties:
11264 * @propValues:
11265 * @fields:
11266 * @fieldValues:
11267 * @error: set on error
11269 * Creates the blob of data that needs to be saved in the metadata and that represents
11270 * the custom attributed described by @ctor, @ctorArgs etc.
11271 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
11273 MonoArray*
11274 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
11276 MonoArray *result = NULL;
11277 MonoMethodSignature *sig;
11278 MonoObject *arg;
11279 char *buffer, *p;
11280 guint32 buflen, i;
11282 mono_error_init (error);
11284 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11285 /* sig is freed later so allocate it in the heap */
11286 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11287 if (!is_ok (error)) {
11288 g_free (sig);
11289 return NULL;
11291 } else {
11292 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11295 g_assert (mono_array_length (ctorArgs) == sig->param_count);
11296 buflen = 256;
11297 p = buffer = (char *)g_malloc (buflen);
11298 /* write the prolog */
11299 *p++ = 1;
11300 *p++ = 0;
11301 for (i = 0; i < sig->param_count; ++i) {
11302 arg = mono_array_get (ctorArgs, MonoObject*, i);
11303 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11304 if (!is_ok (error)) goto leave;
11306 i = 0;
11307 if (properties)
11308 i += mono_array_length (properties);
11309 if (fields)
11310 i += mono_array_length (fields);
11311 *p++ = i & 0xff;
11312 *p++ = (i >> 8) & 0xff;
11313 if (properties) {
11314 MonoObject *prop;
11315 for (i = 0; i < mono_array_length (properties); ++i) {
11316 MonoType *ptype;
11317 char *pname;
11319 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11320 get_prop_name_and_type (prop, &pname, &ptype, error);
11321 if (!is_ok (error)) goto leave;
11322 *p++ = 0x54; /* PROPERTY signature */
11323 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11324 g_free (pname);
11325 if (!is_ok (error)) goto leave;
11329 if (fields) {
11330 MonoObject *field;
11331 for (i = 0; i < mono_array_length (fields); ++i) {
11332 MonoType *ftype;
11333 char *fname;
11335 field = (MonoObject *)mono_array_get (fields, gpointer, i);
11336 get_field_name_and_type (field, &fname, &ftype, error);
11337 if (!is_ok (error)) goto leave;
11338 *p++ = 0x53; /* FIELD signature */
11339 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11340 g_free (fname);
11341 if (!is_ok (error)) goto leave;
11345 g_assert (p - buffer <= buflen);
11346 buflen = p - buffer;
11347 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11348 p = mono_array_addr (result, char, 0);
11349 memcpy (p, buffer, buflen);
11350 leave:
11351 g_free (buffer);
11352 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11353 g_free (sig);
11354 return result;
11358 * mono_reflection_setup_internal_class:
11359 * @tb: a TypeBuilder object
11361 * Creates a MonoClass that represents the TypeBuilder.
11362 * This is a trick that lets us simplify a lot of reflection code
11363 * (and will allow us to support Build and Run assemblies easier).
11365 void
11366 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11368 MonoError error;
11369 MonoClass *klass, *parent;
11371 RESOLVE_TYPE (tb->parent, &error);
11372 mono_error_raise_exception (&error); /* FIXME don't raise here */
11374 mono_loader_lock ();
11376 if (tb->parent) {
11377 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11378 if (!is_ok (&error)) {
11379 mono_loader_unlock ();
11380 mono_error_raise_exception (&error); /* FIXME don't raise here */
11382 /* check so we can compile corlib correctly */
11383 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11384 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11385 parent = parent_type->data.klass;
11386 } else {
11387 parent = mono_class_from_mono_type (parent_type);
11389 } else {
11390 parent = NULL;
11393 /* the type has already being created: it means we just have to change the parent */
11394 if (tb->type.type) {
11395 klass = mono_class_from_mono_type (tb->type.type);
11396 klass->parent = NULL;
11397 /* fool mono_class_setup_parent */
11398 klass->supertypes = NULL;
11399 mono_class_setup_parent (klass, parent);
11400 mono_class_setup_mono_type (klass);
11401 mono_loader_unlock ();
11402 return;
11405 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11407 klass->image = &tb->module->dynamic_image->image;
11409 klass->inited = 1; /* we lie to the runtime */
11410 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11411 if (!mono_error_ok (&error))
11412 goto failure;
11413 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11414 if (!mono_error_ok (&error))
11415 goto failure;
11416 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11417 klass->flags = tb->attrs;
11419 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11421 klass->element_class = klass;
11423 if (mono_class_get_ref_info (klass) == NULL) {
11425 mono_class_set_ref_info (klass, tb);
11427 /* Put into cache so mono_class_get_checked () will find it.
11428 Skip nested types as those should not be available on the global scope. */
11429 if (!tb->nesting_type)
11430 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11433 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11434 by performing a mono_class_get which does the full resolution.
11436 Working around this semantics would require us to write a lot of code for no clear advantage.
11438 mono_image_append_class_to_reflection_info_set (klass);
11439 } else {
11440 g_assert (mono_class_get_ref_info (klass) == tb);
11443 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11445 if (parent != NULL) {
11446 mono_class_setup_parent (klass, parent);
11447 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11448 const char *old_n = klass->name;
11449 /* trick to get relative numbering right when compiling corlib */
11450 klass->name = "BuildingObject";
11451 mono_class_setup_parent (klass, mono_defaults.object_class);
11452 klass->name = old_n;
11455 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11456 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11457 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11458 klass->instance_size = sizeof (MonoObject);
11459 klass->size_inited = 1;
11460 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11463 mono_class_setup_mono_type (klass);
11465 mono_class_setup_supertypes (klass);
11468 * FIXME: handle interfaces.
11471 tb->type.type = &klass->byval_arg;
11473 if (tb->nesting_type) {
11474 g_assert (tb->nesting_type->type);
11475 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11476 if (!is_ok (&error)) goto failure;
11477 klass->nested_in = mono_class_from_mono_type (nesting_type);
11480 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11482 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11484 mono_loader_unlock ();
11485 return;
11487 failure:
11488 mono_loader_unlock ();
11489 mono_error_raise_exception (&error);
11493 * mono_reflection_setup_generic_class:
11494 * @tb: a TypeBuilder object
11496 * Setup the generic class before adding the first generic parameter.
11498 void
11499 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11504 * mono_reflection_create_generic_class:
11505 * @tb: a TypeBuilder object
11507 * Creates the generic class after all generic parameters have been added.
11509 void
11510 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11512 MonoError error;
11513 MonoClass *klass;
11514 int count, i;
11516 klass = mono_class_from_mono_type (tb->type.type);
11518 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11520 if (klass->generic_container || (count == 0))
11521 return;
11523 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11525 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11527 klass->generic_container->owner.klass = klass;
11528 klass->generic_container->type_argc = count;
11529 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11531 klass->is_generic = 1;
11533 for (i = 0; i < count; i++) {
11534 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11535 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11536 mono_error_raise_exception (&error); /* FIXME don't raise here */
11537 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11538 klass->generic_container->type_params [i] = *param;
11539 /*Make sure we are a diferent type instance */
11540 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11541 klass->generic_container->type_params [i].info.pklass = NULL;
11542 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11544 g_assert (klass->generic_container->type_params [i].param.owner);
11547 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11551 * mono_reflection_create_internal_class:
11552 * @tb: a TypeBuilder object
11554 * Actually create the MonoClass that is associated with the TypeBuilder.
11556 void
11557 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11559 MonoError error;
11560 MonoClass *klass;
11562 klass = mono_class_from_mono_type (tb->type.type);
11564 mono_loader_lock ();
11565 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11566 MonoReflectionFieldBuilder *fb;
11567 MonoClass *ec;
11568 MonoType *enum_basetype;
11570 g_assert (tb->fields != NULL);
11571 g_assert (mono_array_length (tb->fields) >= 1);
11573 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11575 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11576 if (!is_ok (&error)) {
11577 mono_loader_unlock ();
11578 mono_error_raise_exception (&error); /* FIXME don't raise here */
11580 if (!mono_type_is_valid_enum_basetype (field_type)) {
11581 mono_loader_unlock ();
11582 return;
11585 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11586 if (!is_ok (&error)) {
11587 mono_loader_unlock ();
11588 mono_error_raise_exception (&error); /* FIXME don't raise here */
11590 klass->element_class = mono_class_from_mono_type (enum_basetype);
11591 if (!klass->element_class)
11592 klass->element_class = mono_class_from_mono_type (enum_basetype);
11595 * get the element_class from the current corlib.
11597 ec = default_class_from_mono_type (enum_basetype);
11598 klass->instance_size = ec->instance_size;
11599 klass->size_inited = 1;
11601 * this is almost safe to do with enums and it's needed to be able
11602 * to create objects of the enum type (for use in SetConstant).
11604 /* FIXME: Does this mean enums can't have method overrides ? */
11605 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11607 mono_loader_unlock ();
11610 static MonoMarshalSpec*
11611 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11612 MonoReflectionMarshal *minfo, MonoError *error)
11614 MonoMarshalSpec *res;
11616 mono_error_init (error);
11618 res = image_g_new0 (image, MonoMarshalSpec, 1);
11619 res->native = (MonoMarshalNative)minfo->type;
11621 switch (minfo->type) {
11622 case MONO_NATIVE_LPARRAY:
11623 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11624 if (minfo->has_size) {
11625 res->data.array_data.param_num = minfo->param_num;
11626 res->data.array_data.num_elem = minfo->count;
11627 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11629 else {
11630 res->data.array_data.param_num = -1;
11631 res->data.array_data.num_elem = -1;
11632 res->data.array_data.elem_mult = -1;
11634 break;
11636 case MONO_NATIVE_BYVALTSTR:
11637 case MONO_NATIVE_BYVALARRAY:
11638 res->data.array_data.num_elem = minfo->count;
11639 break;
11641 case MONO_NATIVE_CUSTOM:
11642 if (minfo->marshaltyperef) {
11643 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11644 if (!is_ok (error)) {
11645 image_g_free (image, res);
11646 return NULL;
11648 res->data.custom_data.custom_name =
11649 type_get_fully_qualified_name (marshaltyperef);
11651 if (minfo->mcookie)
11652 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11653 break;
11655 default:
11656 break;
11659 return res;
11661 #endif /* !DISABLE_REFLECTION_EMIT */
11663 MonoReflectionMarshalAsAttribute*
11664 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11665 MonoMarshalSpec *spec, MonoError *error)
11667 MonoReflectionType *rt;
11668 MonoReflectionMarshalAsAttribute *minfo;
11669 MonoType *mtype;
11671 mono_error_init (error);
11673 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11674 if (!minfo)
11675 return NULL;
11676 minfo->utype = spec->native;
11678 switch (minfo->utype) {
11679 case MONO_NATIVE_LPARRAY:
11680 minfo->array_subtype = spec->data.array_data.elem_type;
11681 minfo->size_const = spec->data.array_data.num_elem;
11682 if (spec->data.array_data.param_num != -1)
11683 minfo->size_param_index = spec->data.array_data.param_num;
11684 break;
11686 case MONO_NATIVE_BYVALTSTR:
11687 case MONO_NATIVE_BYVALARRAY:
11688 minfo->size_const = spec->data.array_data.num_elem;
11689 break;
11691 case MONO_NATIVE_CUSTOM:
11692 if (spec->data.custom_data.custom_name) {
11693 mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11694 return_val_if_nok (error, NULL);
11696 if (mtype) {
11697 rt = mono_type_get_object_checked (domain, mtype, error);
11698 if (!rt)
11699 return NULL;
11701 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11704 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11706 if (spec->data.custom_data.cookie)
11707 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11708 break;
11710 default:
11711 break;
11714 return minfo;
11717 #ifndef DISABLE_REFLECTION_EMIT
11718 static MonoMethod*
11719 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11720 ReflectionMethodBuilder *rmb,
11721 MonoMethodSignature *sig)
11723 MonoError error;
11724 MonoMethod *m;
11725 MonoMethodWrapper *wrapperm;
11726 MonoMarshalSpec **specs;
11727 MonoReflectionMethodAux *method_aux;
11728 MonoImage *image;
11729 gboolean dynamic;
11730 int i;
11732 mono_error_init (&error);
11734 * Methods created using a MethodBuilder should have their memory allocated
11735 * inside the image mempool, while dynamic methods should have their memory
11736 * malloc'd.
11738 dynamic = rmb->refs != NULL;
11739 image = dynamic ? NULL : klass->image;
11741 if (!dynamic)
11742 g_assert (!klass->generic_class);
11744 mono_loader_lock ();
11746 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11747 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11748 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11749 else
11750 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11752 wrapperm = (MonoMethodWrapper*)m;
11754 m->dynamic = dynamic;
11755 m->slot = -1;
11756 m->flags = rmb->attrs;
11757 m->iflags = rmb->iattrs;
11758 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11759 m->klass = klass;
11760 m->signature = sig;
11761 m->sre_method = TRUE;
11762 m->skip_visibility = rmb->skip_visibility;
11763 if (rmb->table_idx)
11764 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11766 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11767 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11768 m->string_ctor = 1;
11770 m->signature->pinvoke = 1;
11771 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11772 m->signature->pinvoke = 1;
11774 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11776 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11777 g_assert (mono_error_ok (&error));
11778 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11779 g_assert (mono_error_ok (&error));
11781 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11783 if (image_is_dynamic (klass->image))
11784 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11786 mono_loader_unlock ();
11788 return m;
11789 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11790 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11791 MonoMethodHeader *header;
11792 guint32 code_size;
11793 gint32 max_stack, i;
11794 gint32 num_locals = 0;
11795 gint32 num_clauses = 0;
11796 guint8 *code;
11798 if (rmb->ilgen) {
11799 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11800 code_size = rmb->ilgen->code_len;
11801 max_stack = rmb->ilgen->max_stack;
11802 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11803 if (rmb->ilgen->ex_handlers)
11804 num_clauses = method_count_clauses (rmb->ilgen);
11805 } else {
11806 if (rmb->code) {
11807 code = mono_array_addr (rmb->code, guint8, 0);
11808 code_size = mono_array_length (rmb->code);
11809 /* we probably need to run a verifier on the code... */
11810 max_stack = 8;
11812 else {
11813 code = NULL;
11814 code_size = 0;
11815 max_stack = 8;
11819 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11820 header->code_size = code_size;
11821 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11822 memcpy ((char*)header->code, code, code_size);
11823 header->max_stack = max_stack;
11824 header->init_locals = rmb->init_locals;
11825 header->num_locals = num_locals;
11827 for (i = 0; i < num_locals; ++i) {
11828 MonoReflectionLocalBuilder *lb =
11829 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11831 header->locals [i] = image_g_new0 (image, MonoType, 1);
11832 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11833 mono_error_assert_ok (&error);
11834 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11837 header->num_clauses = num_clauses;
11838 if (num_clauses) {
11839 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11840 rmb->ilgen, num_clauses, &error);
11841 mono_error_assert_ok (&error);
11844 wrapperm->header = header;
11847 if (rmb->generic_params) {
11848 int count = mono_array_length (rmb->generic_params);
11849 MonoGenericContainer *container = rmb->generic_container;
11851 g_assert (container);
11853 container->type_argc = count;
11854 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11855 container->owner.method = m;
11856 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11858 m->is_generic = TRUE;
11859 mono_method_set_generic_container (m, container);
11861 for (i = 0; i < count; i++) {
11862 MonoReflectionGenericParam *gp =
11863 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11864 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11865 mono_error_assert_ok (&error);
11866 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11867 container->type_params [i] = *param;
11871 * The method signature might have pointers to generic parameters that belong to other methods.
11872 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11873 * generic parameters.
11875 for (i = 0; i < m->signature->param_count; ++i) {
11876 MonoType *t = m->signature->params [i];
11877 if (t->type == MONO_TYPE_MVAR) {
11878 MonoGenericParam *gparam = t->data.generic_param;
11879 if (gparam->num < count) {
11880 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11881 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11887 if (klass->generic_container) {
11888 container->parent = klass->generic_container;
11889 container->context.class_inst = klass->generic_container->context.class_inst;
11891 container->context.method_inst = mono_get_shared_generic_inst (container);
11894 if (rmb->refs) {
11895 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11896 int i;
11897 void **data;
11899 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11901 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11902 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11903 for (i = 0; i < rmb->nrefs; ++i)
11904 data [i + 1] = rmb->refs [i];
11907 method_aux = NULL;
11909 /* Parameter info */
11910 if (rmb->pinfo) {
11911 if (!method_aux)
11912 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11913 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11914 for (i = 0; i <= m->signature->param_count; ++i) {
11915 MonoReflectionParamBuilder *pb;
11916 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11917 if ((i > 0) && (pb->attrs)) {
11918 /* Make a copy since it might point to a shared type structure */
11919 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11920 m->signature->params [i - 1]->attrs = pb->attrs;
11923 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11924 MonoDynamicImage *assembly;
11925 guint32 idx, len;
11926 MonoTypeEnum def_type;
11927 char *p;
11928 const char *p2;
11930 if (!method_aux->param_defaults) {
11931 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11932 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11934 assembly = (MonoDynamicImage*)klass->image;
11935 idx = encode_constant (assembly, pb->def_value, &def_type);
11936 /* Copy the data from the blob since it might get realloc-ed */
11937 p = assembly->blob.data + idx;
11938 len = mono_metadata_decode_blob_size (p, &p2);
11939 len += p2 - p;
11940 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11941 method_aux->param_default_types [i] = def_type;
11942 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11945 if (pb->name) {
11946 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11947 g_assert (mono_error_ok (&error));
11949 if (pb->cattrs) {
11950 if (!method_aux->param_cattr)
11951 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11952 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11958 /* Parameter marshalling */
11959 specs = NULL;
11960 if (rmb->pinfo)
11961 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11962 MonoReflectionParamBuilder *pb;
11963 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11964 if (pb->marshal_info) {
11965 if (specs == NULL)
11966 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11967 specs [pb->position] =
11968 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, &error);
11969 if (!is_ok (&error)) {
11970 mono_loader_unlock ();
11971 image_g_free (image, specs);
11972 mono_error_raise_exception (&error); /* FIXME don't raise here */
11977 if (specs != NULL) {
11978 if (!method_aux)
11979 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11980 method_aux->param_marshall = specs;
11983 if (image_is_dynamic (klass->image) && method_aux)
11984 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11986 mono_loader_unlock ();
11988 return m;
11991 static MonoMethod*
11992 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11994 ReflectionMethodBuilder rmb;
11995 MonoMethodSignature *sig;
11997 mono_loader_lock ();
11998 g_assert (klass->image != NULL);
11999 sig = ctor_builder_to_signature (klass->image, mb, error);
12000 mono_loader_unlock ();
12001 return_val_if_nok (error, NULL);
12003 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12004 return NULL;
12006 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12007 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12009 /* If we are in a generic class, we might be called multiple times from inflate_method */
12010 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12011 /* ilgen is no longer needed */
12012 mb->ilgen = NULL;
12015 return mb->mhandle;
12018 static MonoMethod*
12019 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12021 ReflectionMethodBuilder rmb;
12022 MonoMethodSignature *sig;
12024 mono_error_init (error);
12026 mono_loader_lock ();
12027 g_assert (klass->image != NULL);
12028 sig = method_builder_to_signature (klass->image, mb, error);
12029 mono_loader_unlock ();
12030 return_val_if_nok (error, NULL);
12032 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12033 return NULL;
12035 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12036 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12038 /* If we are in a generic class, we might be called multiple times from inflate_method */
12039 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12040 /* ilgen is no longer needed */
12041 mb->ilgen = NULL;
12043 return mb->mhandle;
12046 static MonoClassField*
12047 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
12049 MonoClassField *field;
12050 MonoType *custom;
12051 MonoError error;
12053 field = g_new0 (MonoClassField, 1);
12055 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
12056 g_assert (mono_error_ok (&error));
12057 if (fb->attrs || fb->modreq || fb->modopt) {
12058 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
12059 if (!is_ok (&error)) {
12060 g_free (field);
12061 mono_error_raise_exception (&error); /* FIXME don't raise here */
12063 field->type = mono_metadata_type_dup (NULL, type);
12064 field->type->attrs = fb->attrs;
12066 g_assert (image_is_dynamic (klass->image));
12067 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, &error);
12068 g_free (field->type);
12069 if (!is_ok (&error)) {
12070 g_free (field);
12071 mono_error_raise_exception (&error); /* FIXME don't raise here */
12073 field->type = mono_metadata_type_dup (klass->image, custom);
12074 g_free (custom);
12075 } else {
12076 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
12077 if (!is_ok (&error)) {
12078 g_free (field);
12079 mono_error_raise_exception (&error); /* FIXME don't raise here */
12082 if (fb->offset != -1)
12083 field->offset = fb->offset;
12084 field->parent = klass;
12085 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12087 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12089 return field;
12091 #endif
12094 * mono_reflection_bind_generic_parameters:
12095 * @type: a managed type object (which should be some kind of generic (instance? definition?))
12096 * @type_args: the number of type arguments to bind
12097 * @types: array of type arguments
12098 * @error: set on error
12100 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12101 * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
12103 MonoType*
12104 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12106 MonoClass *klass;
12107 MonoReflectionTypeBuilder *tb = NULL;
12108 gboolean is_dynamic = FALSE;
12109 MonoClass *geninst;
12111 mono_error_init (error);
12113 mono_loader_lock ();
12115 if (is_sre_type_builder (mono_object_class (type))) {
12116 tb = (MonoReflectionTypeBuilder *) type;
12118 is_dynamic = TRUE;
12119 } else if (is_sre_generic_instance (mono_object_class (type))) {
12120 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12121 MonoReflectionType *gtd = rgi->generic_type;
12123 if (is_sre_type_builder (mono_object_class (gtd))) {
12124 tb = (MonoReflectionTypeBuilder *)gtd;
12125 is_dynamic = TRUE;
12129 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12130 if (tb && tb->generic_container)
12131 mono_reflection_create_generic_class (tb);
12133 MonoType *t = mono_reflection_type_get_handle (type, error);
12134 if (!is_ok (error)) {
12135 mono_loader_unlock ();
12136 return NULL;
12139 klass = mono_class_from_mono_type (t);
12140 if (!klass->generic_container) {
12141 mono_loader_unlock ();
12142 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12143 return NULL;
12146 if (klass->wastypebuilder) {
12147 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12149 is_dynamic = TRUE;
12152 mono_loader_unlock ();
12154 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12156 return &geninst->byval_arg;
12159 MonoClass*
12160 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12162 MonoGenericClass *gclass;
12163 MonoGenericInst *inst;
12165 g_assert (klass->generic_container);
12167 inst = mono_metadata_get_generic_inst (type_argc, types);
12168 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12170 return mono_generic_class_get_class (gclass);
12173 MonoReflectionMethod*
12174 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12176 MonoError error;
12177 MonoClass *klass;
12178 MonoMethod *method, *inflated;
12179 MonoMethodInflated *imethod;
12180 MonoGenericContext tmp_context;
12181 MonoGenericInst *ginst;
12182 MonoType **type_argv;
12183 int count, i;
12185 /*FIXME but this no longer should happen*/
12186 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12187 #ifndef DISABLE_REFLECTION_EMIT
12188 MonoReflectionMethodBuilder *mb = NULL;
12189 MonoType *tb;
12190 MonoClass *klass;
12192 mb = (MonoReflectionMethodBuilder *) rmethod;
12193 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
12194 mono_error_raise_exception (&error); /* FIXME don't raise here */
12195 klass = mono_class_from_mono_type (tb);
12197 method = methodbuilder_to_mono_method (klass, mb, &error);
12198 if (!method)
12199 mono_error_raise_exception (&error); /* FIXME don't raise here */
12200 #else
12201 g_assert_not_reached ();
12202 method = NULL;
12203 #endif
12204 } else {
12205 method = rmethod->method;
12208 klass = method->klass;
12210 if (method->is_inflated)
12211 method = ((MonoMethodInflated *) method)->declaring;
12213 count = mono_method_signature (method)->generic_param_count;
12214 if (count != mono_array_length (types))
12215 return NULL;
12217 type_argv = g_new0 (MonoType *, count);
12218 for (i = 0; i < count; i++) {
12219 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12220 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12221 if (!is_ok (&error)) {
12222 g_free (type_argv);
12223 mono_error_raise_exception (&error); /* FIXME don't raise here */
12226 ginst = mono_metadata_get_generic_inst (count, type_argv);
12227 g_free (type_argv);
12229 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12230 tmp_context.method_inst = ginst;
12232 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12233 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12234 imethod = (MonoMethodInflated *) inflated;
12236 /*FIXME but I think this is no longer necessary*/
12237 if (image_is_dynamic (method->klass->image)) {
12238 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12240 * This table maps metadata structures representing inflated methods/fields
12241 * to the reflection objects representing their generic definitions.
12243 mono_image_lock ((MonoImage*)image);
12244 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12245 mono_image_unlock ((MonoImage*)image);
12248 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12249 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12251 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12252 mono_error_raise_exception (&error); /* FIXME don't raise here */
12253 return ret;
12256 #ifndef DISABLE_REFLECTION_EMIT
12258 static MonoMethod *
12259 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12261 MonoMethodInflated *imethod;
12262 MonoGenericContext *context;
12263 int i;
12266 * With generic code sharing the klass might not be inflated.
12267 * This can happen because classes inflated with their own
12268 * type arguments are "normalized" to the uninflated class.
12270 if (!klass->generic_class)
12271 return method;
12273 context = mono_class_get_context (klass);
12275 if (klass->method.count && klass->methods) {
12276 /* Find the already created inflated method */
12277 for (i = 0; i < klass->method.count; ++i) {
12278 g_assert (klass->methods [i]->is_inflated);
12279 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12280 break;
12282 g_assert (i < klass->method.count);
12283 imethod = (MonoMethodInflated*)klass->methods [i];
12284 } else {
12285 MonoError error;
12286 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12287 mono_error_assert_ok (&error);
12290 if (method->is_generic && image_is_dynamic (method->klass->image)) {
12291 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12293 mono_image_lock ((MonoImage*)image);
12294 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12295 mono_image_unlock ((MonoImage*)image);
12297 return (MonoMethod *) imethod;
12300 static MonoMethod *
12301 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12303 MonoMethod *method;
12304 MonoClass *gklass;
12306 mono_error_init (error);
12308 MonoClass *type_class = mono_object_class (type);
12310 if (is_sre_generic_instance (type_class)) {
12311 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12312 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12313 return_val_if_nok (error, NULL);
12314 gklass = mono_class_from_mono_type (generic_type);
12315 } else if (is_sre_type_builder (type_class)) {
12316 MonoType *t = mono_reflection_type_get_handle (type, error);
12317 return_val_if_nok (error, NULL);
12318 gklass = mono_class_from_mono_type (t);
12319 } else if (type->type) {
12320 gklass = mono_class_from_mono_type (type->type);
12321 gklass = mono_class_get_generic_type_definition (gklass);
12322 } else {
12323 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12326 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12327 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12328 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12329 else {
12330 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12331 if (!method)
12332 return NULL;
12334 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12335 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12336 if (!method)
12337 return NULL;
12338 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12339 method = ((MonoReflectionMethod *) obj)->method;
12340 else {
12341 method = NULL; /* prevent compiler warning */
12342 g_error ("can't handle type %s", obj->vtable->klass->name);
12345 MonoType *t = mono_reflection_type_get_handle (type, error);
12346 return_val_if_nok (error, NULL);
12347 return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12350 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12351 void
12352 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12354 MonoError error;
12355 MonoGenericClass *gclass;
12356 MonoDynamicGenericClass *dgclass;
12357 MonoClass *klass, *gklass;
12358 MonoType *gtype;
12359 int i;
12361 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12362 mono_error_raise_exception (&error); /* FIXME don't raise here */
12363 klass = mono_class_from_mono_type (gtype);
12364 g_assert (gtype->type == MONO_TYPE_GENERICINST);
12365 gclass = gtype->data.generic_class;
12367 if (!gclass->is_dynamic)
12368 return;
12370 dgclass = (MonoDynamicGenericClass *) gclass;
12372 if (dgclass->initialized)
12373 return;
12375 gklass = gclass->container_class;
12376 mono_class_init (gklass);
12378 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12380 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12381 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12382 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12384 for (i = 0; i < dgclass->count_fields; i++) {
12385 MonoError error;
12386 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12387 MonoClassField *field, *inflated_field = NULL;
12389 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12390 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12391 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12392 field = ((MonoReflectionField *) obj)->field;
12393 else {
12394 field = NULL; /* prevent compiler warning */
12395 g_assert_not_reached ();
12398 dgclass->fields [i] = *field;
12399 dgclass->fields [i].parent = klass;
12400 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12401 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12402 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12403 dgclass->field_generic_types [i] = field->type;
12404 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12405 dgclass->field_objects [i] = obj;
12407 if (inflated_field) {
12408 g_free (inflated_field);
12409 } else {
12410 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12414 dgclass->initialized = TRUE;
12417 void
12418 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12420 MonoDynamicGenericClass *dgclass;
12421 int i;
12423 g_assert (gclass->is_dynamic);
12425 dgclass = (MonoDynamicGenericClass *)gclass;
12427 for (i = 0; i < dgclass->count_fields; ++i) {
12428 MonoClassField *field = dgclass->fields + i;
12429 mono_metadata_free_type (field->type);
12430 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12435 * fix_partial_generic_class:
12436 * @klass: a generic instantiation MonoClass
12437 * @error: set on error
12439 * Assumes that the generic container of @klass has its vtable
12440 * initialized, and updates the parent class, insterfaces, methods and
12441 * fields of @klass by inflating the types using the generic context.
12443 * On success returns TRUE, on failure returns FALSE and sets @error.
12446 static gboolean
12447 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12449 MonoClass *gklass = klass->generic_class->container_class;
12450 MonoDynamicGenericClass *dgclass;
12451 int i;
12453 mono_error_init (error);
12455 if (klass->wastypebuilder)
12456 return TRUE;
12458 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
12459 if (klass->parent != gklass->parent) {
12460 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12461 if (mono_error_ok (error)) {
12462 MonoClass *parent = mono_class_from_mono_type (parent_type);
12463 mono_metadata_free_type (parent_type);
12464 if (parent != klass->parent) {
12465 /*fool mono_class_setup_parent*/
12466 klass->supertypes = NULL;
12467 mono_class_setup_parent (klass, parent);
12469 } else {
12470 if (gklass->wastypebuilder)
12471 klass->wastypebuilder = TRUE;
12472 return FALSE;
12476 if (!dgclass->initialized)
12477 return TRUE;
12479 if (klass->method.count != gklass->method.count) {
12480 klass->method.count = gklass->method.count;
12481 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12483 for (i = 0; i < klass->method.count; i++) {
12484 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12485 gklass->methods [i], klass, mono_class_get_context (klass), error);
12486 mono_error_assert_ok (error);
12490 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12491 klass->interface_count = gklass->interface_count;
12492 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12493 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12495 for (i = 0; i < gklass->interface_count; ++i) {
12496 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12497 return_val_if_nok (error, FALSE);
12499 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12500 mono_metadata_free_type (iface_type);
12502 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12503 return FALSE;
12505 klass->interfaces_inited = 1;
12508 if (klass->field.count != gklass->field.count) {
12509 klass->field.count = gklass->field.count;
12510 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12512 for (i = 0; i < klass->field.count; i++) {
12513 klass->fields [i] = gklass->fields [i];
12514 klass->fields [i].parent = klass;
12515 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12516 return_val_if_nok (error, FALSE);
12520 /*We can only finish with this klass once it's parent has as well*/
12521 if (gklass->wastypebuilder)
12522 klass->wastypebuilder = TRUE;
12523 return TRUE;
12527 * ensure_generic_class_runtime_vtable:
12528 * @klass a generic class
12529 * @error set on error
12531 * Ensures that the generic container of @klass has a vtable and
12532 * returns TRUE on success. On error returns FALSE and sets @error.
12534 static gboolean
12535 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12537 MonoClass *gklass = klass->generic_class->container_class;
12539 mono_error_init (error);
12541 if (!ensure_runtime_vtable (gklass, error))
12542 return FALSE;
12544 return fix_partial_generic_class (klass, error);
12548 * ensure_runtime_vtable:
12549 * @klass the class
12550 * @error set on error
12552 * Ensures that @klass has a vtable and returns TRUE on success. On
12553 * error returns FALSE and sets @error.
12555 static gboolean
12556 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12558 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12559 int i, num, j;
12561 mono_error_init (error);
12563 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12564 return TRUE;
12565 if (klass->parent)
12566 if (!ensure_runtime_vtable (klass->parent, error))
12567 return FALSE;
12569 if (tb) {
12570 num = tb->ctors? mono_array_length (tb->ctors): 0;
12571 num += tb->num_methods;
12572 klass->method.count = num;
12573 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12574 num = tb->ctors? mono_array_length (tb->ctors): 0;
12575 for (i = 0; i < num; ++i) {
12576 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12577 if (!ctor)
12578 return FALSE;
12579 klass->methods [i] = ctor;
12581 num = tb->num_methods;
12582 j = i;
12583 for (i = 0; i < num; ++i) {
12584 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12585 if (!meth)
12586 return FALSE;
12587 klass->methods [j++] = meth;
12590 if (tb->interfaces) {
12591 klass->interface_count = mono_array_length (tb->interfaces);
12592 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12593 for (i = 0; i < klass->interface_count; ++i) {
12594 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12595 return_val_if_nok (error, FALSE);
12596 klass->interfaces [i] = mono_class_from_mono_type (iface);
12597 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12598 return FALSE;
12600 klass->interfaces_inited = 1;
12602 } else if (klass->generic_class){
12603 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12604 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12605 return FALSE;
12609 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12610 int slot_num = 0;
12611 for (i = 0; i < klass->method.count; ++i) {
12612 MonoMethod *im = klass->methods [i];
12613 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12614 im->slot = slot_num++;
12617 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12618 mono_class_setup_interface_offsets (klass);
12619 mono_class_setup_interface_id (klass);
12623 * The generic vtable is needed even if image->run is not set since some
12624 * runtime code like ves_icall_Type_GetMethodsByName depends on
12625 * method->slot being defined.
12629 * tb->methods could not be freed since it is used for determining
12630 * overrides during dynamic vtable construction.
12633 return TRUE;
12636 static MonoMethod*
12637 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12639 mono_error_init (error);
12640 MonoClass *klass = mono_object_class (method);
12641 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12642 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12643 return sr_method->method;
12645 if (is_sre_method_builder (klass)) {
12646 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12647 return mb->mhandle;
12649 if (is_sre_method_on_tb_inst (klass)) {
12650 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12651 MonoMethod *result;
12652 /*FIXME move this to a proper method and unify with resolve_object*/
12653 if (m->method_args) {
12654 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12655 } else {
12656 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12657 return_val_if_nok (error, NULL);
12658 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12659 MonoMethod *mono_method;
12661 if (is_sre_method_builder (mono_object_class (m->mb)))
12662 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12663 else if (is_sr_mono_method (mono_object_class (m->mb)))
12664 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12665 else
12666 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)));
12668 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12670 return result;
12673 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12674 return NULL;
12677 void
12678 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12680 MonoReflectionTypeBuilder *tb;
12681 int i, j, onum;
12682 MonoReflectionMethod *m;
12684 mono_error_init (error);
12685 *overrides = NULL;
12686 *num_overrides = 0;
12688 g_assert (image_is_dynamic (klass->image));
12690 if (!mono_class_get_ref_info (klass))
12691 return;
12693 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12695 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12697 onum = 0;
12698 if (tb->methods) {
12699 for (i = 0; i < tb->num_methods; ++i) {
12700 MonoReflectionMethodBuilder *mb =
12701 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12702 if (mb->override_methods)
12703 onum += mono_array_length (mb->override_methods);
12707 if (onum) {
12708 *overrides = g_new0 (MonoMethod*, onum * 2);
12710 onum = 0;
12711 for (i = 0; i < tb->num_methods; ++i) {
12712 MonoReflectionMethodBuilder *mb =
12713 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12714 if (mb->override_methods) {
12715 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12716 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12718 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12719 return_if_nok (error);
12720 (*overrides) [onum * 2 + 1] = mb->mhandle;
12722 g_assert (mb->mhandle);
12724 onum ++;
12730 *num_overrides = onum;
12733 static void
12734 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12736 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12737 MonoReflectionFieldBuilder *fb;
12738 MonoClassField *field;
12739 MonoImage *image = klass->image;
12740 const char *p, *p2;
12741 int i;
12742 guint32 len, idx, real_size = 0;
12744 klass->field.count = tb->num_fields;
12745 klass->field.first = 0;
12747 mono_error_init (error);
12749 if (tb->class_size) {
12750 if ((tb->packing_size & 0xffffff00) != 0) {
12751 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12752 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12753 return;
12755 klass->packing_size = tb->packing_size;
12756 real_size = klass->instance_size + tb->class_size;
12759 if (!klass->field.count) {
12760 klass->instance_size = MAX (klass->instance_size, real_size);
12761 return;
12764 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12765 mono_class_alloc_ext (klass);
12766 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12768 This is, guess what, a hack.
12769 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12770 On the static path no field class is resolved, only types are built. This is the right thing to do
12771 but we suck.
12772 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12774 klass->size_inited = 1;
12776 for (i = 0; i < klass->field.count; ++i) {
12777 MonoArray *rva_data;
12778 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12779 field = &klass->fields [i];
12780 field->name = mono_string_to_utf8_image (image, fb->name, error);
12781 if (!mono_error_ok (error))
12782 return;
12783 if (fb->attrs) {
12784 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12785 return_if_nok (error);
12786 field->type = mono_metadata_type_dup (klass->image, type);
12787 field->type->attrs = fb->attrs;
12788 } else {
12789 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12790 return_if_nok (error);
12793 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12794 char *base = mono_array_addr (rva_data, char, 0);
12795 size_t size = mono_array_length (rva_data);
12796 char *data = (char *)mono_image_alloc (klass->image, size);
12797 memcpy (data, base, size);
12798 klass->ext->field_def_values [i].data = data;
12800 if (fb->offset != -1)
12801 field->offset = fb->offset;
12802 field->parent = klass;
12803 fb->handle = field;
12804 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12806 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12807 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12809 if (fb->def_value) {
12810 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12811 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12812 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12813 /* Copy the data from the blob since it might get realloc-ed */
12814 p = assembly->blob.data + idx;
12815 len = mono_metadata_decode_blob_size (p, &p2);
12816 len += p2 - p;
12817 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12818 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12822 klass->instance_size = MAX (klass->instance_size, real_size);
12823 mono_class_layout_fields (klass);
12826 static void
12827 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12829 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12830 MonoReflectionPropertyBuilder *pb;
12831 MonoImage *image = klass->image;
12832 MonoProperty *properties;
12833 int i;
12835 mono_error_init (error);
12837 if (!klass->ext)
12838 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12840 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12841 klass->ext->property.first = 0;
12843 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12844 klass->ext->properties = properties;
12845 for (i = 0; i < klass->ext->property.count; ++i) {
12846 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12847 properties [i].parent = klass;
12848 properties [i].attrs = pb->attrs;
12849 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12850 if (!mono_error_ok (error))
12851 return;
12852 if (pb->get_method)
12853 properties [i].get = pb->get_method->mhandle;
12854 if (pb->set_method)
12855 properties [i].set = pb->set_method->mhandle;
12857 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12858 if (pb->def_value) {
12859 guint32 len, idx;
12860 const char *p, *p2;
12861 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12862 if (!klass->ext->prop_def_values)
12863 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12864 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12865 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12866 /* Copy the data from the blob since it might get realloc-ed */
12867 p = assembly->blob.data + idx;
12868 len = mono_metadata_decode_blob_size (p, &p2);
12869 len += p2 - p;
12870 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12871 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12876 MonoReflectionEvent *
12877 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12879 MonoError error;
12880 MonoEvent *event = g_new0 (MonoEvent, 1);
12881 MonoClass *klass;
12883 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12884 mono_error_raise_exception (&error); /* FIXME don't raise here */
12885 klass = mono_class_from_mono_type (type);
12887 event->parent = klass;
12888 event->attrs = eb->attrs;
12889 event->name = mono_string_to_utf8 (eb->name);
12890 if (eb->add_method)
12891 event->add = eb->add_method->mhandle;
12892 if (eb->remove_method)
12893 event->remove = eb->remove_method->mhandle;
12894 if (eb->raise_method)
12895 event->raise = eb->raise_method->mhandle;
12897 #ifndef MONO_SMALL_CONFIG
12898 if (eb->other_methods) {
12899 int j;
12900 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12901 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12902 MonoReflectionMethodBuilder *mb =
12903 mono_array_get (eb->other_methods,
12904 MonoReflectionMethodBuilder*, j);
12905 event->other [j] = mb->mhandle;
12908 #endif
12910 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12911 mono_error_raise_exception (&error); /* FIXME don't raise here */
12912 return ev_obj;
12915 static void
12916 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12918 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12919 MonoReflectionEventBuilder *eb;
12920 MonoImage *image = klass->image;
12921 MonoEvent *events;
12922 int i;
12924 mono_error_init (error);
12926 if (!klass->ext)
12927 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12929 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12930 klass->ext->event.first = 0;
12932 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12933 klass->ext->events = events;
12934 for (i = 0; i < klass->ext->event.count; ++i) {
12935 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12936 events [i].parent = klass;
12937 events [i].attrs = eb->attrs;
12938 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12939 if (!mono_error_ok (error))
12940 return;
12941 if (eb->add_method)
12942 events [i].add = eb->add_method->mhandle;
12943 if (eb->remove_method)
12944 events [i].remove = eb->remove_method->mhandle;
12945 if (eb->raise_method)
12946 events [i].raise = eb->raise_method->mhandle;
12948 #ifndef MONO_SMALL_CONFIG
12949 if (eb->other_methods) {
12950 int j;
12951 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12952 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12953 MonoReflectionMethodBuilder *mb =
12954 mono_array_get (eb->other_methods,
12955 MonoReflectionMethodBuilder*, j);
12956 events [i].other [j] = mb->mhandle;
12959 #endif
12960 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12964 static gboolean
12965 remove_instantiations_of_and_ensure_contents (gpointer key,
12966 gpointer value,
12967 gpointer user_data)
12969 MonoError error;
12970 MonoType *type = (MonoType*)key;
12971 MonoClass *klass = (MonoClass*)user_data;
12973 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12974 MonoClass *inst_klass = mono_class_from_mono_type (type);
12975 //Ensure it's safe to use it.
12976 if (!fix_partial_generic_class (inst_klass, &error)) {
12977 mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12978 mono_error_raise_exception (&error); /* FIXME don't raise here */
12980 return TRUE;
12981 } else
12982 return FALSE;
12985 static void
12986 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12988 mono_error_init (error);
12989 int i;
12991 if (!arr)
12992 return;
12994 for (i = 0; i < mono_array_length (arr); ++i) {
12995 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12996 if (!mono_error_ok (error))
12997 break;
13001 MonoReflectionType*
13002 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13004 MonoError error;
13005 MonoClass *klass;
13006 MonoDomain* domain;
13007 MonoReflectionType* res;
13008 int i, j;
13010 domain = mono_object_domain (tb);
13011 klass = mono_class_from_mono_type (tb->type.type);
13014 * Check for user defined Type subclasses.
13016 RESOLVE_TYPE (tb->parent, &error);
13017 mono_error_raise_exception (&error); /* FIXME don't raise here */
13018 check_array_for_usertypes (tb->interfaces, &error);
13019 mono_error_raise_exception (&error); /*FIXME don't raise here */
13020 if (tb->fields) {
13021 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13022 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13023 if (fb) {
13024 RESOLVE_TYPE (fb->type, &error);
13025 mono_error_raise_exception (&error); /* FIXME don't raise here */
13026 check_array_for_usertypes (fb->modreq, &error);
13027 mono_error_raise_exception (&error); /*FIXME don't raise here */
13028 check_array_for_usertypes (fb->modopt, &error);
13029 mono_error_raise_exception (&error); /*FIXME don't raise here */
13030 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13031 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13032 mono_error_raise_exception (&error); /* FIXME don't raise here */
13037 if (tb->methods) {
13038 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13039 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13040 if (mb) {
13041 RESOLVE_TYPE (mb->rtype, &error);
13042 mono_error_raise_exception (&error); /* FIXME don't raise here */
13043 check_array_for_usertypes (mb->return_modreq, &error);
13044 mono_error_raise_exception (&error); /*FIXME don't raise here */
13045 check_array_for_usertypes (mb->return_modopt, &error);
13046 mono_error_raise_exception (&error); /*FIXME don't raise here */
13047 check_array_for_usertypes (mb->parameters, &error);
13048 mono_error_raise_exception (&error); /*FIXME don't raise here */
13049 if (mb->param_modreq)
13050 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13051 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13052 mono_error_raise_exception (&error); /*FIXME don't raise here */
13054 if (mb->param_modopt)
13055 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13056 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13057 mono_error_raise_exception (&error); /*FIXME don't raise here */
13062 if (tb->ctors) {
13063 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13064 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13065 if (mb) {
13066 check_array_for_usertypes (mb->parameters, &error);
13067 mono_error_raise_exception (&error); /*FIXME don't raise here */
13068 if (mb->param_modreq)
13069 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13070 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13071 mono_error_raise_exception (&error); /*FIXME don't raise here */
13073 if (mb->param_modopt)
13074 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13075 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13076 mono_error_raise_exception (&error); /*FIXME don't raise here */
13082 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13085 * we need to lock the domain because the lock will be taken inside
13086 * So, we need to keep the locking order correct.
13088 mono_loader_lock ();
13089 mono_domain_lock (domain);
13090 if (klass->wastypebuilder) {
13091 mono_domain_unlock (domain);
13092 mono_loader_unlock ();
13094 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13095 mono_error_raise_exception (&error); /* FIXME don't raise here */
13097 return res;
13100 * Fields to set in klass:
13101 * the various flags: delegate/unicode/contextbound etc.
13103 klass->flags = tb->attrs;
13104 klass->has_cctor = 1;
13105 klass->has_finalize = 1;
13106 klass->has_finalize_inited = 1;
13108 mono_class_setup_parent (klass, klass->parent);
13109 /* fool mono_class_setup_supertypes */
13110 klass->supertypes = NULL;
13111 mono_class_setup_supertypes (klass);
13112 mono_class_setup_mono_type (klass);
13114 #if 0
13115 if (!((MonoDynamicImage*)klass->image)->run) {
13116 if (klass->generic_container) {
13117 /* FIXME: The code below can't handle generic classes */
13118 klass->wastypebuilder = TRUE;
13119 mono_loader_unlock ();
13120 mono_domain_unlock (domain);
13122 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13123 mono_error_raise_exception (&error); /* FIXME don't raise here */
13125 return res;
13128 #endif
13130 /* enums are done right away */
13131 if (!klass->enumtype)
13132 if (!ensure_runtime_vtable (klass, &error))
13133 goto failure;
13135 if (tb->subtypes) {
13136 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13137 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13138 mono_class_alloc_ext (klass);
13139 MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13140 if (!is_ok (&error)) goto failure;
13141 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13145 klass->nested_classes_inited = TRUE;
13147 /* fields and object layout */
13148 if (klass->parent) {
13149 if (!klass->parent->size_inited)
13150 mono_class_init (klass->parent);
13151 klass->instance_size = klass->parent->instance_size;
13152 klass->sizes.class_size = 0;
13153 klass->min_align = klass->parent->min_align;
13154 /* if the type has no fields we won't call the field_setup
13155 * routine which sets up klass->has_references.
13157 klass->has_references |= klass->parent->has_references;
13158 } else {
13159 klass->instance_size = sizeof (MonoObject);
13160 klass->min_align = 1;
13163 /* FIXME: handle packing_size and instance_size */
13164 typebuilder_setup_fields (klass, &error);
13165 if (!mono_error_ok (&error))
13166 goto failure;
13167 typebuilder_setup_properties (klass, &error);
13168 if (!mono_error_ok (&error))
13169 goto failure;
13171 typebuilder_setup_events (klass, &error);
13172 if (!mono_error_ok (&error))
13173 goto failure;
13175 klass->wastypebuilder = TRUE;
13178 * If we are a generic TypeBuilder, there might be instantiations in the type cache
13179 * which have type System.Reflection.MonoGenericClass, but after the type is created,
13180 * we want to return normal System.MonoType objects, so clear these out from the cache.
13182 * Together with this we must ensure the contents of all instances to match the created type.
13184 if (domain->type_hash && klass->generic_container)
13185 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
13187 mono_domain_unlock (domain);
13188 mono_loader_unlock ();
13190 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13191 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13192 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
13195 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13196 mono_error_raise_exception (&error); /* FIXME don't raise here */
13198 g_assert (res != (MonoReflectionType*)tb);
13200 return res;
13202 failure:
13203 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13204 klass->wastypebuilder = TRUE;
13205 mono_domain_unlock (domain);
13206 mono_loader_unlock ();
13207 mono_error_raise_exception (&error);
13208 return NULL;
13211 void
13212 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13214 MonoGenericParamFull *param;
13215 MonoImage *image;
13216 MonoClass *pklass;
13217 MonoError error;
13219 image = &gparam->tbuilder->module->dynamic_image->image;
13221 param = mono_image_new0 (image, MonoGenericParamFull, 1);
13223 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
13224 g_assert (mono_error_ok (&error));
13225 param->param.num = gparam->index;
13227 if (gparam->mbuilder) {
13228 if (!gparam->mbuilder->generic_container) {
13229 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
13230 mono_error_raise_exception (&error); /* FIXME don't raise here */
13232 MonoClass *klass = mono_class_from_mono_type (tb);
13233 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13234 gparam->mbuilder->generic_container->is_method = TRUE;
13236 * Cannot set owner.method, since the MonoMethod is not created yet.
13237 * Set the image field instead, so type_in_image () works.
13239 gparam->mbuilder->generic_container->is_anonymous = TRUE;
13240 gparam->mbuilder->generic_container->owner.image = klass->image;
13242 param->param.owner = gparam->mbuilder->generic_container;
13243 } else if (gparam->tbuilder) {
13244 if (!gparam->tbuilder->generic_container) {
13245 MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
13246 mono_error_raise_exception (&error); /* FIXME don't raise here */
13247 MonoClass *klass = mono_class_from_mono_type (tb);
13248 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13249 gparam->tbuilder->generic_container->owner.klass = klass;
13251 param->param.owner = gparam->tbuilder->generic_container;
13254 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13256 gparam->type.type = &pklass->byval_arg;
13258 mono_class_set_ref_info (pklass, gparam);
13259 mono_image_append_class_to_reflection_info_set (pklass);
13262 MonoArray *
13263 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13265 MonoError error;
13266 MonoReflectionModuleBuilder *module = sig->module;
13267 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13268 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13269 guint32 buflen, i;
13270 MonoArray *result;
13271 SigBuffer buf;
13273 check_array_for_usertypes (sig->arguments, &error);
13274 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13276 sigbuffer_init (&buf, 32);
13278 sigbuffer_add_value (&buf, 0x07);
13279 sigbuffer_add_value (&buf, na);
13280 if (assembly != NULL){
13281 for (i = 0; i < na; ++i) {
13282 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13283 encode_reflection_type (assembly, type, &buf, &error);
13284 if (!is_ok (&error)) goto fail;
13288 buflen = buf.p - buf.buf;
13289 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13290 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13291 sigbuffer_free (&buf);
13292 return result;
13293 fail:
13294 sigbuffer_free (&buf);
13295 mono_error_raise_exception (&error); /* FIXME don't raise here */
13296 return NULL;
13299 MonoArray *
13300 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13302 MonoError error;
13303 MonoDynamicImage *assembly = sig->module->dynamic_image;
13304 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13305 guint32 buflen, i;
13306 MonoArray *result;
13307 SigBuffer buf;
13309 check_array_for_usertypes (sig->arguments, &error);
13310 mono_error_raise_exception (&error); /* FIXME: don't raise here */
13312 sigbuffer_init (&buf, 32);
13314 sigbuffer_add_value (&buf, 0x06);
13315 for (i = 0; i < na; ++i) {
13316 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13317 encode_reflection_type (assembly, type, &buf, &error);
13318 if (!is_ok (&error))
13319 goto fail;
13322 buflen = buf.p - buf.buf;
13323 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13324 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13325 sigbuffer_free (&buf);
13327 return result;
13328 fail:
13329 sigbuffer_free (&buf);
13330 mono_error_raise_exception (&error); /* FIXME don't raise here */
13331 return NULL;
13334 typedef struct {
13335 MonoMethod *handle;
13336 MonoDomain *domain;
13337 } DynamicMethodReleaseData;
13340 * The runtime automatically clean up those after finalization.
13342 static MonoReferenceQueue *dynamic_method_queue;
13344 static void
13345 free_dynamic_method (void *dynamic_method)
13347 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13348 MonoDomain *domain = data->domain;
13349 MonoMethod *method = data->handle;
13350 guint32 dis_link;
13352 mono_domain_lock (domain);
13353 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13354 g_hash_table_remove (domain->method_to_dyn_method, method);
13355 mono_domain_unlock (domain);
13356 g_assert (dis_link);
13357 mono_gchandle_free (dis_link);
13359 mono_runtime_free_method (domain, method);
13360 g_free (data);
13363 void
13364 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13366 MonoError error;
13367 MonoReferenceQueue *queue;
13368 MonoMethod *handle;
13369 DynamicMethodReleaseData *release_data;
13370 ReflectionMethodBuilder rmb;
13371 MonoMethodSignature *sig;
13372 MonoClass *klass;
13373 MonoDomain *domain;
13374 GSList *l;
13375 int i;
13377 if (mono_runtime_is_shutting_down ())
13378 mono_raise_exception (mono_get_exception_invalid_operation (""));
13380 if (!(queue = dynamic_method_queue)) {
13381 mono_loader_lock ();
13382 if (!(queue = dynamic_method_queue))
13383 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13384 mono_loader_unlock ();
13387 sig = dynamic_method_to_signature (mb, &error);
13388 mono_error_raise_exception (&error); /* FIXME don't raise here */
13391 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13394 * Resolve references.
13397 * Every second entry in the refs array is reserved for storing handle_class,
13398 * which is needed by the ldtoken implementation in the JIT.
13400 rmb.nrefs = mb->nrefs;
13401 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13402 for (i = 0; i < mb->nrefs; i += 2) {
13403 MonoClass *handle_class;
13404 gpointer ref;
13405 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13407 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13408 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13410 * The referenced DynamicMethod should already be created by the managed
13411 * code, except in the case of circular references. In that case, we store
13412 * method in the refs array, and fix it up later when the referenced
13413 * DynamicMethod is created.
13415 if (method->mhandle) {
13416 ref = method->mhandle;
13417 } else {
13418 /* FIXME: GC object stored in unmanaged memory */
13419 ref = method;
13421 /* FIXME: GC object stored in unmanaged memory */
13422 method->referenced_by = g_slist_append (method->referenced_by, mb);
13424 handle_class = mono_defaults.methodhandle_class;
13425 } else {
13426 MonoException *ex = NULL;
13427 ref = resolve_object (mb->module->image, obj, &handle_class, NULL, &error);
13428 if (!is_ok (&error)) {
13429 g_free (rmb.refs);
13430 mono_error_raise_exception (&error); /* FIXME don't raise here */
13432 if (!ref)
13433 ex = mono_get_exception_type_load (NULL, NULL);
13434 else if (mono_security_core_clr_enabled ())
13435 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13437 if (ex) {
13438 g_free (rmb.refs);
13439 mono_raise_exception (ex);
13440 return;
13444 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13445 rmb.refs [i + 1] = handle_class;
13448 if (mb->owner) {
13449 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13450 if (!is_ok (&error)) {
13451 g_free (rmb.refs);
13452 mono_error_raise_exception (&error); /* FIXME don't raise here */
13454 klass = mono_class_from_mono_type (owner_type);
13455 } else {
13456 klass = mono_defaults.object_class;
13459 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13460 release_data = g_new (DynamicMethodReleaseData, 1);
13461 release_data->handle = handle;
13462 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13463 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13464 g_free (release_data);
13466 /* Fix up refs entries pointing at us */
13467 for (l = mb->referenced_by; l; l = l->next) {
13468 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13469 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13470 gpointer *data;
13472 g_assert (method->mhandle);
13474 data = (gpointer*)wrapper->method_data;
13475 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13476 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13477 data [i + 1] = mb->mhandle;
13480 g_slist_free (mb->referenced_by);
13482 g_free (rmb.refs);
13484 /* ilgen is no longer needed */
13485 mb->ilgen = NULL;
13487 domain = mono_domain_get ();
13488 mono_domain_lock (domain);
13489 if (!domain->method_to_dyn_method)
13490 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13491 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13492 mono_domain_unlock (domain);
13495 #endif /* DISABLE_REFLECTION_EMIT */
13499 * mono_reflection_is_valid_dynamic_token:
13501 * Returns TRUE if token is valid.
13504 gboolean
13505 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13507 return lookup_dyn_token (image, token) != NULL;
13510 MonoMethodSignature *
13511 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13513 MonoMethodSignature *sig;
13514 g_assert (image_is_dynamic (image));
13516 mono_error_init (error);
13518 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13519 if (sig)
13520 return sig;
13522 return mono_method_signature_checked (method, error);
13525 #ifndef DISABLE_REFLECTION_EMIT
13528 * mono_reflection_lookup_dynamic_token:
13530 * Finish the Builder object pointed to by TOKEN and return the corresponding
13531 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13532 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13533 * mapping table.
13535 * LOCKING: Take the loader lock
13537 gpointer
13538 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13540 MonoError error;
13541 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13542 MonoObject *obj;
13543 MonoClass *klass;
13545 obj = lookup_dyn_token (assembly, token);
13546 if (!obj) {
13547 if (valid_token)
13548 g_error ("Could not find required dynamic token 0x%08x", token);
13549 else
13550 return NULL;
13553 if (!handle_class)
13554 handle_class = &klass;
13555 gpointer result = resolve_object (image, obj, handle_class, context, &error);
13556 mono_error_raise_exception (&error); /* FIXME don't raise here */
13557 return result;
13561 * ensure_complete_type:
13563 * Ensure that KLASS is completed if it is a dynamic type, or references
13564 * dynamic types.
13566 static void
13567 ensure_complete_type (MonoClass *klass, MonoError *error)
13569 mono_error_init (error);
13571 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13572 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13574 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13575 return_if_nok (error);
13577 // Asserting here could break a lot of code
13578 //g_assert (klass->wastypebuilder);
13581 if (klass->generic_class) {
13582 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13583 int i;
13585 for (i = 0; i < inst->type_argc; ++i) {
13586 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13587 return_if_nok (error);
13592 static gpointer
13593 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13595 gpointer result = NULL;
13597 mono_error_init (error);
13599 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13600 result = mono_string_intern_checked ((MonoString*)obj, error);
13601 return_val_if_nok (error, NULL);
13602 *handle_class = mono_defaults.string_class;
13603 g_assert (result);
13604 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13605 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13606 return_val_if_nok (error, NULL);
13607 MonoClass *mc = mono_class_from_mono_type (type);
13608 if (!mono_class_init (mc)) {
13609 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13610 return NULL;
13613 if (context) {
13614 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13615 return_val_if_nok (error, NULL);
13617 result = mono_class_from_mono_type (inflated);
13618 mono_metadata_free_type (inflated);
13619 } else {
13620 result = mono_class_from_mono_type (type);
13622 *handle_class = mono_defaults.typehandle_class;
13623 g_assert (result);
13624 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13625 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13626 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13627 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13628 result = ((MonoReflectionMethod*)obj)->method;
13629 if (context) {
13630 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13631 mono_error_assert_ok (error);
13633 *handle_class = mono_defaults.methodhandle_class;
13634 g_assert (result);
13635 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13636 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13637 result = mb->mhandle;
13638 if (!result) {
13639 /* Type is not yet created */
13640 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13642 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13643 return_val_if_nok (error, NULL);
13646 * Hopefully this has been filled in by calling CreateType() on the
13647 * TypeBuilder.
13650 * TODO: This won't work if the application finishes another
13651 * TypeBuilder instance instead of this one.
13653 result = mb->mhandle;
13655 if (context) {
13656 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13657 mono_error_assert_ok (error);
13659 *handle_class = mono_defaults.methodhandle_class;
13660 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13661 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13663 result = cb->mhandle;
13664 if (!result) {
13665 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13667 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13668 return_val_if_nok (error, NULL);
13669 result = cb->mhandle;
13671 if (context) {
13672 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13673 mono_error_assert_ok (error);
13675 *handle_class = mono_defaults.methodhandle_class;
13676 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13677 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13679 ensure_complete_type (field->parent, error);
13680 return_val_if_nok (error, NULL);
13682 if (context) {
13683 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13684 return_val_if_nok (error, NULL);
13686 MonoClass *klass = mono_class_from_mono_type (inflated);
13687 MonoClassField *inflated_field;
13688 gpointer iter = NULL;
13689 mono_metadata_free_type (inflated);
13690 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13691 if (!strcmp (field->name, inflated_field->name))
13692 break;
13694 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13695 result = inflated_field;
13696 } else {
13697 result = field;
13699 *handle_class = mono_defaults.fieldhandle_class;
13700 g_assert (result);
13701 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13702 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13703 result = fb->handle;
13705 if (!result) {
13706 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13708 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13709 return_val_if_nok (error, NULL);
13710 result = fb->handle;
13713 if (fb->handle && fb->handle->parent->generic_container) {
13714 MonoClass *klass = fb->handle->parent;
13715 MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
13716 return_val_if_nok (error, NULL);
13718 MonoClass *inflated = mono_class_from_mono_type (type);
13720 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13721 g_assert (result);
13722 mono_metadata_free_type (type);
13724 *handle_class = mono_defaults.fieldhandle_class;
13725 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13726 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13727 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13728 return_val_if_nok (error, NULL);
13729 MonoClass *klass;
13731 klass = type->data.klass;
13732 if (klass->wastypebuilder) {
13733 /* Already created */
13734 result = klass;
13736 else {
13737 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13738 return_val_if_nok (error, NULL);
13739 result = type->data.klass;
13740 g_assert (result);
13742 *handle_class = mono_defaults.typehandle_class;
13743 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13744 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13745 MonoMethodSignature *sig;
13746 int nargs, i;
13748 if (helper->arguments)
13749 nargs = mono_array_length (helper->arguments);
13750 else
13751 nargs = 0;
13753 sig = mono_metadata_signature_alloc (image, nargs);
13754 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13755 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13757 if (helper->unmanaged_call_conv) { /* unmanaged */
13758 sig->call_convention = helper->unmanaged_call_conv - 1;
13759 sig->pinvoke = TRUE;
13760 } else if (helper->call_conv & 0x02) {
13761 sig->call_convention = MONO_CALL_VARARG;
13762 } else {
13763 sig->call_convention = MONO_CALL_DEFAULT;
13766 sig->param_count = nargs;
13767 /* TODO: Copy type ? */
13768 sig->ret = helper->return_type->type;
13769 for (i = 0; i < nargs; ++i) {
13770 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
13771 if (!is_ok (error)) {
13772 image_g_free (image, sig);
13773 return NULL;
13777 result = sig;
13778 *handle_class = NULL;
13779 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13780 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13781 /* Already created by the managed code */
13782 g_assert (method->mhandle);
13783 result = method->mhandle;
13784 *handle_class = mono_defaults.methodhandle_class;
13785 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13786 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13787 return_val_if_nok (error, NULL);
13788 type = mono_class_inflate_generic_type_checked (type, context, error);
13789 return_val_if_nok (error, NULL);
13791 result = mono_class_from_mono_type (type);
13792 *handle_class = mono_defaults.typehandle_class;
13793 g_assert (result);
13794 mono_metadata_free_type (type);
13795 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13796 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13797 return_val_if_nok (error, NULL);
13798 type = mono_class_inflate_generic_type_checked (type, context, error);
13799 return_val_if_nok (error, NULL);
13801 result = mono_class_from_mono_type (type);
13802 *handle_class = mono_defaults.typehandle_class;
13803 g_assert (result);
13804 mono_metadata_free_type (type);
13805 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13806 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13807 MonoClass *inflated;
13808 MonoType *type;
13809 MonoClassField *field;
13811 if (is_sre_field_builder (mono_object_class (f->fb)))
13812 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13813 else if (is_sr_mono_field (mono_object_class (f->fb)))
13814 field = ((MonoReflectionField*)f->fb)->field;
13815 else
13816 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)));
13818 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
13819 return_val_if_nok (error, NULL);
13820 type = mono_class_inflate_generic_type_checked (finst, context, error);
13821 return_val_if_nok (error, NULL);
13823 inflated = mono_class_from_mono_type (type);
13825 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13826 ensure_complete_type (field->parent, error);
13827 if (!is_ok (error)) {
13828 mono_metadata_free_type (type);
13829 return NULL;
13832 g_assert (result);
13833 mono_metadata_free_type (type);
13834 *handle_class = mono_defaults.fieldhandle_class;
13835 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13836 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13837 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
13838 return_val_if_nok (error, NULL);
13839 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
13840 return_val_if_nok (error, NULL);
13842 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13843 MonoMethod *method;
13845 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13846 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13847 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13848 method = ((MonoReflectionMethod *)c->cb)->method;
13849 else
13850 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)));
13852 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13853 *handle_class = mono_defaults.methodhandle_class;
13854 mono_metadata_free_type (type);
13855 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13856 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13857 if (m->method_args) {
13858 result = mono_reflection_method_on_tb_inst_get_handle (m, error);
13859 return_val_if_nok (error, NULL);
13860 if (context) {
13861 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13862 mono_error_assert_ok (error);
13864 } else {
13865 MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
13866 return_val_if_nok (error, NULL);
13867 MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
13868 return_val_if_nok (error, NULL);
13870 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13871 MonoMethod *method;
13873 if (is_sre_method_builder (mono_object_class (m->mb)))
13874 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13875 else if (is_sr_mono_method (mono_object_class (m->mb)))
13876 method = ((MonoReflectionMethod *)m->mb)->method;
13877 else
13878 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)));
13880 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13881 mono_metadata_free_type (type);
13883 *handle_class = mono_defaults.methodhandle_class;
13884 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13885 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13886 MonoType *mtype;
13887 MonoClass *klass;
13888 MonoMethod *method;
13889 gpointer iter;
13890 char *name;
13892 mtype = mono_reflection_type_get_handle (m->parent, error);
13893 return_val_if_nok (error, NULL);
13894 klass = mono_class_from_mono_type (mtype);
13896 /* Find the method */
13898 name = mono_string_to_utf8 (m->name);
13899 iter = NULL;
13900 while ((method = mono_class_get_methods (klass, &iter))) {
13901 if (!strcmp (method->name, name))
13902 break;
13904 g_free (name);
13906 // FIXME:
13907 g_assert (method);
13908 // FIXME: Check parameters/return value etc. match
13910 result = method;
13911 *handle_class = mono_defaults.methodhandle_class;
13912 } else if (is_sre_array (mono_object_get_class(obj)) ||
13913 is_sre_byref (mono_object_get_class(obj)) ||
13914 is_sre_pointer (mono_object_get_class(obj))) {
13915 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13916 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
13917 return_val_if_nok (error, NULL);
13919 if (context) {
13920 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13921 return_val_if_nok (error, NULL);
13923 result = mono_class_from_mono_type (inflated);
13924 mono_metadata_free_type (inflated);
13925 } else {
13926 result = mono_class_from_mono_type (type);
13928 *handle_class = mono_defaults.typehandle_class;
13929 } else {
13930 g_print ("%s\n", obj->vtable->klass->name);
13931 g_assert_not_reached ();
13933 return result;
13936 #else /* DISABLE_REFLECTION_EMIT */
13938 MonoArray*
13939 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13941 g_assert_not_reached ();
13942 return NULL;
13945 void
13946 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13948 g_assert_not_reached ();
13951 void
13952 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13954 g_assert_not_reached ();
13957 void
13958 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13960 g_assert_not_reached ();
13963 void
13964 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13966 g_assert_not_reached ();
13969 void
13970 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13972 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13975 void
13976 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13978 g_assert_not_reached ();
13981 void
13982 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13984 g_assert_not_reached ();
13987 MonoReflectionModule *
13988 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
13990 g_assert_not_reached ();
13991 return NULL;
13994 guint32
13995 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13997 g_assert_not_reached ();
13998 return 0;
14001 guint32
14002 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14004 g_assert_not_reached ();
14005 return 0;
14008 guint32
14009 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
14010 gboolean create_open_instance, gboolean register_token, MonoError *error)
14012 g_assert_not_reached ();
14013 return 0;
14016 void
14017 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14021 void
14022 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14024 g_assert_not_reached ();
14027 void
14028 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14030 mono_error_init (error);
14031 *overrides = NULL;
14032 *num_overrides = 0;
14035 MonoReflectionEvent *
14036 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14038 g_assert_not_reached ();
14039 return NULL;
14042 MonoReflectionType*
14043 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14045 g_assert_not_reached ();
14046 return NULL;
14049 void
14050 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14052 g_assert_not_reached ();
14055 MonoArray *
14056 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14058 g_assert_not_reached ();
14059 return NULL;
14062 MonoArray *
14063 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14065 g_assert_not_reached ();
14066 return NULL;
14069 void
14070 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14074 gpointer
14075 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
14077 return NULL;
14080 MonoType*
14081 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14083 mono_error_init (error);
14084 if (!ref)
14085 return NULL;
14086 return ref->type;
14089 void
14090 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14092 g_assert_not_reached ();
14095 #endif /* DISABLE_REFLECTION_EMIT */
14097 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14098 const static guint32 declsec_flags_map[] = {
14099 0x00000000, /* empty */
14100 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
14101 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
14102 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
14103 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
14104 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
14105 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
14106 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
14107 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
14108 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
14109 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
14110 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
14111 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
14112 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
14113 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
14114 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
14115 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
14116 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
14117 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
14121 * Returns flags that includes all available security action associated to the handle.
14122 * @token: metadata token (either for a class or a method)
14123 * @image: image where resides the metadata.
14125 static guint32
14126 mono_declsec_get_flags (MonoImage *image, guint32 token)
14128 int index = mono_metadata_declsec_from_index (image, token);
14129 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14130 guint32 result = 0;
14131 guint32 action;
14132 int i;
14134 /* HasSecurity can be present for other, not specially encoded, attributes,
14135 e.g. SuppressUnmanagedCodeSecurityAttribute */
14136 if (index < 0)
14137 return 0;
14139 for (i = index; i < t->rows; i++) {
14140 guint32 cols [MONO_DECL_SECURITY_SIZE];
14142 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14143 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14144 break;
14146 action = cols [MONO_DECL_SECURITY_ACTION];
14147 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14148 result |= declsec_flags_map [action];
14149 } else {
14150 g_assert_not_reached ();
14153 return result;
14157 * Get the security actions (in the form of flags) associated with the specified method.
14159 * @method: The method for which we want the declarative security flags.
14160 * Return the declarative security flags for the method (only).
14162 * Note: To keep MonoMethod size down we do not cache the declarative security flags
14163 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
14165 guint32
14166 mono_declsec_flags_from_method (MonoMethod *method)
14168 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14169 /* FIXME: No cache (for the moment) */
14170 guint32 idx = mono_method_get_index (method);
14171 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14172 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14173 return mono_declsec_get_flags (method->klass->image, idx);
14175 return 0;
14179 * Get the security actions (in the form of flags) associated with the specified class.
14181 * @klass: The class for which we want the declarative security flags.
14182 * Return the declarative security flags for the class.
14184 * Note: We cache the flags inside the MonoClass structure as this will get
14185 * called very often (at least for each method).
14187 guint32
14188 mono_declsec_flags_from_class (MonoClass *klass)
14190 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14191 if (!klass->ext || !klass->ext->declsec_flags) {
14192 guint32 idx;
14194 idx = mono_metadata_token_index (klass->type_token);
14195 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14196 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14197 mono_loader_lock ();
14198 mono_class_alloc_ext (klass);
14199 mono_loader_unlock ();
14200 /* we cache the flags on classes */
14201 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14203 return klass->ext->declsec_flags;
14205 return 0;
14209 * Get the security actions (in the form of flags) associated with the specified assembly.
14211 * @assembly: The assembly for which we want the declarative security flags.
14212 * Return the declarative security flags for the assembly.
14214 guint32
14215 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14217 guint32 idx = 1; /* there is only one assembly */
14218 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14219 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14220 return mono_declsec_get_flags (assembly->image, idx);
14225 * Fill actions for the specific index (which may either be an encoded class token or
14226 * an encoded method token) from the metadata image.
14227 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14229 static MonoBoolean
14230 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14231 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14233 MonoBoolean result = FALSE;
14234 MonoTableInfo *t;
14235 guint32 cols [MONO_DECL_SECURITY_SIZE];
14236 int index = mono_metadata_declsec_from_index (image, token);
14237 int i;
14239 t = &image->tables [MONO_TABLE_DECLSECURITY];
14240 for (i = index; i < t->rows; i++) {
14241 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14243 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14244 return result;
14246 /* if present only replace (class) permissions with method permissions */
14247 /* if empty accept either class or method permissions */
14248 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14249 if (!actions->demand.blob) {
14250 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14251 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14252 actions->demand.blob = (char*) (blob + 2);
14253 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14254 result = TRUE;
14256 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14257 if (!actions->noncasdemand.blob) {
14258 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14259 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14260 actions->noncasdemand.blob = (char*) (blob + 2);
14261 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14262 result = TRUE;
14264 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14265 if (!actions->demandchoice.blob) {
14266 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14267 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14268 actions->demandchoice.blob = (char*) (blob + 2);
14269 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14270 result = TRUE;
14275 return result;
14278 static MonoBoolean
14279 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
14280 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14282 guint32 idx = mono_metadata_token_index (klass->type_token);
14283 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14284 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14285 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14288 static MonoBoolean
14289 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
14290 guint32 id_std, guint32 id_noncas, guint32 id_choice)
14292 guint32 idx = mono_method_get_index (method);
14293 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14294 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14295 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14299 * Collect all actions (that requires to generate code in mini) assigned for
14300 * the specified method.
14301 * Note: Don't use the content of actions if the function return FALSE.
14303 MonoBoolean
14304 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14306 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
14307 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14308 MonoBoolean result = FALSE;
14309 guint32 flags;
14311 /* quick exit if no declarative security is present in the metadata */
14312 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14313 return FALSE;
14315 /* we want the original as the wrapper is "free" of the security informations */
14316 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14317 method = mono_marshal_method_from_wrapper (method);
14318 if (!method)
14319 return FALSE;
14322 /* First we look for method-level attributes */
14323 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14324 mono_class_init (method->klass);
14325 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14327 result = mono_declsec_get_method_demands_params (method, demands,
14328 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14331 /* Here we use (or create) the class declarative cache to look for demands */
14332 flags = mono_declsec_flags_from_class (method->klass);
14333 if (flags & mask) {
14334 if (!result) {
14335 mono_class_init (method->klass);
14336 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14338 result |= mono_declsec_get_class_demands_params (method->klass, demands,
14339 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14342 /* The boolean return value is used as a shortcut in case nothing needs to
14343 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14344 return result;
14349 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14351 * Note: Don't use the content of actions if the function return FALSE.
14353 MonoBoolean
14354 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14356 MonoBoolean result = FALSE;
14357 guint32 flags;
14359 /* quick exit if no declarative security is present in the metadata */
14360 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14361 return FALSE;
14363 /* we want the original as the wrapper is "free" of the security informations */
14364 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14365 method = mono_marshal_method_from_wrapper (method);
14366 if (!method)
14367 return FALSE;
14370 /* results are independant - zeroize both */
14371 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14372 memset (klass, 0, sizeof (MonoDeclSecurityActions));
14374 /* First we look for method-level attributes */
14375 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14376 mono_class_init (method->klass);
14378 result = mono_declsec_get_method_demands_params (method, cmethod,
14379 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14382 /* Here we use (or create) the class declarative cache to look for demands */
14383 flags = mono_declsec_flags_from_class (method->klass);
14384 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14385 mono_class_init (method->klass);
14387 result |= mono_declsec_get_class_demands_params (method->klass, klass,
14388 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14391 return result;
14395 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14397 * @klass The inherited class - this is the class that provides the security check (attributes)
14398 * @demans
14399 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14401 * Note: Don't use the content of actions if the function return FALSE.
14403 MonoBoolean
14404 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14406 MonoBoolean result = FALSE;
14407 guint32 flags;
14409 /* quick exit if no declarative security is present in the metadata */
14410 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14411 return FALSE;
14413 /* Here we use (or create) the class declarative cache to look for demands */
14414 flags = mono_declsec_flags_from_class (klass);
14415 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14416 mono_class_init (klass);
14417 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14419 result |= mono_declsec_get_class_demands_params (klass, demands,
14420 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14423 return result;
14427 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14429 * Note: Don't use the content of actions if the function return FALSE.
14431 MonoBoolean
14432 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14434 /* quick exit if no declarative security is present in the metadata */
14435 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14436 return FALSE;
14438 /* we want the original as the wrapper is "free" of the security informations */
14439 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14440 method = mono_marshal_method_from_wrapper (method);
14441 if (!method)
14442 return FALSE;
14445 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14446 mono_class_init (method->klass);
14447 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14449 return mono_declsec_get_method_demands_params (method, demands,
14450 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14452 return FALSE;
14456 static MonoBoolean
14457 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14459 guint32 cols [MONO_DECL_SECURITY_SIZE];
14460 MonoTableInfo *t;
14461 int i;
14463 int index = mono_metadata_declsec_from_index (image, token);
14464 if (index == -1)
14465 return FALSE;
14467 t = &image->tables [MONO_TABLE_DECLSECURITY];
14468 for (i = index; i < t->rows; i++) {
14469 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14471 /* shortcut - index are ordered */
14472 if (token != cols [MONO_DECL_SECURITY_PARENT])
14473 return FALSE;
14475 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14476 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14477 entry->blob = (char*) (metadata + 2);
14478 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14479 return TRUE;
14483 return FALSE;
14486 MonoBoolean
14487 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14489 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14490 guint32 idx = mono_method_get_index (method);
14491 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14492 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14493 return get_declsec_action (method->klass->image, idx, action, entry);
14495 return FALSE;
14498 MonoBoolean
14499 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14501 /* use cache */
14502 guint32 flags = mono_declsec_flags_from_class (klass);
14503 if (declsec_flags_map [action] & flags) {
14504 guint32 idx = mono_metadata_token_index (klass->type_token);
14505 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14506 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14507 return get_declsec_action (klass->image, idx, action, entry);
14509 return FALSE;
14512 MonoBoolean
14513 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14515 guint32 idx = 1; /* there is only one assembly */
14516 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14517 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14519 return get_declsec_action (assembly->image, idx, action, entry);
14522 gboolean
14523 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14525 MonoObject *res, *exc;
14526 void *params [1];
14527 static MonoMethod *method = NULL;
14529 mono_error_init (error);
14531 if (method == NULL) {
14532 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14533 g_assert (method);
14537 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14538 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14540 g_assert (mono_class_get_ref_info (klass));
14541 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14543 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14544 return_val_if_nok (error, FALSE);
14546 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
14548 if (exc || !mono_error_ok (error)) {
14549 mono_error_cleanup (error);
14550 return FALSE;
14551 } else
14552 return *(MonoBoolean*)mono_object_unbox (res);
14556 * mono_reflection_type_get_type:
14557 * @reftype: the System.Type object
14559 * Returns the MonoType* associated with the C# System.Type object @reftype.
14561 MonoType*
14562 mono_reflection_type_get_type (MonoReflectionType *reftype)
14564 g_assert (reftype);
14566 MonoError error;
14567 MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14568 mono_error_assert_ok (&error);
14569 return result;
14573 * mono_reflection_assembly_get_assembly:
14574 * @refassembly: the System.Reflection.Assembly object
14576 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14578 MonoAssembly*
14579 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14581 g_assert (refassembly);
14583 return refassembly->assembly;