[reflection] MonoError in mono_param_get_objects_internal
[mono-project.git] / mono / metadata / reflection.c
blobd6bb70057a4d2a13f7b892a18305174b58b4d3c4
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);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
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);
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);
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);
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) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
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);
427 #ifndef DISABLE_REFLECTION_EMIT
428 static char*
429 image_strdup (MonoImage *image, const char *s)
431 MONO_REQ_GC_NEUTRAL_MODE;
433 if (image)
434 return mono_image_strdup (image, s);
435 else
436 return g_strdup (s);
438 #endif
440 #define image_g_new(image,struct_type, n_structs) \
441 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
443 #define image_g_new0(image,struct_type, n_structs) \
444 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
447 static void
448 alloc_table (MonoDynamicTable *table, guint nrows)
450 MONO_REQ_GC_NEUTRAL_MODE;
452 table->rows = nrows;
453 g_assert (table->columns);
454 if (nrows + 1 >= table->alloc_rows) {
455 while (nrows + 1 >= table->alloc_rows) {
456 if (table->alloc_rows == 0)
457 table->alloc_rows = 16;
458 else
459 table->alloc_rows *= 2;
462 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
466 static void
467 make_room_in_stream (MonoDynamicStream *stream, int size)
469 MONO_REQ_GC_NEUTRAL_MODE;
471 if (size <= stream->alloc_size)
472 return;
474 while (stream->alloc_size <= size) {
475 if (stream->alloc_size < 4096)
476 stream->alloc_size = 4096;
477 else
478 stream->alloc_size *= 2;
481 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
484 static guint32
485 string_heap_insert (MonoDynamicStream *sh, const char *str)
487 MONO_REQ_GC_NEUTRAL_MODE;
489 guint32 idx;
490 guint32 len;
491 gpointer oldkey, oldval;
493 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
494 return GPOINTER_TO_UINT (oldval);
496 len = strlen (str) + 1;
497 idx = sh->index;
499 make_room_in_stream (sh, idx + len);
502 * We strdup the string even if we already copy them in sh->data
503 * so that the string pointers in the hash remain valid even if
504 * we need to realloc sh->data. We may want to avoid that later.
506 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
507 memcpy (sh->data + idx, str, len);
508 sh->index += len;
509 return idx;
512 static guint32
513 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
515 MONO_REQ_GC_UNSAFE_MODE;
517 char *name = mono_string_to_utf8 (str);
518 guint32 idx;
519 idx = string_heap_insert (sh, name);
520 g_free (name);
521 return idx;
524 #ifndef DISABLE_REFLECTION_EMIT
525 static void
526 string_heap_init (MonoDynamicStream *sh)
528 MONO_REQ_GC_NEUTRAL_MODE;
530 sh->index = 0;
531 sh->alloc_size = 4096;
532 sh->data = (char *)g_malloc (4096);
533 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
534 string_heap_insert (sh, "");
536 #endif
538 static guint32
539 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
541 MONO_REQ_GC_NEUTRAL_MODE;
543 guint32 idx;
545 make_room_in_stream (stream, stream->index + len);
546 memcpy (stream->data + stream->index, data, len);
547 idx = stream->index;
548 stream->index += len;
550 * align index? Not without adding an additional param that controls it since
551 * we may store a blob value in pieces.
553 return idx;
556 static guint32
557 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
559 MONO_REQ_GC_NEUTRAL_MODE;
561 guint32 idx;
563 make_room_in_stream (stream, stream->index + len);
564 memset (stream->data + stream->index, 0, len);
565 idx = stream->index;
566 stream->index += len;
567 return idx;
570 static void
571 stream_data_align (MonoDynamicStream *stream)
573 MONO_REQ_GC_NEUTRAL_MODE;
575 char buf [4] = {0};
576 guint32 count = stream->index % 4;
578 /* we assume the stream data will be aligned */
579 if (count)
580 mono_image_add_stream_data (stream, buf, 4 - count);
583 #ifndef DISABLE_REFLECTION_EMIT
584 static int
585 mono_blob_entry_hash (const char* str)
587 MONO_REQ_GC_NEUTRAL_MODE;
589 guint len, h;
590 const char *end;
591 len = mono_metadata_decode_blob_size (str, &str);
592 if (len > 0) {
593 end = str + len;
594 h = *str;
595 for (str += 1; str < end; str++)
596 h = (h << 5) - h + *str;
597 return h;
598 } else {
599 return 0;
603 static gboolean
604 mono_blob_entry_equal (const char *str1, const char *str2) {
605 MONO_REQ_GC_NEUTRAL_MODE;
607 int len, len2;
608 const char *end1;
609 const char *end2;
610 len = mono_metadata_decode_blob_size (str1, &end1);
611 len2 = mono_metadata_decode_blob_size (str2, &end2);
612 if (len != len2)
613 return 0;
614 return memcmp (end1, end2, len) == 0;
616 #endif
617 static guint32
618 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
620 MONO_REQ_GC_NEUTRAL_MODE;
622 guint32 idx;
623 char *copy;
624 gpointer oldkey, oldval;
626 copy = (char *)g_malloc (s1+s2);
627 memcpy (copy, b1, s1);
628 memcpy (copy + s1, b2, s2);
629 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
630 g_free (copy);
631 idx = GPOINTER_TO_UINT (oldval);
632 } else {
633 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
634 mono_image_add_stream_data (&assembly->blob, b2, s2);
635 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
637 return idx;
640 static guint32
641 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
643 MONO_REQ_GC_NEUTRAL_MODE;
645 char blob_size [8];
646 char *b = blob_size;
647 guint32 size = buf->p - buf->buf;
648 /* store length */
649 g_assert (size <= (buf->end - buf->buf));
650 mono_metadata_encode_value (size, b, &b);
651 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
655 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
656 * dest may be misaligned.
658 static void
659 swap_with_size (char *dest, const char* val, int len, int nelem) {
660 MONO_REQ_GC_NEUTRAL_MODE;
661 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
662 int elem;
664 for (elem = 0; elem < nelem; ++elem) {
665 switch (len) {
666 case 1:
667 *dest = *val;
668 break;
669 case 2:
670 dest [0] = val [1];
671 dest [1] = val [0];
672 break;
673 case 4:
674 dest [0] = val [3];
675 dest [1] = val [2];
676 dest [2] = val [1];
677 dest [3] = val [0];
678 break;
679 case 8:
680 dest [0] = val [7];
681 dest [1] = val [6];
682 dest [2] = val [5];
683 dest [3] = val [4];
684 dest [4] = val [3];
685 dest [5] = val [2];
686 dest [6] = val [1];
687 dest [7] = val [0];
688 break;
689 default:
690 g_assert_not_reached ();
692 dest += len;
693 val += len;
695 #else
696 memcpy (dest, val, len * nelem);
697 #endif
700 static guint32
701 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
703 MONO_REQ_GC_UNSAFE_MODE;
705 char blob_size [64];
706 char *b = blob_size;
707 guint32 idx = 0, len;
709 len = str->length * 2;
710 mono_metadata_encode_value (len, b, &b);
711 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
713 char *swapped = g_malloc (2 * mono_string_length (str));
714 const char *p = (const char*)mono_string_chars (str);
716 swap_with_size (swapped, p, 2, mono_string_length (str));
717 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
718 g_free (swapped);
720 #else
721 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
722 #endif
723 return idx;
726 #ifndef DISABLE_REFLECTION_EMIT
727 static MonoClass *
728 default_class_from_mono_type (MonoType *type)
730 MONO_REQ_GC_NEUTRAL_MODE;
732 switch (type->type) {
733 case MONO_TYPE_OBJECT:
734 return mono_defaults.object_class;
735 case MONO_TYPE_VOID:
736 return mono_defaults.void_class;
737 case MONO_TYPE_BOOLEAN:
738 return mono_defaults.boolean_class;
739 case MONO_TYPE_CHAR:
740 return mono_defaults.char_class;
741 case MONO_TYPE_I1:
742 return mono_defaults.sbyte_class;
743 case MONO_TYPE_U1:
744 return mono_defaults.byte_class;
745 case MONO_TYPE_I2:
746 return mono_defaults.int16_class;
747 case MONO_TYPE_U2:
748 return mono_defaults.uint16_class;
749 case MONO_TYPE_I4:
750 return mono_defaults.int32_class;
751 case MONO_TYPE_U4:
752 return mono_defaults.uint32_class;
753 case MONO_TYPE_I:
754 return mono_defaults.int_class;
755 case MONO_TYPE_U:
756 return mono_defaults.uint_class;
757 case MONO_TYPE_I8:
758 return mono_defaults.int64_class;
759 case MONO_TYPE_U8:
760 return mono_defaults.uint64_class;
761 case MONO_TYPE_R4:
762 return mono_defaults.single_class;
763 case MONO_TYPE_R8:
764 return mono_defaults.double_class;
765 case MONO_TYPE_STRING:
766 return mono_defaults.string_class;
767 default:
768 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
769 g_assert_not_reached ();
772 return NULL;
774 #endif
777 * mono_class_get_ref_info:
779 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
781 gpointer
782 mono_class_get_ref_info (MonoClass *klass)
784 MONO_REQ_GC_UNSAFE_MODE;
786 if (klass->ref_info_handle == 0)
787 return NULL;
788 else
789 return mono_gchandle_get_target (klass->ref_info_handle);
792 void
793 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
795 MONO_REQ_GC_UNSAFE_MODE;
797 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
798 g_assert (klass->ref_info_handle != 0);
801 void
802 mono_class_free_ref_info (MonoClass *klass)
804 MONO_REQ_GC_NEUTRAL_MODE;
806 if (klass->ref_info_handle) {
807 mono_gchandle_free (klass->ref_info_handle);
808 klass->ref_info_handle = 0;
812 static void
813 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
815 MONO_REQ_GC_NEUTRAL_MODE;
817 int i;
818 MonoGenericInst *class_inst;
819 MonoClass *klass;
821 g_assert (gclass);
823 class_inst = gclass->context.class_inst;
825 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
826 klass = gclass->container_class;
827 sigbuffer_add_value (buf, klass->byval_arg.type);
828 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
830 sigbuffer_add_value (buf, class_inst->type_argc);
831 for (i = 0; i < class_inst->type_argc; ++i)
832 encode_type (assembly, class_inst->type_argv [i], buf);
836 static void
837 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
839 MONO_REQ_GC_NEUTRAL_MODE;
841 if (!type) {
842 g_assert_not_reached ();
843 return;
846 if (type->byref)
847 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
849 switch (type->type){
850 case MONO_TYPE_VOID:
851 case MONO_TYPE_BOOLEAN:
852 case MONO_TYPE_CHAR:
853 case MONO_TYPE_I1:
854 case MONO_TYPE_U1:
855 case MONO_TYPE_I2:
856 case MONO_TYPE_U2:
857 case MONO_TYPE_I4:
858 case MONO_TYPE_U4:
859 case MONO_TYPE_I8:
860 case MONO_TYPE_U8:
861 case MONO_TYPE_R4:
862 case MONO_TYPE_R8:
863 case MONO_TYPE_I:
864 case MONO_TYPE_U:
865 case MONO_TYPE_STRING:
866 case MONO_TYPE_OBJECT:
867 case MONO_TYPE_TYPEDBYREF:
868 sigbuffer_add_value (buf, type->type);
869 break;
870 case MONO_TYPE_PTR:
871 sigbuffer_add_value (buf, type->type);
872 encode_type (assembly, type->data.type, buf);
873 break;
874 case MONO_TYPE_SZARRAY:
875 sigbuffer_add_value (buf, type->type);
876 encode_type (assembly, &type->data.klass->byval_arg, buf);
877 break;
878 case MONO_TYPE_VALUETYPE:
879 case MONO_TYPE_CLASS: {
880 MonoClass *k = mono_class_from_mono_type (type);
882 if (k->generic_container) {
883 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
884 encode_generic_class (assembly, gclass, buf);
885 } else {
887 * Make sure we use the correct type.
889 sigbuffer_add_value (buf, k->byval_arg.type);
891 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
892 * otherwise two typerefs could point to the same type, leading to
893 * verification errors.
895 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
897 break;
899 case MONO_TYPE_ARRAY:
900 sigbuffer_add_value (buf, type->type);
901 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
902 sigbuffer_add_value (buf, type->data.array->rank);
903 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
904 sigbuffer_add_value (buf, 0);
905 break;
906 case MONO_TYPE_GENERICINST:
907 encode_generic_class (assembly, type->data.generic_class, buf);
908 break;
909 case MONO_TYPE_VAR:
910 case MONO_TYPE_MVAR:
911 sigbuffer_add_value (buf, type->type);
912 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
913 break;
914 default:
915 g_error ("need to encode type %x", type->type);
919 static void
920 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
922 MONO_REQ_GC_UNSAFE_MODE;
924 if (!type) {
925 sigbuffer_add_value (buf, MONO_TYPE_VOID);
926 return;
929 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
932 static void
933 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
935 MONO_REQ_GC_UNSAFE_MODE;
937 int i;
939 if (modreq) {
940 for (i = 0; i < mono_array_length (modreq); ++i) {
941 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
942 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
943 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
946 if (modopt) {
947 for (i = 0; i < mono_array_length (modopt); ++i) {
948 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
949 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
950 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
955 #ifndef DISABLE_REFLECTION_EMIT
956 static guint32
957 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
959 MONO_REQ_GC_UNSAFE_MODE;
961 SigBuffer buf;
962 int i;
963 guint32 nparams = sig->param_count;
964 guint32 idx;
966 if (!assembly->save)
967 return 0;
969 sigbuffer_init (&buf, 32);
971 * FIXME: vararg, explicit_this, differenc call_conv values...
973 idx = sig->call_convention;
974 if (sig->hasthis)
975 idx |= 0x20; /* hasthis */
976 if (sig->generic_param_count)
977 idx |= 0x10; /* generic */
978 sigbuffer_add_byte (&buf, idx);
979 if (sig->generic_param_count)
980 sigbuffer_add_value (&buf, sig->generic_param_count);
981 sigbuffer_add_value (&buf, nparams);
982 encode_type (assembly, sig->ret, &buf);
983 for (i = 0; i < nparams; ++i) {
984 if (i == sig->sentinelpos)
985 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
986 encode_type (assembly, sig->params [i], &buf);
988 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
989 sigbuffer_free (&buf);
990 return idx;
992 #endif
994 static guint32
995 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
997 MONO_REQ_GC_UNSAFE_MODE;
1000 * FIXME: reuse code from method_encode_signature().
1002 SigBuffer buf;
1003 int i;
1004 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
1005 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1006 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1007 guint32 idx;
1009 sigbuffer_init (&buf, 32);
1010 /* LAMESPEC: all the call conv spec is foobared */
1011 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1012 if (mb->call_conv & 2)
1013 idx |= 0x5; /* vararg */
1014 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1015 idx |= 0x20; /* hasthis */
1016 if (ngparams)
1017 idx |= 0x10; /* generic */
1018 sigbuffer_add_byte (&buf, idx);
1019 if (ngparams)
1020 sigbuffer_add_value (&buf, ngparams);
1021 sigbuffer_add_value (&buf, nparams + notypes);
1022 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1023 encode_reflection_type (assembly, mb->rtype, &buf);
1024 for (i = 0; i < nparams; ++i) {
1025 MonoArray *modreq = NULL;
1026 MonoArray *modopt = NULL;
1027 MonoReflectionType *pt;
1029 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1030 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1031 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1032 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1033 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1034 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1035 encode_reflection_type (assembly, pt, &buf);
1037 if (notypes)
1038 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1039 for (i = 0; i < notypes; ++i) {
1040 MonoReflectionType *pt;
1042 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1043 encode_reflection_type (assembly, pt, &buf);
1046 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1047 sigbuffer_free (&buf);
1048 return idx;
1051 static guint32
1052 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1054 MONO_REQ_GC_UNSAFE_MODE;
1056 MonoDynamicTable *table;
1057 guint32 *values;
1058 guint32 idx, sig_idx;
1059 guint nl = mono_array_length (ilgen->locals);
1060 SigBuffer buf;
1061 int i;
1063 sigbuffer_init (&buf, 32);
1064 sigbuffer_add_value (&buf, 0x07);
1065 sigbuffer_add_value (&buf, nl);
1066 for (i = 0; i < nl; ++i) {
1067 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1069 if (lb->is_pinned)
1070 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1072 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1074 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1075 sigbuffer_free (&buf);
1077 if (assembly->standalonesig_cache == NULL)
1078 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1079 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1080 if (idx)
1081 return idx;
1083 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1084 idx = table->next_idx ++;
1085 table->rows ++;
1086 alloc_table (table, table->rows);
1087 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1089 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1091 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1093 return idx;
1096 static guint32
1097 method_count_clauses (MonoReflectionILGen *ilgen)
1099 MONO_REQ_GC_UNSAFE_MODE;
1101 guint32 num_clauses = 0;
1102 int i;
1104 MonoILExceptionInfo *ex_info;
1105 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1106 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1107 if (ex_info->handlers)
1108 num_clauses += mono_array_length (ex_info->handlers);
1109 else
1110 num_clauses++;
1113 return num_clauses;
1116 #ifndef DISABLE_REFLECTION_EMIT
1117 static MonoExceptionClause*
1118 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1120 MONO_REQ_GC_UNSAFE_MODE;
1122 MonoExceptionClause *clauses;
1123 MonoExceptionClause *clause;
1124 MonoILExceptionInfo *ex_info;
1125 MonoILExceptionBlock *ex_block;
1126 guint32 finally_start;
1127 int i, j, clause_index;;
1129 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1131 clause_index = 0;
1132 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1133 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1134 finally_start = ex_info->start + ex_info->len;
1135 if (!ex_info->handlers)
1136 continue;
1137 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1138 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1139 clause = &(clauses [clause_index]);
1141 clause->flags = ex_block->type;
1142 clause->try_offset = ex_info->start;
1144 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1145 clause->try_len = finally_start - ex_info->start;
1146 else
1147 clause->try_len = ex_info->len;
1148 clause->handler_offset = ex_block->start;
1149 clause->handler_len = ex_block->len;
1150 if (ex_block->extype) {
1151 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1152 } else {
1153 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1154 clause->data.filter_offset = ex_block->filter_offset;
1155 else
1156 clause->data.filter_offset = 0;
1158 finally_start = ex_block->start + ex_block->len;
1160 clause_index ++;
1164 return clauses;
1166 #endif /* !DISABLE_REFLECTION_EMIT */
1169 * method_encode_code:
1171 * @assembly the assembly
1172 * @mb the managed MethodBuilder
1173 * @error set on error
1175 * Note that the return value is not sensible if @error is set.
1177 static guint32
1178 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1180 MONO_REQ_GC_UNSAFE_MODE;
1182 char flags = 0;
1183 guint32 idx;
1184 guint32 code_size;
1185 gint32 max_stack, i;
1186 gint32 num_locals = 0;
1187 gint32 num_exception = 0;
1188 gint maybe_small;
1189 guint32 fat_flags;
1190 char fat_header [12];
1191 guint32 int_value;
1192 guint16 short_value;
1193 guint32 local_sig = 0;
1194 guint32 header_size = 12;
1195 MonoArray *code;
1197 mono_error_init (error);
1199 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1200 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1201 return 0;
1203 /*if (mb->name)
1204 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1205 if (mb->ilgen) {
1206 code = mb->ilgen->code;
1207 code_size = mb->ilgen->code_len;
1208 max_stack = mb->ilgen->max_stack;
1209 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1210 if (mb->ilgen->ex_handlers)
1211 num_exception = method_count_clauses (mb->ilgen);
1212 } else {
1213 code = mb->code;
1214 if (code == NULL){
1215 char *name = mono_string_to_utf8 (mb->name);
1216 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1217 mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1218 g_free (str);
1219 g_free (name);
1220 return 0;
1223 code_size = mono_array_length (code);
1224 max_stack = 8; /* we probably need to run a verifier on the code... */
1227 stream_data_align (&assembly->code);
1229 /* check for exceptions, maxstack, locals */
1230 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1231 if (maybe_small) {
1232 if (code_size < 64 && !(code_size & 1)) {
1233 flags = (code_size << 2) | 0x2;
1234 } else if (code_size < 32 && (code_size & 1)) {
1235 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1236 } else {
1237 goto fat_header;
1239 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1240 /* add to the fixup todo list */
1241 if (mb->ilgen && mb->ilgen->num_token_fixups)
1242 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1243 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1244 return assembly->text_rva + idx;
1246 fat_header:
1247 if (num_locals)
1248 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1250 * FIXME: need to set also the header size in fat_flags.
1251 * (and more sects and init locals flags)
1253 fat_flags = 0x03;
1254 if (num_exception)
1255 fat_flags |= METHOD_HEADER_MORE_SECTS;
1256 if (mb->init_locals)
1257 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1258 fat_header [0] = fat_flags;
1259 fat_header [1] = (header_size / 4 ) << 4;
1260 short_value = GUINT16_TO_LE (max_stack);
1261 memcpy (fat_header + 2, &short_value, 2);
1262 int_value = GUINT32_TO_LE (code_size);
1263 memcpy (fat_header + 4, &int_value, 4);
1264 int_value = GUINT32_TO_LE (local_sig);
1265 memcpy (fat_header + 8, &int_value, 4);
1266 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1267 /* add to the fixup todo list */
1268 if (mb->ilgen && mb->ilgen->num_token_fixups)
1269 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1271 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1272 if (num_exception) {
1273 unsigned char sheader [4];
1274 MonoILExceptionInfo * ex_info;
1275 MonoILExceptionBlock * ex_block;
1276 int j;
1278 stream_data_align (&assembly->code);
1279 /* always use fat format for now */
1280 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1281 num_exception *= 6 * sizeof (guint32);
1282 num_exception += 4; /* include the size of the header */
1283 sheader [1] = num_exception & 0xff;
1284 sheader [2] = (num_exception >> 8) & 0xff;
1285 sheader [3] = (num_exception >> 16) & 0xff;
1286 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1287 /* fat header, so we are already aligned */
1288 /* reverse order */
1289 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1290 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1291 if (ex_info->handlers) {
1292 int finally_start = ex_info->start + ex_info->len;
1293 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1294 guint32 val;
1295 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1296 /* the flags */
1297 val = GUINT32_TO_LE (ex_block->type);
1298 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1299 /* try offset */
1300 val = GUINT32_TO_LE (ex_info->start);
1301 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1302 /* need fault, too, probably */
1303 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1304 val = GUINT32_TO_LE (finally_start - ex_info->start);
1305 else
1306 val = GUINT32_TO_LE (ex_info->len);
1307 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1308 /* handler offset */
1309 val = GUINT32_TO_LE (ex_block->start);
1310 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1311 /* handler len */
1312 val = GUINT32_TO_LE (ex_block->len);
1313 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1314 finally_start = ex_block->start + ex_block->len;
1315 if (ex_block->extype) {
1316 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1317 } else {
1318 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1319 val = ex_block->filter_offset;
1320 else
1321 val = 0;
1323 val = GUINT32_TO_LE (val);
1324 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1325 /*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",
1326 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);*/
1328 } else {
1329 g_error ("No clauses for ex info block %d", i);
1333 return assembly->text_rva + idx;
1336 static guint32
1337 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1339 MONO_REQ_GC_NEUTRAL_MODE;
1341 int i;
1342 MonoDynamicTable *table;
1343 guint32 *values;
1345 table = &assembly->tables [table_idx];
1347 g_assert (col < table->columns);
1349 values = table->values + table->columns;
1350 for (i = 1; i <= table->rows; ++i) {
1351 if (values [col] == token)
1352 return i;
1353 values += table->columns;
1355 return 0;
1359 * LOCKING: Acquires the loader lock.
1361 static MonoCustomAttrInfo*
1362 lookup_custom_attr (MonoImage *image, gpointer member)
1364 MONO_REQ_GC_NEUTRAL_MODE;
1366 MonoCustomAttrInfo* res;
1368 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1370 if (!res)
1371 return NULL;
1373 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1374 res->cached = 0;
1375 return res;
1378 static gboolean
1379 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1381 MONO_REQ_GC_UNSAFE_MODE;
1383 /* FIXME: Need to do more checks */
1384 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1385 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1387 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1388 return FALSE;
1391 return TRUE;
1394 static MonoCustomAttrInfo*
1395 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1397 MONO_REQ_GC_UNSAFE_MODE;
1399 int i, index, count, not_visible;
1400 MonoCustomAttrInfo *ainfo;
1401 MonoReflectionCustomAttr *cattr;
1403 if (!cattrs)
1404 return NULL;
1405 /* FIXME: check in assembly the Run flag is set */
1407 count = mono_array_length (cattrs);
1409 /* Skip nonpublic attributes since MS.NET seems to do the same */
1410 /* FIXME: This needs to be done more globally */
1411 not_visible = 0;
1412 for (i = 0; i < count; ++i) {
1413 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1414 if (!custom_attr_visible (image, cattr))
1415 not_visible ++;
1417 count -= not_visible;
1419 ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1421 ainfo->image = image;
1422 ainfo->num_attrs = count;
1423 ainfo->cached = alloc_img != NULL;
1424 index = 0;
1425 for (i = 0; i < count; ++i) {
1426 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1427 if (custom_attr_visible (image, cattr)) {
1428 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1429 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1430 ainfo->attrs [index].ctor = cattr->ctor->method;
1431 ainfo->attrs [index].data = saved;
1432 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1433 index ++;
1437 return ainfo;
1440 #ifndef DISABLE_REFLECTION_EMIT
1442 * LOCKING: Acquires the loader lock.
1444 static void
1445 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1447 MONO_REQ_GC_UNSAFE_MODE;
1449 MonoCustomAttrInfo *ainfo, *tmp;
1451 if (!cattrs || !mono_array_length (cattrs))
1452 return;
1454 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1456 mono_loader_lock ();
1457 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1458 if (tmp)
1459 mono_custom_attrs_free (tmp);
1460 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1461 mono_loader_unlock ();
1464 #endif
1466 void
1467 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1469 MONO_REQ_GC_NEUTRAL_MODE;
1471 if (ainfo && !ainfo->cached)
1472 g_free (ainfo);
1476 * idx is the table index of the object
1477 * type is one of MONO_CUSTOM_ATTR_*
1479 static gboolean
1480 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1482 MONO_REQ_GC_UNSAFE_MODE;
1484 MonoDynamicTable *table;
1485 MonoReflectionCustomAttr *cattr;
1486 guint32 *values;
1487 guint32 count, i, token;
1488 char blob_size [6];
1489 char *p = blob_size;
1491 mono_error_init (error);
1493 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1494 if (!cattrs)
1495 return TRUE;
1496 count = mono_array_length (cattrs);
1497 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1498 table->rows += count;
1499 alloc_table (table, table->rows);
1500 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1501 idx <<= MONO_CUSTOM_ATTR_BITS;
1502 idx |= type;
1503 for (i = 0; i < count; ++i) {
1504 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1505 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1506 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1507 if (!mono_error_ok (error)) goto fail;
1508 type = mono_metadata_token_index (token);
1509 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1510 switch (mono_metadata_token_table (token)) {
1511 case MONO_TABLE_METHOD:
1512 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1514 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1515 * method, not the one returned by mono_image_create_token ().
1517 mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1518 break;
1519 case MONO_TABLE_MEMBERREF:
1520 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1521 break;
1522 default:
1523 g_warning ("got wrong token in custom attr");
1524 continue;
1526 values [MONO_CUSTOM_ATTR_TYPE] = type;
1527 p = blob_size;
1528 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1529 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1530 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1531 values += MONO_CUSTOM_ATTR_SIZE;
1532 ++table->next_idx;
1535 return TRUE;
1537 fail:
1538 return FALSE;
1541 static void
1542 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1544 MONO_REQ_GC_UNSAFE_MODE;
1546 MonoDynamicTable *table;
1547 guint32 *values;
1548 guint32 count, i, idx;
1549 MonoReflectionPermissionSet *perm;
1551 if (!permissions)
1552 return;
1554 count = mono_array_length (permissions);
1555 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1556 table->rows += count;
1557 alloc_table (table, table->rows);
1559 for (i = 0; i < mono_array_length (permissions); ++i) {
1560 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1562 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1564 idx = mono_metadata_token_index (parent_token);
1565 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1566 switch (mono_metadata_token_table (parent_token)) {
1567 case MONO_TABLE_TYPEDEF:
1568 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1569 break;
1570 case MONO_TABLE_METHOD:
1571 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1572 break;
1573 case MONO_TABLE_ASSEMBLY:
1574 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1575 break;
1576 default:
1577 g_assert_not_reached ();
1580 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1581 values [MONO_DECL_SECURITY_PARENT] = idx;
1582 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1584 ++table->next_idx;
1589 * Fill in the MethodDef and ParamDef tables for a method.
1590 * This is used for both normal methods and constructors.
1592 static gboolean
1593 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1595 MONO_REQ_GC_UNSAFE_MODE;
1597 MonoDynamicTable *table;
1598 guint32 *values;
1599 guint i, count;
1601 mono_error_init (error);
1603 /* room in this table is already allocated */
1604 table = &assembly->tables [MONO_TABLE_METHOD];
1605 *mb->table_idx = table->next_idx ++;
1606 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1607 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1608 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1609 values [MONO_METHOD_FLAGS] = mb->attrs;
1610 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1611 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1612 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1613 if (!mono_error_ok (error))
1614 return FALSE;
1616 table = &assembly->tables [MONO_TABLE_PARAM];
1617 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1619 mono_image_add_decl_security (assembly,
1620 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1622 if (mb->pinfo) {
1623 MonoDynamicTable *mtable;
1624 guint32 *mvalues;
1626 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1627 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1629 count = 0;
1630 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1631 if (mono_array_get (mb->pinfo, gpointer, i))
1632 count++;
1634 table->rows += count;
1635 alloc_table (table, table->rows);
1636 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1637 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1638 MonoReflectionParamBuilder *pb;
1639 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1640 values [MONO_PARAM_FLAGS] = pb->attrs;
1641 values [MONO_PARAM_SEQUENCE] = i;
1642 if (pb->name != NULL) {
1643 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1644 } else {
1645 values [MONO_PARAM_NAME] = 0;
1647 values += MONO_PARAM_SIZE;
1648 if (pb->marshal_info) {
1649 mtable->rows++;
1650 alloc_table (mtable, mtable->rows);
1651 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1652 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1653 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1655 pb->table_idx = table->next_idx++;
1656 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1657 guint32 field_type = 0;
1658 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1659 mtable->rows ++;
1660 alloc_table (mtable, mtable->rows);
1661 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1662 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1663 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1664 mvalues [MONO_CONSTANT_TYPE] = field_type;
1665 mvalues [MONO_CONSTANT_PADDING] = 0;
1671 return TRUE;
1674 #ifndef DISABLE_REFLECTION_EMIT
1675 static gboolean
1676 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1678 MONO_REQ_GC_UNSAFE_MODE;
1680 mono_error_init (error);
1681 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1683 rmb->ilgen = mb->ilgen;
1684 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1685 return_val_if_nok (error, FALSE);
1686 rmb->parameters = mb->parameters;
1687 rmb->generic_params = mb->generic_params;
1688 rmb->generic_container = mb->generic_container;
1689 rmb->opt_types = NULL;
1690 rmb->pinfo = mb->pinfo;
1691 rmb->attrs = mb->attrs;
1692 rmb->iattrs = mb->iattrs;
1693 rmb->call_conv = mb->call_conv;
1694 rmb->code = mb->code;
1695 rmb->type = mb->type;
1696 rmb->name = mb->name;
1697 rmb->table_idx = &mb->table_idx;
1698 rmb->init_locals = mb->init_locals;
1699 rmb->skip_visibility = FALSE;
1700 rmb->return_modreq = mb->return_modreq;
1701 rmb->return_modopt = mb->return_modopt;
1702 rmb->param_modreq = mb->param_modreq;
1703 rmb->param_modopt = mb->param_modopt;
1704 rmb->permissions = mb->permissions;
1705 rmb->mhandle = mb->mhandle;
1706 rmb->nrefs = 0;
1707 rmb->refs = NULL;
1709 if (mb->dll) {
1710 rmb->charset = mb->charset;
1711 rmb->extra_flags = mb->extra_flags;
1712 rmb->native_cc = mb->native_cc;
1713 rmb->dllentry = mb->dllentry;
1714 rmb->dll = mb->dll;
1717 return TRUE;
1720 static gboolean
1721 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1723 MONO_REQ_GC_UNSAFE_MODE;
1725 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1727 mono_error_init (error);
1729 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1731 rmb->ilgen = mb->ilgen;
1732 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1733 return_val_if_nok (error, FALSE);
1734 rmb->parameters = mb->parameters;
1735 rmb->generic_params = NULL;
1736 rmb->generic_container = NULL;
1737 rmb->opt_types = NULL;
1738 rmb->pinfo = mb->pinfo;
1739 rmb->attrs = mb->attrs;
1740 rmb->iattrs = mb->iattrs;
1741 rmb->call_conv = mb->call_conv;
1742 rmb->code = NULL;
1743 rmb->type = mb->type;
1744 rmb->name = mono_string_new (mono_domain_get (), name);
1745 rmb->table_idx = &mb->table_idx;
1746 rmb->init_locals = mb->init_locals;
1747 rmb->skip_visibility = FALSE;
1748 rmb->return_modreq = NULL;
1749 rmb->return_modopt = NULL;
1750 rmb->param_modreq = mb->param_modreq;
1751 rmb->param_modopt = mb->param_modopt;
1752 rmb->permissions = mb->permissions;
1753 rmb->mhandle = mb->mhandle;
1754 rmb->nrefs = 0;
1755 rmb->refs = NULL;
1757 return TRUE;
1760 static void
1761 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1763 MONO_REQ_GC_UNSAFE_MODE;
1765 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1767 rmb->ilgen = mb->ilgen;
1768 rmb->rtype = mb->rtype;
1769 rmb->parameters = mb->parameters;
1770 rmb->generic_params = NULL;
1771 rmb->generic_container = NULL;
1772 rmb->opt_types = NULL;
1773 rmb->pinfo = NULL;
1774 rmb->attrs = mb->attrs;
1775 rmb->iattrs = 0;
1776 rmb->call_conv = mb->call_conv;
1777 rmb->code = NULL;
1778 rmb->type = (MonoObject *) mb->owner;
1779 rmb->name = mb->name;
1780 rmb->table_idx = NULL;
1781 rmb->init_locals = mb->init_locals;
1782 rmb->skip_visibility = mb->skip_visibility;
1783 rmb->return_modreq = NULL;
1784 rmb->return_modopt = NULL;
1785 rmb->param_modreq = NULL;
1786 rmb->param_modopt = NULL;
1787 rmb->permissions = NULL;
1788 rmb->mhandle = mb->mhandle;
1789 rmb->nrefs = 0;
1790 rmb->refs = NULL;
1792 #endif
1794 static gboolean
1795 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1797 MONO_REQ_GC_UNSAFE_MODE;
1799 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1800 MonoDynamicTable *table;
1801 guint32 *values;
1802 guint32 tok;
1803 MonoReflectionMethod *m;
1804 int i;
1806 mono_error_init (error);
1808 if (!mb->override_methods)
1809 return TRUE;
1811 for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1812 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1814 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1815 table->rows ++;
1816 alloc_table (table, table->rows);
1817 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1818 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1819 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1821 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1822 return_val_if_nok (error, FALSE);
1824 switch (mono_metadata_token_table (tok)) {
1825 case MONO_TABLE_MEMBERREF:
1826 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1827 break;
1828 case MONO_TABLE_METHOD:
1829 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1830 break;
1831 default:
1832 g_assert_not_reached ();
1834 values [MONO_METHODIMPL_DECLARATION] = tok;
1837 return TRUE;
1840 #ifndef DISABLE_REFLECTION_EMIT
1841 static gboolean
1842 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1844 MONO_REQ_GC_UNSAFE_MODE;
1846 MonoDynamicTable *table;
1847 guint32 *values;
1848 ReflectionMethodBuilder rmb;
1849 int i;
1851 mono_error_init (error);
1853 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1854 !mono_image_basic_method (&rmb, assembly, error))
1855 return FALSE;
1857 mb->table_idx = *rmb.table_idx;
1859 if (mb->dll) { /* It's a P/Invoke method */
1860 guint32 moduleref;
1861 /* map CharSet values to on-disk values */
1862 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1863 int extra_flags = mb->extra_flags;
1864 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1865 table->rows ++;
1866 alloc_table (table, table->rows);
1867 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1869 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1870 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1871 if (mb->dllentry)
1872 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1873 else
1874 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1875 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1876 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1877 table = &assembly->tables [MONO_TABLE_MODULEREF];
1878 table->rows ++;
1879 alloc_table (table, table->rows);
1880 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1881 values [MONO_IMPLMAP_SCOPE] = table->rows;
1885 if (mb->generic_params) {
1886 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1887 table->rows += mono_array_length (mb->generic_params);
1888 alloc_table (table, table->rows);
1889 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1890 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1892 mono_image_get_generic_param_info (
1893 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1897 return TRUE;
1900 static gboolean
1901 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1903 MONO_REQ_GC_UNSAFE_MODE;
1905 ReflectionMethodBuilder rmb;
1907 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1908 return FALSE;
1910 if (!mono_image_basic_method (&rmb, assembly, error))
1911 return FALSE;
1913 mb->table_idx = *rmb.table_idx;
1915 return TRUE;
1917 #endif
1919 static char*
1920 type_get_fully_qualified_name (MonoType *type)
1922 MONO_REQ_GC_NEUTRAL_MODE;
1924 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1927 static char*
1928 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1930 MONO_REQ_GC_UNSAFE_MODE;
1932 MonoClass *klass;
1933 MonoAssembly *ta;
1935 klass = mono_class_from_mono_type (type);
1936 if (!klass)
1937 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1938 ta = klass->image->assembly;
1939 if (assembly_is_dynamic (ta) || (ta == ass)) {
1940 if (klass->generic_class || klass->generic_container)
1941 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1942 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1943 else
1944 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1947 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1950 #ifndef DISABLE_REFLECTION_EMIT
1951 /*field_image is the image to which the eventual custom mods have been encoded against*/
1952 static guint32
1953 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1955 MONO_REQ_GC_NEUTRAL_MODE;
1957 SigBuffer buf;
1958 guint32 idx, i, token;
1960 if (!assembly->save)
1961 return 0;
1963 sigbuffer_init (&buf, 32);
1965 sigbuffer_add_value (&buf, 0x06);
1966 /* encode custom attributes before the type */
1967 if (type->num_mods) {
1968 for (i = 0; i < type->num_mods; ++i) {
1969 if (field_image) {
1970 MonoError error;
1971 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1972 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1974 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1975 } else {
1976 token = type->modifiers [i].token;
1979 if (type->modifiers [i].required)
1980 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1981 else
1982 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1984 sigbuffer_add_value (&buf, token);
1987 encode_type (assembly, type, &buf);
1988 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1989 sigbuffer_free (&buf);
1990 return idx;
1992 #endif
1994 static guint32
1995 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1997 MONO_REQ_GC_UNSAFE_MODE;
1999 SigBuffer buf;
2000 guint32 idx;
2001 guint32 typespec = 0;
2002 MonoType *type;
2003 MonoClass *klass;
2005 init_type_builder_generics (fb->type);
2007 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
2008 klass = mono_class_from_mono_type (type);
2010 sigbuffer_init (&buf, 32);
2012 sigbuffer_add_value (&buf, 0x06);
2013 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
2014 /* encode custom attributes before the type */
2016 if (klass->generic_container)
2017 typespec = create_typespec (assembly, type);
2019 if (typespec) {
2020 MonoGenericClass *gclass;
2021 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2022 encode_generic_class (assembly, gclass, &buf);
2023 } else {
2024 encode_type (assembly, type, &buf);
2026 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2027 sigbuffer_free (&buf);
2028 return idx;
2031 static guint32
2032 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2034 MONO_REQ_GC_UNSAFE_MODE;
2036 char blob_size [64];
2037 char *b = blob_size;
2038 char *box_val;
2039 char* buf;
2040 guint32 idx = 0, len = 0, dummy = 0;
2042 buf = (char *)g_malloc (64);
2043 if (!val) {
2044 *ret_type = MONO_TYPE_CLASS;
2045 len = 4;
2046 box_val = (char*)&dummy;
2047 } else {
2048 box_val = ((char*)val) + sizeof (MonoObject);
2049 *ret_type = val->vtable->klass->byval_arg.type;
2051 handle_enum:
2052 switch (*ret_type) {
2053 case MONO_TYPE_BOOLEAN:
2054 case MONO_TYPE_U1:
2055 case MONO_TYPE_I1:
2056 len = 1;
2057 break;
2058 case MONO_TYPE_CHAR:
2059 case MONO_TYPE_U2:
2060 case MONO_TYPE_I2:
2061 len = 2;
2062 break;
2063 case MONO_TYPE_U4:
2064 case MONO_TYPE_I4:
2065 case MONO_TYPE_R4:
2066 len = 4;
2067 break;
2068 case MONO_TYPE_U8:
2069 case MONO_TYPE_I8:
2070 len = 8;
2071 break;
2072 case MONO_TYPE_R8:
2073 len = 8;
2074 break;
2075 case MONO_TYPE_VALUETYPE: {
2076 MonoClass *klass = val->vtable->klass;
2078 if (klass->enumtype) {
2079 *ret_type = mono_class_enum_basetype (klass)->type;
2080 goto handle_enum;
2081 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2082 len = 8;
2083 } else
2084 g_error ("we can't encode valuetypes, we should have never reached this line");
2085 break;
2087 case MONO_TYPE_CLASS:
2088 break;
2089 case MONO_TYPE_STRING: {
2090 MonoString *str = (MonoString*)val;
2091 /* there is no signature */
2092 len = str->length * 2;
2093 mono_metadata_encode_value (len, b, &b);
2094 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2096 char *swapped = g_malloc (2 * mono_string_length (str));
2097 const char *p = (const char*)mono_string_chars (str);
2099 swap_with_size (swapped, p, 2, mono_string_length (str));
2100 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2101 g_free (swapped);
2103 #else
2104 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2105 #endif
2107 g_free (buf);
2108 return idx;
2110 case MONO_TYPE_GENERICINST:
2111 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2112 goto handle_enum;
2113 default:
2114 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2117 /* there is no signature */
2118 mono_metadata_encode_value (len, b, &b);
2119 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2120 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2121 swap_with_size (blob_size, box_val, len, 1);
2122 mono_image_add_stream_data (&assembly->blob, blob_size, len);
2123 #else
2124 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2125 #endif
2127 g_free (buf);
2128 return idx;
2131 static guint32
2132 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2134 MONO_REQ_GC_UNSAFE_MODE;
2136 char *str;
2137 SigBuffer buf;
2138 guint32 idx, len;
2140 sigbuffer_init (&buf, 32);
2142 sigbuffer_add_value (&buf, minfo->type);
2144 switch (minfo->type) {
2145 case MONO_NATIVE_BYVALTSTR:
2146 case MONO_NATIVE_BYVALARRAY:
2147 sigbuffer_add_value (&buf, minfo->count);
2148 break;
2149 case MONO_NATIVE_LPARRAY:
2150 if (minfo->eltype || minfo->has_size) {
2151 sigbuffer_add_value (&buf, minfo->eltype);
2152 if (minfo->has_size) {
2153 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2154 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2156 /* LAMESPEC: ElemMult is undocumented */
2157 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2160 break;
2161 case MONO_NATIVE_SAFEARRAY:
2162 if (minfo->eltype)
2163 sigbuffer_add_value (&buf, minfo->eltype);
2164 break;
2165 case MONO_NATIVE_CUSTOM:
2166 if (minfo->guid) {
2167 str = mono_string_to_utf8 (minfo->guid);
2168 len = strlen (str);
2169 sigbuffer_add_value (&buf, len);
2170 sigbuffer_add_mem (&buf, str, len);
2171 g_free (str);
2172 } else {
2173 sigbuffer_add_value (&buf, 0);
2175 /* native type name */
2176 sigbuffer_add_value (&buf, 0);
2177 /* custom marshaler type name */
2178 if (minfo->marshaltype || minfo->marshaltyperef) {
2179 if (minfo->marshaltyperef)
2180 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2181 else
2182 str = mono_string_to_utf8 (minfo->marshaltype);
2183 len = strlen (str);
2184 sigbuffer_add_value (&buf, len);
2185 sigbuffer_add_mem (&buf, str, len);
2186 g_free (str);
2187 } else {
2188 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2189 sigbuffer_add_value (&buf, 0);
2191 if (minfo->mcookie) {
2192 str = mono_string_to_utf8 (minfo->mcookie);
2193 len = strlen (str);
2194 sigbuffer_add_value (&buf, len);
2195 sigbuffer_add_mem (&buf, str, len);
2196 g_free (str);
2197 } else {
2198 sigbuffer_add_value (&buf, 0);
2200 break;
2201 default:
2202 break;
2204 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2205 sigbuffer_free (&buf);
2206 return idx;
2209 static void
2210 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2212 MONO_REQ_GC_UNSAFE_MODE;
2214 MonoDynamicTable *table;
2215 guint32 *values;
2217 /* maybe this fixup should be done in the C# code */
2218 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2219 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2220 table = &assembly->tables [MONO_TABLE_FIELD];
2221 fb->table_idx = table->next_idx ++;
2222 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2223 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2224 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2225 values [MONO_FIELD_FLAGS] = fb->attrs;
2226 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2228 if (fb->offset != -1) {
2229 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2230 table->rows ++;
2231 alloc_table (table, table->rows);
2232 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2233 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2234 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2236 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2237 MonoTypeEnum field_type = (MonoTypeEnum)0;
2238 table = &assembly->tables [MONO_TABLE_CONSTANT];
2239 table->rows ++;
2240 alloc_table (table, table->rows);
2241 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2242 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2243 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2244 values [MONO_CONSTANT_TYPE] = field_type;
2245 values [MONO_CONSTANT_PADDING] = 0;
2247 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2248 guint32 rva_idx;
2249 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2250 table->rows ++;
2251 alloc_table (table, table->rows);
2252 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2253 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2255 * We store it in the code section because it's simpler for now.
2257 if (fb->rva_data) {
2258 if (mono_array_length (fb->rva_data) >= 10)
2259 stream_data_align (&assembly->code);
2260 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2261 } else
2262 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2263 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2265 if (fb->marshal_info) {
2266 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2267 table->rows ++;
2268 alloc_table (table, table->rows);
2269 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2270 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2271 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2275 static guint32
2276 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2278 MONO_REQ_GC_UNSAFE_MODE;
2280 SigBuffer buf;
2281 guint32 nparams = 0;
2282 MonoReflectionMethodBuilder *mb = fb->get_method;
2283 MonoReflectionMethodBuilder *smb = fb->set_method;
2284 guint32 idx, i;
2286 if (mb && mb->parameters)
2287 nparams = mono_array_length (mb->parameters);
2288 if (!mb && smb && smb->parameters)
2289 nparams = mono_array_length (smb->parameters) - 1;
2290 sigbuffer_init (&buf, 32);
2291 if (fb->call_conv & 0x20)
2292 sigbuffer_add_byte (&buf, 0x28);
2293 else
2294 sigbuffer_add_byte (&buf, 0x08);
2295 sigbuffer_add_value (&buf, nparams);
2296 if (mb) {
2297 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2298 for (i = 0; i < nparams; ++i) {
2299 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2300 encode_reflection_type (assembly, pt, &buf);
2302 } else if (smb && smb->parameters) {
2303 /* the property type is the last param */
2304 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2305 for (i = 0; i < nparams; ++i) {
2306 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2307 encode_reflection_type (assembly, pt, &buf);
2309 } else {
2310 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2313 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2314 sigbuffer_free (&buf);
2315 return idx;
2318 static void
2319 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2321 MONO_REQ_GC_UNSAFE_MODE;
2323 MonoDynamicTable *table;
2324 guint32 *values;
2325 guint num_methods = 0;
2326 guint32 semaidx;
2329 * we need to set things in the following tables:
2330 * PROPERTYMAP (info already filled in _get_type_info ())
2331 * PROPERTY (rows already preallocated in _get_type_info ())
2332 * METHOD (method info already done with the generic method code)
2333 * METHODSEMANTICS
2334 * CONSTANT
2336 table = &assembly->tables [MONO_TABLE_PROPERTY];
2337 pb->table_idx = table->next_idx ++;
2338 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2339 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2340 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2341 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2343 /* FIXME: we still don't handle 'other' methods */
2344 if (pb->get_method) num_methods ++;
2345 if (pb->set_method) num_methods ++;
2347 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2348 table->rows += num_methods;
2349 alloc_table (table, table->rows);
2351 if (pb->get_method) {
2352 semaidx = table->next_idx ++;
2353 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2354 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2355 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2356 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2358 if (pb->set_method) {
2359 semaidx = table->next_idx ++;
2360 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2361 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2362 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2363 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2365 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2366 MonoTypeEnum field_type = (MonoTypeEnum)0;
2367 table = &assembly->tables [MONO_TABLE_CONSTANT];
2368 table->rows ++;
2369 alloc_table (table, table->rows);
2370 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2371 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2372 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2373 values [MONO_CONSTANT_TYPE] = field_type;
2374 values [MONO_CONSTANT_PADDING] = 0;
2378 static void
2379 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2381 MONO_REQ_GC_UNSAFE_MODE;
2383 MonoDynamicTable *table;
2384 guint32 *values;
2385 guint num_methods = 0;
2386 guint32 semaidx;
2389 * we need to set things in the following tables:
2390 * EVENTMAP (info already filled in _get_type_info ())
2391 * EVENT (rows already preallocated in _get_type_info ())
2392 * METHOD (method info already done with the generic method code)
2393 * METHODSEMANTICS
2395 table = &assembly->tables [MONO_TABLE_EVENT];
2396 eb->table_idx = table->next_idx ++;
2397 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2398 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2399 values [MONO_EVENT_FLAGS] = eb->attrs;
2400 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2403 * FIXME: we still don't handle 'other' methods
2405 if (eb->add_method) num_methods ++;
2406 if (eb->remove_method) num_methods ++;
2407 if (eb->raise_method) num_methods ++;
2409 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2410 table->rows += num_methods;
2411 alloc_table (table, table->rows);
2413 if (eb->add_method) {
2414 semaidx = table->next_idx ++;
2415 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2416 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2417 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2418 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2420 if (eb->remove_method) {
2421 semaidx = table->next_idx ++;
2422 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2423 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2424 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2425 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2427 if (eb->raise_method) {
2428 semaidx = table->next_idx ++;
2429 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2430 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2431 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2432 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2436 static void
2437 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2439 MONO_REQ_GC_UNSAFE_MODE;
2441 MonoDynamicTable *table;
2442 guint32 num_constraints, i;
2443 guint32 *values;
2444 guint32 table_idx;
2446 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2447 num_constraints = gparam->iface_constraints ?
2448 mono_array_length (gparam->iface_constraints) : 0;
2449 table->rows += num_constraints;
2450 if (gparam->base_type)
2451 table->rows++;
2452 alloc_table (table, table->rows);
2454 if (gparam->base_type) {
2455 table_idx = table->next_idx ++;
2456 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2458 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2459 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2460 assembly, mono_reflection_type_get_handle (gparam->base_type));
2463 for (i = 0; i < num_constraints; i++) {
2464 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2465 gparam->iface_constraints, gpointer, i);
2467 table_idx = table->next_idx ++;
2468 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2470 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2471 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2472 assembly, mono_reflection_type_get_handle (constraint));
2476 static void
2477 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2479 MONO_REQ_GC_UNSAFE_MODE;
2481 GenericParamTableEntry *entry;
2484 * The GenericParam table must be sorted according to the `owner' field.
2485 * We need to do this sorting prior to writing the GenericParamConstraint
2486 * table, since we have to use the final GenericParam table indices there
2487 * and they must also be sorted.
2490 entry = g_new0 (GenericParamTableEntry, 1);
2491 entry->owner = owner;
2492 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2493 MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2494 entry->gparam = gparam;
2496 g_ptr_array_add (assembly->gen_params, entry);
2499 static gboolean
2500 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2502 MONO_REQ_GC_UNSAFE_MODE;
2504 MonoDynamicTable *table;
2505 MonoGenericParam *param;
2506 guint32 *values;
2507 guint32 table_idx;
2509 mono_error_init (error);
2511 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2512 table_idx = table->next_idx ++;
2513 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2515 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2517 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2518 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2519 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2520 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2522 if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2523 return FALSE;
2525 encode_constraints (entry->gparam, table_idx, assembly);
2527 return TRUE;
2530 static guint32
2531 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2533 MONO_REQ_GC_UNSAFE_MODE;
2535 MonoDynamicTable *table;
2536 guint32 token;
2537 guint32 *values;
2538 guint32 cols [MONO_ASSEMBLY_SIZE];
2539 const char *pubkey;
2540 guint32 publen;
2542 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2543 return token;
2545 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2546 table = &assembly->tables [MONO_TABLE_MODULEREF];
2547 token = table->next_idx ++;
2548 table->rows ++;
2549 alloc_table (table, table->rows);
2550 values = table->values + token * MONO_MODULEREF_SIZE;
2551 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2553 token <<= MONO_RESOLUTION_SCOPE_BITS;
2554 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2555 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2557 return token;
2560 if (assembly_is_dynamic (image->assembly))
2561 /* FIXME: */
2562 memset (cols, 0, sizeof (cols));
2563 else {
2564 /* image->assembly->image is the manifest module */
2565 image = image->assembly->image;
2566 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2569 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2570 token = table->next_idx ++;
2571 table->rows ++;
2572 alloc_table (table, table->rows);
2573 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2574 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2575 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2576 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2577 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2578 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2579 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2580 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2581 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2583 if (strcmp ("", image->assembly->aname.culture)) {
2584 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2585 image->assembly->aname.culture);
2588 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2589 guchar pubtoken [9];
2590 pubtoken [0] = 8;
2591 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2592 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2593 } else {
2594 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2596 token <<= MONO_RESOLUTION_SCOPE_BITS;
2597 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2598 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2599 return token;
2602 static guint32
2603 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2605 MONO_REQ_GC_NEUTRAL_MODE;
2607 MonoDynamicTable *table;
2608 guint32 *values;
2609 guint32 token;
2610 SigBuffer buf;
2612 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2613 return token;
2615 sigbuffer_init (&buf, 32);
2616 switch (type->type) {
2617 case MONO_TYPE_FNPTR:
2618 case MONO_TYPE_PTR:
2619 case MONO_TYPE_SZARRAY:
2620 case MONO_TYPE_ARRAY:
2621 case MONO_TYPE_VAR:
2622 case MONO_TYPE_MVAR:
2623 case MONO_TYPE_GENERICINST:
2624 encode_type (assembly, type, &buf);
2625 break;
2626 case MONO_TYPE_CLASS:
2627 case MONO_TYPE_VALUETYPE: {
2628 MonoClass *k = mono_class_from_mono_type (type);
2629 if (!k || !k->generic_container) {
2630 sigbuffer_free (&buf);
2631 return 0;
2633 encode_type (assembly, type, &buf);
2634 break;
2636 default:
2637 sigbuffer_free (&buf);
2638 return 0;
2641 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2642 if (assembly->save) {
2643 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2644 alloc_table (table, table->rows + 1);
2645 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2646 values [MONO_TYPESPEC_SIGNATURE] = token;
2648 sigbuffer_free (&buf);
2650 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2651 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2652 table->next_idx ++;
2653 return token;
2656 static guint32
2657 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2659 MONO_REQ_GC_UNSAFE_MODE;
2661 MonoDynamicTable *table;
2662 guint32 *values;
2663 guint32 token, scope, enclosing;
2664 MonoClass *klass;
2666 /* if the type requires a typespec, we must try that first*/
2667 if (try_typespec && (token = create_typespec (assembly, type)))
2668 return token;
2669 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2670 if (token)
2671 return token;
2672 klass = mono_class_from_mono_type (type);
2673 if (!klass)
2674 klass = mono_class_from_mono_type (type);
2677 * If it's in the same module and not a generic type parameter:
2679 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2680 (type->type != MONO_TYPE_MVAR)) {
2681 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2682 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2683 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2684 return token;
2687 if (klass->nested_in) {
2688 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2689 /* get the typeref idx of the enclosing type */
2690 enclosing >>= MONO_TYPEDEFORREF_BITS;
2691 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2692 } else {
2693 scope = resolution_scope_from_image (assembly, klass->image);
2695 table = &assembly->tables [MONO_TABLE_TYPEREF];
2696 if (assembly->save) {
2697 alloc_table (table, table->rows + 1);
2698 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2699 values [MONO_TYPEREF_SCOPE] = scope;
2700 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2701 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2703 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2704 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2705 table->next_idx ++;
2706 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2707 return token;
2711 * Despite the name, we handle also TypeSpec (with the above helper).
2713 static guint32
2714 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2716 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2719 #ifndef DISABLE_REFLECTION_EMIT
2720 static guint32
2721 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2723 MONO_REQ_GC_NEUTRAL_MODE;
2725 MonoDynamicTable *table;
2726 guint32 *values;
2727 guint32 token, pclass;
2729 switch (parent & MONO_TYPEDEFORREF_MASK) {
2730 case MONO_TYPEDEFORREF_TYPEREF:
2731 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2732 break;
2733 case MONO_TYPEDEFORREF_TYPESPEC:
2734 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2735 break;
2736 case MONO_TYPEDEFORREF_TYPEDEF:
2737 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2738 break;
2739 default:
2740 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2741 return 0;
2743 /* extract the index */
2744 parent >>= MONO_TYPEDEFORREF_BITS;
2746 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2748 if (assembly->save) {
2749 alloc_table (table, table->rows + 1);
2750 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2751 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2752 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2753 values [MONO_MEMBERREF_SIGNATURE] = sig;
2756 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2757 table->next_idx ++;
2759 return token;
2763 * Insert a memberef row into the metadata: the token that point to the memberref
2764 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2765 * mono_image_get_fieldref_token()).
2766 * The sig param is an index to an already built signature.
2768 static guint32
2769 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2771 MONO_REQ_GC_NEUTRAL_MODE;
2773 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2774 return mono_image_add_memberef_row (assembly, parent, name, sig);
2778 static guint32
2779 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2781 MONO_REQ_GC_NEUTRAL_MODE;
2783 guint32 token;
2784 MonoMethodSignature *sig;
2786 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2788 if (create_typespec) {
2789 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2790 if (token)
2791 return token;
2794 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2795 if (token && !create_typespec)
2796 return token;
2798 g_assert (!method->is_inflated);
2799 if (!token) {
2801 * A methodref signature can't contain an unmanaged calling convention.
2803 sig = mono_metadata_signature_dup (mono_method_signature (method));
2804 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2805 sig->call_convention = MONO_CALL_DEFAULT;
2806 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2807 method->name, method_encode_signature (assembly, sig));
2808 g_free (sig);
2809 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2812 if (create_typespec) {
2813 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2814 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2815 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2817 if (assembly->save) {
2818 guint32 *values;
2820 alloc_table (table, table->rows + 1);
2821 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2822 values [MONO_METHODSPEC_METHOD] = token;
2823 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2826 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2827 table->next_idx ++;
2828 /*methodspec and memberef tokens are diferent, */
2829 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2830 return token;
2832 return token;
2835 static guint32
2836 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2838 guint32 token, parent, sig;
2839 ReflectionMethodBuilder rmb;
2840 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2842 mono_error_init (error);
2843 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2844 if (token)
2845 return token;
2847 if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2848 return 0;
2851 * A methodref signature can't contain an unmanaged calling convention.
2852 * Since some flags are encoded as part of call_conv, we need to check against it.
2854 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2855 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2857 sig = method_builder_encode_signature (assembly, &rmb);
2859 if (tb->generic_params)
2860 parent = create_generic_typespec (assembly, tb);
2861 else
2862 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2864 char *name = mono_string_to_utf8 (method->name);
2866 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2867 g_free (name);
2869 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2871 return token;
2874 static guint32
2875 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2876 const gchar *name, guint32 sig)
2878 MonoDynamicTable *table;
2879 guint32 token;
2880 guint32 *values;
2882 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2884 if (assembly->save) {
2885 alloc_table (table, table->rows + 1);
2886 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2887 values [MONO_MEMBERREF_CLASS] = original;
2888 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2889 values [MONO_MEMBERREF_SIGNATURE] = sig;
2892 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2893 table->next_idx ++;
2895 return token;
2898 static guint32
2899 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2901 SigBuffer buf;
2902 int i;
2903 guint32 nparams = mono_array_length (mb->generic_params);
2904 guint32 idx;
2906 if (!assembly->save)
2907 return 0;
2909 sigbuffer_init (&buf, 32);
2911 sigbuffer_add_value (&buf, 0xa);
2912 sigbuffer_add_value (&buf, nparams);
2914 for (i = 0; i < nparams; i++) {
2915 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2916 sigbuffer_add_value (&buf, i);
2919 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2920 sigbuffer_free (&buf);
2921 return idx;
2924 static guint32
2925 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
2927 MonoDynamicTable *table;
2928 guint32 *values;
2929 guint32 token, mtoken = 0;
2931 mono_error_init (error);
2932 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2933 if (token)
2934 return token;
2936 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2938 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2939 if (!mono_error_ok (error))
2940 return 0;
2942 switch (mono_metadata_token_table (mtoken)) {
2943 case MONO_TABLE_MEMBERREF:
2944 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2945 break;
2946 case MONO_TABLE_METHOD:
2947 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2948 break;
2949 default:
2950 g_assert_not_reached ();
2953 if (assembly->save) {
2954 alloc_table (table, table->rows + 1);
2955 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2956 values [MONO_METHODSPEC_METHOD] = mtoken;
2957 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2960 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2961 table->next_idx ++;
2963 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2964 return token;
2967 static guint32
2968 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
2970 guint32 token;
2972 mono_error_init (error);
2974 if (mb->generic_params && create_methodspec)
2975 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
2977 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2978 if (token)
2979 return token;
2981 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2982 if (!mono_error_ok (error))
2983 return 0;
2984 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2985 return token;
2988 static guint32
2989 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
2991 guint32 token, parent, sig;
2992 ReflectionMethodBuilder rmb;
2993 char *name;
2994 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2996 mono_error_init (error);
2998 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2999 if (token)
3000 return token;
3002 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3003 return 0;
3005 if (tb->generic_params)
3006 parent = create_generic_typespec (assembly, tb);
3007 else
3008 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3010 name = mono_string_to_utf8 (rmb.name);
3011 sig = method_builder_encode_signature (assembly, &rmb);
3013 token = mono_image_add_memberef_row (assembly, parent, name, sig);
3015 g_free (name);
3016 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3017 return token;
3019 #endif
3021 static gboolean
3022 is_field_on_inst (MonoClassField *field)
3024 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3028 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3030 static MonoType*
3031 get_field_on_inst_generic_type (MonoClassField *field)
3033 MonoClass *klass, *gtd;
3034 MonoDynamicGenericClass *dgclass;
3035 int field_index;
3037 g_assert (is_field_on_inst (field));
3039 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3041 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3042 field_index = field - dgclass->fields;
3043 return dgclass->field_generic_types [field_index];
3046 klass = field->parent;
3047 gtd = klass->generic_class->container_class;
3049 if (field >= klass->fields && field - klass->fields < klass->field.count) {
3050 field_index = field - klass->fields;
3051 return gtd->fields [field_index].type;
3054 g_assert_not_reached ();
3055 return 0;
3058 #ifndef DISABLE_REFLECTION_EMIT
3059 static guint32
3060 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3062 MonoType *type;
3063 guint32 token;
3065 g_assert (field);
3066 g_assert (field->parent);
3068 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3069 if (token)
3070 return token;
3072 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3073 int index = field - field->parent->fields;
3074 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3075 } else {
3076 if (is_field_on_inst (field))
3077 type = get_field_on_inst_generic_type (field);
3078 else
3079 type = mono_field_get_type (field);
3081 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3082 mono_field_get_name (field),
3083 fieldref_encode_signature (assembly, field->parent->image, type));
3084 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3085 return token;
3088 static guint32
3089 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3091 guint32 token;
3092 MonoClass *klass;
3093 MonoGenericClass *gclass;
3094 MonoType *type;
3095 char *name;
3097 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3098 if (token)
3099 return token;
3100 if (is_sre_field_builder (mono_object_class (f->fb))) {
3101 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3102 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3103 klass = mono_class_from_mono_type (type);
3104 gclass = type->data.generic_class;
3105 g_assert (gclass->is_dynamic);
3107 name = mono_string_to_utf8 (fb->name);
3108 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
3109 field_encode_signature (assembly, fb));
3110 g_free (name);
3111 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3112 guint32 sig;
3113 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3115 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3116 klass = mono_class_from_mono_type (type);
3118 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3119 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3120 } else {
3121 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3122 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3125 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3126 return token;
3129 static guint32
3130 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3132 guint32 sig, token;
3133 MonoClass *klass;
3134 MonoGenericClass *gclass;
3135 MonoType *type;
3137 mono_error_init (error);
3139 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3141 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3142 if (token)
3143 return token;
3145 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3146 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3147 ReflectionMethodBuilder rmb;
3148 char *name;
3150 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3151 klass = mono_class_from_mono_type (type);
3153 gclass = type->data.generic_class;
3154 g_assert (gclass->is_dynamic);
3156 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3157 return 0;
3159 name = mono_string_to_utf8 (rmb.name);
3161 sig = method_builder_encode_signature (assembly, &rmb);
3163 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3164 g_free (name);
3165 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3166 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3168 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3169 klass = mono_class_from_mono_type (type);
3171 sig = method_encode_signature (assembly, mono_method_signature (mm));
3172 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3173 } else {
3174 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3175 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3179 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3180 return token;
3183 static MonoMethod*
3184 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3186 MonoClass *klass;
3187 MonoGenericContext tmp_context;
3188 MonoType **type_argv;
3189 MonoGenericInst *ginst;
3190 MonoMethod *method, *inflated;
3191 int count, i;
3193 mono_error_init (error);
3195 init_type_builder_generics ((MonoObject*)m->inst);
3197 method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3198 return_val_if_nok (error, NULL);
3200 klass = method->klass;
3202 if (m->method_args == NULL)
3203 return method;
3205 if (method->is_inflated)
3206 method = ((MonoMethodInflated *) method)->declaring;
3208 count = mono_array_length (m->method_args);
3210 type_argv = g_new0 (MonoType *, count);
3211 for (i = 0; i < count; i++) {
3212 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3213 type_argv [i] = mono_reflection_type_get_handle (garg);
3215 ginst = mono_metadata_get_generic_inst (count, type_argv);
3216 g_free (type_argv);
3218 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3219 tmp_context.method_inst = ginst;
3221 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3222 mono_error_assert_ok (error);
3223 return inflated;
3226 static guint32
3227 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3229 guint32 sig, token = 0;
3230 MonoType *type;
3231 MonoClass *klass;
3233 mono_error_init (error);
3235 if (m->method_args) {
3236 MonoMethod *inflated;
3238 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3239 return_val_if_nok (error, 0);
3241 if (create_methodspec)
3242 token = mono_image_get_methodspec_token (assembly, inflated);
3243 else
3244 token = mono_image_get_inflated_method_token (assembly, inflated);
3245 return token;
3248 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3249 if (token)
3250 return token;
3252 if (is_sre_method_builder (mono_object_class (m->mb))) {
3253 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3254 MonoGenericClass *gclass;
3255 ReflectionMethodBuilder rmb;
3256 char *name;
3258 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3259 klass = mono_class_from_mono_type (type);
3260 gclass = type->data.generic_class;
3261 g_assert (gclass->is_dynamic);
3263 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3264 return 0;
3266 name = mono_string_to_utf8 (rmb.name);
3268 sig = method_builder_encode_signature (assembly, &rmb);
3270 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3271 g_free (name);
3272 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3273 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3275 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3276 klass = mono_class_from_mono_type (type);
3278 sig = method_encode_signature (assembly, mono_method_signature (mm));
3279 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3280 } else {
3281 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3282 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3285 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3286 return token;
3289 static guint32
3290 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3292 SigBuffer buf;
3293 int i;
3294 guint32 nparams = context->method_inst->type_argc;
3295 guint32 idx;
3297 if (!assembly->save)
3298 return 0;
3300 sigbuffer_init (&buf, 32);
3302 * FIXME: vararg, explicit_this, differenc call_conv values...
3304 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3305 sigbuffer_add_value (&buf, nparams);
3307 for (i = 0; i < nparams; i++)
3308 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3310 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3311 sigbuffer_free (&buf);
3312 return idx;
3315 static guint32
3316 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3318 MonoDynamicTable *table;
3319 guint32 *values;
3320 guint32 token, mtoken = 0, sig;
3321 MonoMethodInflated *imethod;
3322 MonoMethod *declaring;
3324 table = &assembly->tables [MONO_TABLE_METHODSPEC];
3326 g_assert (method->is_inflated);
3327 imethod = (MonoMethodInflated *) method;
3328 declaring = imethod->declaring;
3330 sig = method_encode_signature (assembly, mono_method_signature (declaring));
3331 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3333 if (!mono_method_signature (declaring)->generic_param_count)
3334 return mtoken;
3336 switch (mono_metadata_token_table (mtoken)) {
3337 case MONO_TABLE_MEMBERREF:
3338 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3339 break;
3340 case MONO_TABLE_METHOD:
3341 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3342 break;
3343 default:
3344 g_assert_not_reached ();
3347 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3349 if (assembly->save) {
3350 alloc_table (table, table->rows + 1);
3351 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3352 values [MONO_METHODSPEC_METHOD] = mtoken;
3353 values [MONO_METHODSPEC_SIGNATURE] = sig;
3356 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3357 table->next_idx ++;
3359 return token;
3362 static guint32
3363 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3365 MonoMethodInflated *imethod;
3366 guint32 token;
3368 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3369 if (token)
3370 return token;
3372 g_assert (method->is_inflated);
3373 imethod = (MonoMethodInflated *) method;
3375 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3376 token = method_encode_methodspec (assembly, method);
3377 } else {
3378 guint32 sig = method_encode_signature (
3379 assembly, mono_method_signature (imethod->declaring));
3380 token = mono_image_get_memberref_token (
3381 assembly, &method->klass->byval_arg, method->name, sig);
3384 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3385 return token;
3388 static guint32
3389 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3391 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3392 guint32 sig, token;
3394 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3395 token = mono_image_get_memberref_token (
3396 assembly, &m->klass->byval_arg, m->name, sig);
3398 return token;
3401 static guint32
3402 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3404 MonoDynamicTable *table;
3405 MonoClass *klass;
3406 MonoType *type;
3407 guint32 *values;
3408 guint32 token;
3409 SigBuffer buf;
3410 int count, i;
3413 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3414 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3415 * Because of this, we must not insert it into the `typeref' hash table.
3417 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3418 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3419 if (token)
3420 return token;
3422 sigbuffer_init (&buf, 32);
3424 g_assert (tb->generic_params);
3425 klass = mono_class_from_mono_type (type);
3427 if (tb->generic_container)
3428 mono_reflection_create_generic_class (tb);
3430 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3431 g_assert (klass->generic_container);
3432 sigbuffer_add_value (&buf, klass->byval_arg.type);
3433 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3435 count = mono_array_length (tb->generic_params);
3436 sigbuffer_add_value (&buf, count);
3437 for (i = 0; i < count; i++) {
3438 MonoReflectionGenericParam *gparam;
3440 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3442 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3445 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3447 if (assembly->save) {
3448 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3449 alloc_table (table, table->rows + 1);
3450 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3451 values [MONO_TYPESPEC_SIGNATURE] = token;
3453 sigbuffer_free (&buf);
3455 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3456 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3457 table->next_idx ++;
3458 return token;
3462 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3464 static MonoType*
3465 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3467 int i, count, len, pos;
3468 MonoType *t;
3470 count = 0;
3471 if (modreq)
3472 count += mono_array_length (modreq);
3473 if (modopt)
3474 count += mono_array_length (modopt);
3476 if (count == 0)
3477 return mono_metadata_type_dup (NULL, type);
3479 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3480 t = (MonoType *)g_malloc (len);
3481 memcpy (t, type, MONO_SIZEOF_TYPE);
3483 t->num_mods = count;
3484 pos = 0;
3485 if (modreq) {
3486 for (i = 0; i < mono_array_length (modreq); ++i) {
3487 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3488 t->modifiers [pos].required = 1;
3489 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3490 pos ++;
3493 if (modopt) {
3494 for (i = 0; i < mono_array_length (modopt); ++i) {
3495 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3496 t->modifiers [pos].required = 0;
3497 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3498 pos ++;
3502 return t;
3505 static void
3506 init_type_builder_generics (MonoObject *type)
3508 MonoReflectionTypeBuilder *tb;
3510 if (!is_sre_type_builder(mono_object_class (type)))
3511 return;
3512 tb = (MonoReflectionTypeBuilder *)type;
3514 if (tb && tb->generic_container)
3515 mono_reflection_create_generic_class (tb);
3518 static guint32
3519 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3521 MonoDynamicTable *table;
3522 MonoType *custom = NULL, *type;
3523 guint32 *values;
3524 guint32 token, pclass, parent, sig;
3525 gchar *name;
3527 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3528 if (token)
3529 return token;
3531 /* FIXME: is this call necessary? */
3532 mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3533 name = mono_string_to_utf8 (fb->name);
3535 /*FIXME this is one more layer of ugliness due how types are created.*/
3536 init_type_builder_generics (fb->type);
3538 /* fb->type does not include the custom modifiers */
3539 /* FIXME: We should do this in one place when a fieldbuilder is created */
3540 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3541 if (fb->modreq || fb->modopt)
3542 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3544 sig = fieldref_encode_signature (assembly, NULL, type);
3545 g_free (custom);
3547 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3548 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3550 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3551 parent >>= MONO_TYPEDEFORREF_BITS;
3553 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3555 if (assembly->save) {
3556 alloc_table (table, table->rows + 1);
3557 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3558 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3559 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3560 values [MONO_MEMBERREF_SIGNATURE] = sig;
3563 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3564 table->next_idx ++;
3565 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3566 g_free (name);
3567 return token;
3570 static guint32
3571 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3573 SigBuffer buf;
3574 guint32 nargs;
3575 guint32 i, idx;
3577 if (!assembly->save)
3578 return 0;
3580 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3581 g_assert (helper->type == 2);
3583 if (helper->arguments)
3584 nargs = mono_array_length (helper->arguments);
3585 else
3586 nargs = 0;
3588 sigbuffer_init (&buf, 32);
3590 /* Encode calling convention */
3591 /* Change Any to Standard */
3592 if ((helper->call_conv & 0x03) == 0x03)
3593 helper->call_conv = 0x01;
3594 /* explicit_this implies has_this */
3595 if (helper->call_conv & 0x40)
3596 helper->call_conv &= 0x20;
3598 if (helper->call_conv == 0) { /* Unmanaged */
3599 idx = helper->unmanaged_call_conv - 1;
3600 } else {
3601 /* Managed */
3602 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3603 if (helper->call_conv & 0x02) /* varargs */
3604 idx += 0x05;
3607 sigbuffer_add_byte (&buf, idx);
3608 sigbuffer_add_value (&buf, nargs);
3609 encode_reflection_type (assembly, helper->return_type, &buf);
3610 for (i = 0; i < nargs; ++i) {
3611 MonoArray *modreqs = NULL;
3612 MonoArray *modopts = NULL;
3613 MonoReflectionType *pt;
3615 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3616 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3617 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3618 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3620 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3621 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3622 encode_reflection_type (assembly, pt, &buf);
3624 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3625 sigbuffer_free (&buf);
3627 return idx;
3630 static guint32
3631 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3633 guint32 idx;
3634 MonoDynamicTable *table;
3635 guint32 *values;
3637 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3638 idx = table->next_idx ++;
3639 table->rows ++;
3640 alloc_table (table, table->rows);
3641 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3643 values [MONO_STAND_ALONE_SIGNATURE] =
3644 mono_reflection_encode_sighelper (assembly, helper);
3646 return idx;
3649 static int
3650 reflection_cc_to_file (int call_conv) {
3651 switch (call_conv & 0x3) {
3652 case 0:
3653 case 1: return MONO_CALL_DEFAULT;
3654 case 2: return MONO_CALL_VARARG;
3655 default:
3656 g_assert_not_reached ();
3658 return 0;
3660 #endif /* !DISABLE_REFLECTION_EMIT */
3662 typedef struct {
3663 MonoType *parent;
3664 MonoMethodSignature *sig;
3665 char *name;
3666 guint32 token;
3667 } ArrayMethod;
3669 #ifndef DISABLE_REFLECTION_EMIT
3670 static guint32
3671 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3673 guint32 nparams, i;
3674 GList *tmp;
3675 char *name;
3676 MonoMethodSignature *sig;
3677 ArrayMethod *am;
3678 MonoType *mtype;
3680 name = mono_string_to_utf8 (m->name);
3681 nparams = mono_array_length (m->parameters);
3682 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3683 sig->hasthis = 1;
3684 sig->sentinelpos = -1;
3685 sig->call_convention = reflection_cc_to_file (m->call_conv);
3686 sig->param_count = nparams;
3687 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3688 mtype = mono_reflection_type_get_handle (m->parent);
3689 for (i = 0; i < nparams; ++i)
3690 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3692 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3693 am = (ArrayMethod *)tmp->data;
3694 if (strcmp (name, am->name) == 0 &&
3695 mono_metadata_type_equal (am->parent, mtype) &&
3696 mono_metadata_signature_equal (am->sig, sig)) {
3697 g_free (name);
3698 g_free (sig);
3699 m->table_idx = am->token & 0xffffff;
3700 return am->token;
3703 am = g_new0 (ArrayMethod, 1);
3704 am->name = name;
3705 am->sig = sig;
3706 am->parent = mtype;
3707 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3708 method_encode_signature (assembly, sig));
3709 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3710 m->table_idx = am->token & 0xffffff;
3711 return am->token;
3715 * Insert into the metadata tables all the info about the TypeBuilder tb.
3716 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3718 static gboolean
3719 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3721 MonoDynamicTable *table;
3722 guint *values;
3723 int i, is_object = 0, is_system = 0;
3724 char *n;
3726 mono_error_init (error);
3728 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3729 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3730 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3731 n = mono_string_to_utf8 (tb->name);
3732 if (strcmp (n, "Object") == 0)
3733 is_object++;
3734 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3735 g_free (n);
3736 n = mono_string_to_utf8 (tb->nspace);
3737 if (strcmp (n, "System") == 0)
3738 is_system++;
3739 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3740 g_free (n);
3741 if (tb->parent && !(is_system && is_object) &&
3742 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3743 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3744 } else {
3745 values [MONO_TYPEDEF_EXTENDS] = 0;
3747 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3748 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3751 * if we have explicitlayout or sequentiallayouts, output data in the
3752 * ClassLayout table.
3754 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3755 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3756 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3757 table->rows++;
3758 alloc_table (table, table->rows);
3759 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3760 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3761 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3762 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3765 /* handle interfaces */
3766 if (tb->interfaces) {
3767 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3768 i = table->rows;
3769 table->rows += mono_array_length (tb->interfaces);
3770 alloc_table (table, table->rows);
3771 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3772 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3773 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3774 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3775 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3776 values += MONO_INTERFACEIMPL_SIZE;
3780 /* handle fields */
3781 if (tb->fields) {
3782 table = &assembly->tables [MONO_TABLE_FIELD];
3783 table->rows += tb->num_fields;
3784 alloc_table (table, table->rows);
3785 for (i = 0; i < tb->num_fields; ++i)
3786 mono_image_get_field_info (
3787 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3790 /* handle constructors */
3791 if (tb->ctors) {
3792 table = &assembly->tables [MONO_TABLE_METHOD];
3793 table->rows += mono_array_length (tb->ctors);
3794 alloc_table (table, table->rows);
3795 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3796 if (!mono_image_get_ctor_info (domain,
3797 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3798 assembly, error))
3799 return FALSE;
3803 /* handle methods */
3804 if (tb->methods) {
3805 table = &assembly->tables [MONO_TABLE_METHOD];
3806 table->rows += tb->num_methods;
3807 alloc_table (table, table->rows);
3808 for (i = 0; i < tb->num_methods; ++i) {
3809 if (!mono_image_get_method_info (
3810 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3811 return FALSE;
3815 /* Do the same with properties etc.. */
3816 if (tb->events && mono_array_length (tb->events)) {
3817 table = &assembly->tables [MONO_TABLE_EVENT];
3818 table->rows += mono_array_length (tb->events);
3819 alloc_table (table, table->rows);
3820 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3821 table->rows ++;
3822 alloc_table (table, table->rows);
3823 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3824 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3825 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3826 for (i = 0; i < mono_array_length (tb->events); ++i)
3827 mono_image_get_event_info (
3828 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3830 if (tb->properties && mono_array_length (tb->properties)) {
3831 table = &assembly->tables [MONO_TABLE_PROPERTY];
3832 table->rows += mono_array_length (tb->properties);
3833 alloc_table (table, table->rows);
3834 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3835 table->rows ++;
3836 alloc_table (table, table->rows);
3837 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3838 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3839 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3840 for (i = 0; i < mono_array_length (tb->properties); ++i)
3841 mono_image_get_property_info (
3842 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3845 /* handle generic parameters */
3846 if (tb->generic_params) {
3847 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3848 table->rows += mono_array_length (tb->generic_params);
3849 alloc_table (table, table->rows);
3850 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3851 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3853 mono_image_get_generic_param_info (
3854 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3858 mono_image_add_decl_security (assembly,
3859 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3861 if (tb->subtypes) {
3862 MonoDynamicTable *ntable;
3864 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3865 ntable->rows += mono_array_length (tb->subtypes);
3866 alloc_table (ntable, ntable->rows);
3867 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3869 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3870 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3872 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3873 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3874 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3875 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3876 mono_string_to_utf8 (tb->name), tb->table_idx,
3877 ntable->next_idx, ntable->rows);*/
3878 values += MONO_NESTED_CLASS_SIZE;
3879 ntable->next_idx++;
3883 return TRUE;
3885 #endif
3887 static void
3888 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3890 int i;
3892 mono_ptr_array_append (*types, type);
3894 if (!type->subtypes)
3895 return;
3897 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3898 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3899 collect_types (types, subtype);
3903 static gint
3904 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3906 if ((*type1)->table_idx < (*type2)->table_idx)
3907 return -1;
3908 else
3909 if ((*type1)->table_idx > (*type2)->table_idx)
3910 return 1;
3911 else
3912 return 0;
3915 static gboolean
3916 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3917 int i;
3919 mono_error_init (error);
3920 if (!pinfo)
3921 return TRUE;
3922 for (i = 0; i < mono_array_length (pinfo); ++i) {
3923 MonoReflectionParamBuilder *pb;
3924 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3925 if (!pb)
3926 continue;
3927 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3928 return FALSE;
3931 return TRUE;
3934 static gboolean
3935 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3936 int i;
3938 mono_error_init (error);
3940 if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3941 return FALSE;
3942 if (tb->fields) {
3943 for (i = 0; i < tb->num_fields; ++i) {
3944 MonoReflectionFieldBuilder* fb;
3945 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3946 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3947 return FALSE;
3950 if (tb->events) {
3951 for (i = 0; i < mono_array_length (tb->events); ++i) {
3952 MonoReflectionEventBuilder* eb;
3953 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3954 if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3955 return FALSE;
3958 if (tb->properties) {
3959 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3960 MonoReflectionPropertyBuilder* pb;
3961 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3962 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3963 return FALSE;
3966 if (tb->ctors) {
3967 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3968 MonoReflectionCtorBuilder* cb;
3969 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3970 if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3971 !params_add_cattrs (assembly, cb->pinfo, error))
3972 return FALSE;
3976 if (tb->methods) {
3977 for (i = 0; i < tb->num_methods; ++i) {
3978 MonoReflectionMethodBuilder* mb;
3979 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3980 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3981 !params_add_cattrs (assembly, mb->pinfo, error))
3982 return FALSE;
3986 if (tb->subtypes) {
3987 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3988 if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3989 return FALSE;
3993 return TRUE;
3996 static gboolean
3997 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
3999 int i;
4001 mono_error_init (error);
4003 if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4004 return FALSE;
4006 if (moduleb->global_methods) {
4007 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4008 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4009 if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4010 !params_add_cattrs (assembly, mb->pinfo, error))
4011 return FALSE;
4015 if (moduleb->global_fields) {
4016 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4017 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4018 if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4019 return FALSE;
4023 if (moduleb->types) {
4024 for (i = 0; i < moduleb->num_types; ++i) {
4025 if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4026 return FALSE;
4030 return TRUE;
4033 static void
4034 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4036 MonoDynamicTable *table;
4037 guint32 *values;
4038 char blob_size [6];
4039 guchar hash [20];
4040 char *b = blob_size;
4041 char *dir, *path;
4043 table = &assembly->tables [MONO_TABLE_FILE];
4044 table->rows++;
4045 alloc_table (table, table->rows);
4046 values = table->values + table->next_idx * MONO_FILE_SIZE;
4047 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4048 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4049 if (image_is_dynamic (module->image)) {
4050 /* This depends on the fact that the main module is emitted last */
4051 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4052 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4053 } else {
4054 dir = NULL;
4055 path = g_strdup (module->image->name);
4057 mono_sha1_get_digest_from_file (path, hash);
4058 g_free (dir);
4059 g_free (path);
4060 mono_metadata_encode_value (20, b, &b);
4061 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4062 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4063 table->next_idx ++;
4066 static void
4067 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4069 MonoDynamicTable *table;
4070 int i;
4072 table = &assembly->tables [MONO_TABLE_MODULE];
4073 mb->table_idx = table->next_idx ++;
4074 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4075 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4076 i /= 16;
4077 ++i;
4078 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4079 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4080 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4081 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4084 static guint32
4085 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4086 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4088 MonoDynamicTable *table;
4089 guint32 *values;
4090 guint32 visib, res;
4092 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4093 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4094 return 0;
4096 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4097 table->rows++;
4098 alloc_table (table, table->rows);
4099 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4101 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4102 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4103 if (klass->nested_in)
4104 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4105 else
4106 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4107 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4108 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4110 res = table->next_idx;
4112 table->next_idx ++;
4114 /* Emit nested types */
4115 if (klass->ext && klass->ext->nested_classes) {
4116 GList *tmp;
4118 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4119 mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4122 return res;
4125 static void
4126 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4127 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4129 MonoClass *klass;
4130 guint32 idx, i;
4132 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4134 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4136 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
4137 parent_index, assembly);
4140 * Emit nested types
4141 * We need to do this ourselves since klass->nested_classes is not set up.
4143 if (tb->subtypes) {
4144 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4145 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4149 static void
4150 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4151 guint32 module_index, MonoDynamicImage *assembly)
4153 MonoImage *image = module->image;
4154 MonoTableInfo *t;
4155 guint32 i;
4157 t = &image->tables [MONO_TABLE_TYPEDEF];
4159 for (i = 0; i < t->rows; ++i) {
4160 MonoError error;
4161 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4162 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4164 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4165 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4169 static void
4170 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4172 MonoDynamicTable *table;
4173 guint32 *values;
4174 guint32 scope, scope_idx, impl, current_idx;
4175 gboolean forwarder = TRUE;
4176 gpointer iter = NULL;
4177 MonoClass *nested;
4179 if (klass->nested_in) {
4180 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4181 forwarder = FALSE;
4182 } else {
4183 scope = resolution_scope_from_image (assembly, klass->image);
4184 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4185 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4186 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4189 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4191 table->rows++;
4192 alloc_table (table, table->rows);
4193 current_idx = table->next_idx;
4194 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4196 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4197 values [MONO_EXP_TYPE_TYPEDEF] = 0;
4198 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4199 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4200 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4202 table->next_idx++;
4204 while ((nested = mono_class_get_nested_types (klass, &iter)))
4205 add_exported_type (assemblyb, assembly, nested, current_idx);
4208 static void
4209 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4211 MonoClass *klass;
4212 int i;
4214 if (!assemblyb->type_forwarders)
4215 return;
4217 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4218 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4219 MonoType *type;
4220 if (!t)
4221 continue;
4223 type = mono_reflection_type_get_handle (t);
4224 g_assert (type);
4226 klass = mono_class_from_mono_type (type);
4228 add_exported_type (assemblyb, assembly, klass, 0);
4232 #define align_pointer(base,p)\
4233 do {\
4234 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4235 if (__diff & 3)\
4236 (p) += 4 - (__diff & 3);\
4237 } while (0)
4239 static int
4240 compare_constants (const void *a, const void *b)
4242 const guint32 *a_values = (const guint32 *)a;
4243 const guint32 *b_values = (const guint32 *)b;
4244 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4247 static int
4248 compare_semantics (const void *a, const void *b)
4250 const guint32 *a_values = (const guint32 *)a;
4251 const guint32 *b_values = (const guint32 *)b;
4252 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4253 if (assoc)
4254 return assoc;
4255 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4258 static int
4259 compare_custom_attrs (const void *a, const void *b)
4261 const guint32 *a_values = (const guint32 *)a;
4262 const guint32 *b_values = (const guint32 *)b;
4264 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4267 static int
4268 compare_field_marshal (const void *a, const void *b)
4270 const guint32 *a_values = (const guint32 *)a;
4271 const guint32 *b_values = (const guint32 *)b;
4273 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4276 static int
4277 compare_nested (const void *a, const void *b)
4279 const guint32 *a_values = (const guint32 *)a;
4280 const guint32 *b_values = (const guint32 *)b;
4282 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4285 static int
4286 compare_genericparam (const void *a, const void *b)
4288 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4289 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4291 if ((*b_entry)->owner == (*a_entry)->owner)
4292 return
4293 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4294 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4295 else
4296 return (*a_entry)->owner - (*b_entry)->owner;
4299 static int
4300 compare_declsecurity_attrs (const void *a, const void *b)
4302 const guint32 *a_values = (const guint32 *)a;
4303 const guint32 *b_values = (const guint32 *)b;
4305 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4308 static int
4309 compare_interface_impl (const void *a, const void *b)
4311 const guint32 *a_values = (const guint32 *)a;
4312 const guint32 *b_values = (const guint32 *)b;
4314 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4315 if (klass)
4316 return klass;
4318 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4321 static void
4322 pad_heap (MonoDynamicStream *sh)
4324 if (sh->index & 3) {
4325 int sz = 4 - (sh->index & 3);
4326 memset (sh->data + sh->index, 0, sz);
4327 sh->index += sz;
4331 struct StreamDesc {
4332 const char *name;
4333 MonoDynamicStream *stream;
4337 * build_compressed_metadata() fills in the blob of data that represents the
4338 * raw metadata as it will be saved in the PE file. The five streams are output
4339 * and the metadata tables are comnpressed from the guint32 array representation,
4340 * to the compressed on-disk format.
4342 static gboolean
4343 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4345 MonoDynamicTable *table;
4346 int i;
4347 guint64 valid_mask = 0;
4348 guint64 sorted_mask;
4349 guint32 heapt_size = 0;
4350 guint32 meta_size = 256; /* allow for header and other stuff */
4351 guint32 table_offset;
4352 guint32 ntables = 0;
4353 guint64 *int64val;
4354 guint32 *int32val;
4355 guint16 *int16val;
4356 MonoImage *meta;
4357 unsigned char *p;
4358 struct StreamDesc stream_desc [5];
4360 mono_error_init (error);
4362 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4363 for (i = 0; i < assembly->gen_params->len; i++) {
4364 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4365 if (!write_generic_param_entry (assembly, entry, error))
4366 return FALSE;
4369 stream_desc [0].name = "#~";
4370 stream_desc [0].stream = &assembly->tstream;
4371 stream_desc [1].name = "#Strings";
4372 stream_desc [1].stream = &assembly->sheap;
4373 stream_desc [2].name = "#US";
4374 stream_desc [2].stream = &assembly->us;
4375 stream_desc [3].name = "#Blob";
4376 stream_desc [3].stream = &assembly->blob;
4377 stream_desc [4].name = "#GUID";
4378 stream_desc [4].stream = &assembly->guid;
4380 /* tables that are sorted */
4381 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4382 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4383 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4384 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4385 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4386 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4387 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4389 /* Compute table sizes */
4390 /* the MonoImage has already been created in mono_image_basic_init() */
4391 meta = &assembly->image;
4393 /* sizes should be multiple of 4 */
4394 pad_heap (&assembly->blob);
4395 pad_heap (&assembly->guid);
4396 pad_heap (&assembly->sheap);
4397 pad_heap (&assembly->us);
4399 /* Setup the info used by compute_sizes () */
4400 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4401 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4402 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4404 meta_size += assembly->blob.index;
4405 meta_size += assembly->guid.index;
4406 meta_size += assembly->sheap.index;
4407 meta_size += assembly->us.index;
4409 for (i=0; i < MONO_TABLE_NUM; ++i)
4410 meta->tables [i].rows = assembly->tables [i].rows;
4412 for (i = 0; i < MONO_TABLE_NUM; i++){
4413 if (meta->tables [i].rows == 0)
4414 continue;
4415 valid_mask |= (guint64)1 << i;
4416 ntables ++;
4417 meta->tables [i].row_size = mono_metadata_compute_size (
4418 meta, i, &meta->tables [i].size_bitfield);
4419 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4421 heapt_size += 24; /* #~ header size */
4422 heapt_size += ntables * 4;
4423 /* make multiple of 4 */
4424 heapt_size += 3;
4425 heapt_size &= ~3;
4426 meta_size += heapt_size;
4427 meta->raw_metadata = (char *)g_malloc0 (meta_size);
4428 p = (unsigned char*)meta->raw_metadata;
4429 /* the metadata signature */
4430 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4431 /* version numbers and 4 bytes reserved */
4432 int16val = (guint16*)p;
4433 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4434 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4435 p += 8;
4436 /* version string */
4437 int32val = (guint32*)p;
4438 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4439 p += 4;
4440 memcpy (p, meta->version, strlen (meta->version));
4441 p += GUINT32_FROM_LE (*int32val);
4442 align_pointer (meta->raw_metadata, p);
4443 int16val = (guint16*)p;
4444 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4445 *int16val = GUINT16_TO_LE (5); /* number of streams */
4446 p += 4;
4449 * write the stream info.
4451 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4452 table_offset += 3; table_offset &= ~3;
4454 assembly->tstream.index = heapt_size;
4455 for (i = 0; i < 5; ++i) {
4456 int32val = (guint32*)p;
4457 stream_desc [i].stream->offset = table_offset;
4458 *int32val++ = GUINT32_TO_LE (table_offset);
4459 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4460 table_offset += GUINT32_FROM_LE (*int32val);
4461 table_offset += 3; table_offset &= ~3;
4462 p += 8;
4463 strcpy ((char*)p, stream_desc [i].name);
4464 p += strlen (stream_desc [i].name) + 1;
4465 align_pointer (meta->raw_metadata, p);
4468 * now copy the data, the table stream header and contents goes first.
4470 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4471 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4472 int32val = (guint32*)p;
4473 *int32val = GUINT32_TO_LE (0); /* reserved */
4474 p += 4;
4476 *p++ = 2; /* version */
4477 *p++ = 0;
4479 if (meta->idx_string_wide)
4480 *p |= 0x01;
4481 if (meta->idx_guid_wide)
4482 *p |= 0x02;
4483 if (meta->idx_blob_wide)
4484 *p |= 0x04;
4485 ++p;
4486 *p++ = 1; /* reserved */
4487 int64val = (guint64*)p;
4488 *int64val++ = GUINT64_TO_LE (valid_mask);
4489 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4490 p += 16;
4491 int32val = (guint32*)p;
4492 for (i = 0; i < MONO_TABLE_NUM; i++){
4493 if (meta->tables [i].rows == 0)
4494 continue;
4495 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4497 p = (unsigned char*)int32val;
4499 /* sort the tables that still need sorting */
4500 table = &assembly->tables [MONO_TABLE_CONSTANT];
4501 if (table->rows)
4502 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4503 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4504 if (table->rows)
4505 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4506 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4507 if (table->rows)
4508 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4509 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4510 if (table->rows)
4511 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4512 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4513 if (table->rows)
4514 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4515 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4516 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4517 if (table->rows)
4518 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4519 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4520 if (table->rows)
4521 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4523 /* compress the tables */
4524 for (i = 0; i < MONO_TABLE_NUM; i++){
4525 int row, col;
4526 guint32 *values;
4527 guint32 bitfield = meta->tables [i].size_bitfield;
4528 if (!meta->tables [i].rows)
4529 continue;
4530 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4531 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4532 meta->tables [i].base = (char*)p;
4533 for (row = 1; row <= meta->tables [i].rows; ++row) {
4534 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4535 for (col = 0; col < assembly->tables [i].columns; ++col) {
4536 switch (mono_metadata_table_size (bitfield, col)) {
4537 case 1:
4538 *p++ = values [col];
4539 break;
4540 case 2:
4541 *p++ = values [col] & 0xff;
4542 *p++ = (values [col] >> 8) & 0xff;
4543 break;
4544 case 4:
4545 *p++ = values [col] & 0xff;
4546 *p++ = (values [col] >> 8) & 0xff;
4547 *p++ = (values [col] >> 16) & 0xff;
4548 *p++ = (values [col] >> 24) & 0xff;
4549 break;
4550 default:
4551 g_assert_not_reached ();
4555 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4558 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4559 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4560 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4561 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4562 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4564 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4566 return TRUE;
4570 * Some tables in metadata need to be sorted according to some criteria, but
4571 * when methods and fields are first created with reflection, they may be assigned a token
4572 * that doesn't correspond to the final token they will get assigned after the sorting.
4573 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4574 * with the reflection objects that represent them. Once all the tables are set up, the
4575 * reflection objects will contains the correct table index. fixup_method() will fixup the
4576 * tokens for the method with ILGenerator @ilgen.
4578 static void
4579 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4581 guint32 code_idx = GPOINTER_TO_UINT (value);
4582 MonoReflectionILTokenInfo *iltoken;
4583 MonoReflectionFieldBuilder *field;
4584 MonoReflectionCtorBuilder *ctor;
4585 MonoReflectionMethodBuilder *method;
4586 MonoReflectionTypeBuilder *tb;
4587 MonoReflectionArrayMethod *am;
4588 guint32 i, idx = 0;
4589 unsigned char *target;
4591 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4592 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4593 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4594 switch (target [3]) {
4595 case MONO_TABLE_FIELD:
4596 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4597 field = (MonoReflectionFieldBuilder *)iltoken->member;
4598 idx = field->table_idx;
4599 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4600 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4601 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4602 } else {
4603 g_assert_not_reached ();
4605 break;
4606 case MONO_TABLE_METHOD:
4607 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4608 method = (MonoReflectionMethodBuilder *)iltoken->member;
4609 idx = method->table_idx;
4610 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4611 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4612 idx = ctor->table_idx;
4613 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4614 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4615 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4616 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4617 } else {
4618 g_assert_not_reached ();
4620 break;
4621 case MONO_TABLE_TYPEDEF:
4622 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4623 g_assert_not_reached ();
4624 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4625 idx = tb->table_idx;
4626 break;
4627 case MONO_TABLE_MEMBERREF:
4628 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4629 am = (MonoReflectionArrayMethod*)iltoken->member;
4630 idx = am->table_idx;
4631 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4632 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4633 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4634 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4635 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4636 g_assert (m->klass->generic_class || m->klass->generic_container);
4637 continue;
4638 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4639 continue;
4640 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4641 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4642 g_assert (is_field_on_inst (f));
4643 continue;
4644 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4645 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4646 continue;
4647 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4648 continue;
4649 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4650 continue;
4651 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4652 continue;
4653 } else {
4654 g_assert_not_reached ();
4656 break;
4657 case MONO_TABLE_METHODSPEC:
4658 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4659 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4660 g_assert (mono_method_signature (m)->generic_param_count);
4661 continue;
4662 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4663 continue;
4664 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4665 continue;
4666 } else {
4667 g_assert_not_reached ();
4669 break;
4670 default:
4671 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4673 target [0] = idx & 0xff;
4674 target [1] = (idx >> 8) & 0xff;
4675 target [2] = (idx >> 16) & 0xff;
4680 * fixup_cattrs:
4682 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4683 * value is not known when the table is emitted.
4685 static void
4686 fixup_cattrs (MonoDynamicImage *assembly)
4688 MonoDynamicTable *table;
4689 guint32 *values;
4690 guint32 type, i, idx, token;
4691 MonoObject *ctor;
4693 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4695 for (i = 0; i < table->rows; ++i) {
4696 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4698 type = values [MONO_CUSTOM_ATTR_TYPE];
4699 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4700 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4701 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4702 ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4703 g_assert (ctor);
4705 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4706 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4707 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4708 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4709 } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4710 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4711 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4712 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4718 static void
4719 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4721 MonoDynamicTable *table;
4722 guint32 *values;
4724 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4725 table->rows++;
4726 alloc_table (table, table->rows);
4727 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4728 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4729 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4730 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4731 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4732 table->next_idx++;
4735 static void
4736 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4738 MonoDynamicTable *table;
4739 guint32 *values;
4740 char blob_size [6];
4741 guchar hash [20];
4742 char *b = blob_size;
4743 char *name, *sname;
4744 guint32 idx, offset;
4746 if (rsrc->filename) {
4747 name = mono_string_to_utf8 (rsrc->filename);
4748 sname = g_path_get_basename (name);
4750 table = &assembly->tables [MONO_TABLE_FILE];
4751 table->rows++;
4752 alloc_table (table, table->rows);
4753 values = table->values + table->next_idx * MONO_FILE_SIZE;
4754 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4755 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4756 g_free (sname);
4758 mono_sha1_get_digest_from_file (name, hash);
4759 mono_metadata_encode_value (20, b, &b);
4760 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4761 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4762 g_free (name);
4763 idx = table->next_idx++;
4764 rsrc->offset = 0;
4765 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4766 } else {
4767 char sizebuf [4];
4768 char *data;
4769 guint len;
4770 if (rsrc->data) {
4771 data = mono_array_addr (rsrc->data, char, 0);
4772 len = mono_array_length (rsrc->data);
4773 } else {
4774 data = NULL;
4775 len = 0;
4777 offset = len;
4778 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4779 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4780 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4781 mono_image_add_stream_data (&assembly->resources, data, len);
4783 if (!mb->is_main)
4785 * The entry should be emitted into the MANIFESTRESOURCE table of
4786 * the main module, but that needs to reference the FILE table
4787 * which isn't emitted yet.
4789 return;
4790 else
4791 idx = 0;
4794 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4797 static void
4798 set_version_from_string (MonoString *version, guint32 *values)
4800 gchar *ver, *p, *str;
4801 guint32 i;
4803 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4804 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4805 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4806 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4807 if (!version)
4808 return;
4809 ver = str = mono_string_to_utf8 (version);
4810 for (i = 0; i < 4; ++i) {
4811 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4812 switch (*p) {
4813 case '.':
4814 p++;
4815 break;
4816 case '*':
4817 /* handle Revision and Build */
4818 p++;
4819 break;
4821 ver = p;
4823 g_free (str);
4826 static guint32
4827 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4828 gsize len;
4829 guint32 token = 0;
4830 char blob_size [6];
4831 char *b = blob_size;
4833 if (!pkey)
4834 return token;
4836 len = mono_array_length (pkey);
4837 mono_metadata_encode_value (len, b, &b);
4838 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4839 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4841 assembly->public_key = (guint8 *)g_malloc (len);
4842 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4843 assembly->public_key_len = len;
4845 /* Special case: check for ECMA key (16 bytes) */
4846 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4847 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4848 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4849 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4850 /* minimum key size (in 2.0) is 384 bits */
4851 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4852 } else {
4853 /* FIXME - verifier */
4854 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4855 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4857 assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4859 return token;
4862 static void
4863 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4865 MonoDynamicTable *table;
4866 MonoDynamicImage *assembly;
4867 MonoReflectionAssemblyBuilder *assemblyb;
4868 MonoDomain *domain;
4869 guint32 *values;
4870 int i;
4871 guint32 module_index;
4873 assemblyb = moduleb->assemblyb;
4874 assembly = moduleb->dynamic_image;
4875 domain = mono_object_domain (assemblyb);
4877 /* Emit ASSEMBLY table */
4878 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4879 alloc_table (table, 1);
4880 values = table->values + MONO_ASSEMBLY_SIZE;
4881 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4882 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4883 if (assemblyb->culture) {
4884 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4885 } else {
4886 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4888 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4889 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4890 set_version_from_string (assemblyb->version, values);
4892 /* Emit FILE + EXPORTED_TYPE table */
4893 module_index = 0;
4894 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4895 int j;
4896 MonoReflectionModuleBuilder *file_module =
4897 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4898 if (file_module != moduleb) {
4899 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4900 module_index ++;
4901 if (file_module->types) {
4902 for (j = 0; j < file_module->num_types; ++j) {
4903 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4904 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4909 if (assemblyb->loaded_modules) {
4910 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4911 MonoReflectionModule *file_module =
4912 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4913 mono_image_fill_file_table (domain, file_module, assembly);
4914 module_index ++;
4915 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4918 if (assemblyb->type_forwarders)
4919 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4921 /* Emit MANIFESTRESOURCE table */
4922 module_index = 0;
4923 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4924 int j;
4925 MonoReflectionModuleBuilder *file_module =
4926 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4927 /* The table for the main module is emitted later */
4928 if (file_module != moduleb) {
4929 module_index ++;
4930 if (file_module->resources) {
4931 int len = mono_array_length (file_module->resources);
4932 for (j = 0; j < len; ++j) {
4933 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4934 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4941 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4944 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4945 * for the modulebuilder @moduleb.
4946 * At the end of the process, method and field tokens are fixed up and the
4947 * on-disk compressed metadata representation is created.
4948 * Return TRUE on success, or FALSE on failure and sets @error
4950 gboolean
4951 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4953 MonoDynamicTable *table;
4954 MonoDynamicImage *assembly;
4955 MonoReflectionAssemblyBuilder *assemblyb;
4956 MonoDomain *domain;
4957 MonoPtrArray types;
4958 guint32 *values;
4959 int i, j;
4961 mono_error_init (error);
4963 assemblyb = moduleb->assemblyb;
4964 assembly = moduleb->dynamic_image;
4965 domain = mono_object_domain (assemblyb);
4967 if (assembly->text_rva)
4968 return TRUE;
4970 assembly->text_rva = START_TEXT_RVA;
4972 if (moduleb->is_main) {
4973 mono_image_emit_manifest (moduleb);
4976 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4977 table->rows = 1; /* .<Module> */
4978 table->next_idx++;
4979 alloc_table (table, table->rows);
4981 * Set the first entry.
4983 values = table->values + table->columns;
4984 values [MONO_TYPEDEF_FLAGS] = 0;
4985 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4986 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4987 values [MONO_TYPEDEF_EXTENDS] = 0;
4988 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4989 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4992 * handle global methods
4993 * FIXME: test what to do when global methods are defined in multiple modules.
4995 if (moduleb->global_methods) {
4996 table = &assembly->tables [MONO_TABLE_METHOD];
4997 table->rows += mono_array_length (moduleb->global_methods);
4998 alloc_table (table, table->rows);
4999 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5000 if (!mono_image_get_method_info (
5001 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5002 goto leave;
5005 if (moduleb->global_fields) {
5006 table = &assembly->tables [MONO_TABLE_FIELD];
5007 table->rows += mono_array_length (moduleb->global_fields);
5008 alloc_table (table, table->rows);
5009 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
5010 mono_image_get_field_info (
5011 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
5014 table = &assembly->tables [MONO_TABLE_MODULE];
5015 alloc_table (table, 1);
5016 mono_image_fill_module_table (domain, moduleb, assembly);
5018 /* Collect all types into a list sorted by their table_idx */
5019 mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5021 if (moduleb->types)
5022 for (i = 0; i < moduleb->num_types; ++i) {
5023 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5024 collect_types (&types, type);
5027 mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5028 table = &assembly->tables [MONO_TABLE_TYPEDEF];
5029 table->rows += mono_ptr_array_size (types);
5030 alloc_table (table, table->rows);
5033 * Emit type names + namespaces at one place inside the string heap,
5034 * so load_class_names () needs to touch fewer pages.
5036 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5037 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5038 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5040 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5041 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5042 string_heap_insert_mstring (&assembly->sheap, tb->name);
5045 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5046 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5047 if (!mono_image_get_type_info (domain, type, assembly, error))
5048 goto leave_types;
5052 * table->rows is already set above and in mono_image_fill_module_table.
5054 /* add all the custom attributes at the end, once all the indexes are stable */
5055 if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5056 goto leave_types;
5058 /* CAS assembly permissions */
5059 if (assemblyb->permissions_minimum)
5060 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5061 if (assemblyb->permissions_optional)
5062 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5063 if (assemblyb->permissions_refused)
5064 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5066 if (!module_add_cattrs (assembly, moduleb, error))
5067 goto leave_types;
5069 /* fixup tokens */
5070 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5072 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5073 * the final tokens and don't need another fixup pass. */
5075 if (moduleb->global_methods) {
5076 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5077 MonoReflectionMethodBuilder *mb = mono_array_get (
5078 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5079 if (!mono_image_add_methodimpl (assembly, mb, error))
5080 goto leave_types;
5084 for (i = 0; i < mono_ptr_array_size (types); ++i) {
5085 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5086 if (type->methods) {
5087 for (j = 0; j < type->num_methods; ++j) {
5088 MonoReflectionMethodBuilder *mb = mono_array_get (
5089 type->methods, MonoReflectionMethodBuilder*, j);
5091 if (!mono_image_add_methodimpl (assembly, mb, error))
5092 goto leave_types;
5097 fixup_cattrs (assembly);
5099 leave_types:
5100 mono_ptr_array_destroy (types);
5101 leave:
5103 return mono_error_ok (error);
5106 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5108 gboolean
5109 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5111 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5114 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5117 typedef struct {
5118 guint32 import_lookup_table;
5119 guint32 timestamp;
5120 guint32 forwarder;
5121 guint32 name_rva;
5122 guint32 import_address_table_rva;
5123 } MonoIDT;
5125 typedef struct {
5126 guint32 name_rva;
5127 guint32 flags;
5128 } MonoILT;
5130 #ifndef DISABLE_REFLECTION_EMIT
5133 * mono_image_insert_string:
5134 * @module: module builder object
5135 * @str: a string
5137 * Insert @str into the user string stream of @module.
5139 guint32
5140 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5142 MonoDynamicImage *assembly;
5143 guint32 idx;
5144 char buf [16];
5145 char *b = buf;
5147 if (!module->dynamic_image)
5148 mono_image_module_basic_init (module);
5150 assembly = module->dynamic_image;
5152 if (assembly->save) {
5153 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5154 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5155 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5157 char *swapped = g_malloc (2 * mono_string_length (str));
5158 const char *p = (const char*)mono_string_chars (str);
5160 swap_with_size (swapped, p, 2, mono_string_length (str));
5161 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5162 g_free (swapped);
5164 #else
5165 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5166 #endif
5167 mono_image_add_stream_data (&assembly->us, "", 1);
5168 } else {
5169 idx = assembly->us.index ++;
5172 register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5174 return MONO_TOKEN_STRING | idx;
5177 guint32
5178 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5180 MonoClass *klass;
5181 guint32 token = 0;
5182 MonoMethodSignature *sig;
5184 mono_error_init (error);
5186 klass = obj->vtable->klass;
5187 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5188 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5189 MonoMethodSignature *old;
5190 guint32 sig_token, parent;
5191 int nargs, i;
5193 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5195 nargs = mono_array_length (opt_param_types);
5196 old = mono_method_signature (method);
5197 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5199 sig->hasthis = old->hasthis;
5200 sig->explicit_this = old->explicit_this;
5201 sig->call_convention = old->call_convention;
5202 sig->generic_param_count = old->generic_param_count;
5203 sig->param_count = old->param_count + nargs;
5204 sig->sentinelpos = old->param_count;
5205 sig->ret = old->ret;
5207 for (i = 0; i < old->param_count; i++)
5208 sig->params [i] = old->params [i];
5210 for (i = 0; i < nargs; i++) {
5211 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5212 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5215 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5216 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5217 parent >>= MONO_TYPEDEFORREF_BITS;
5219 parent <<= MONO_MEMBERREF_PARENT_BITS;
5220 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5222 sig_token = method_encode_signature (assembly, sig);
5223 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5224 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5225 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5226 ReflectionMethodBuilder rmb;
5227 guint32 parent, sig_token;
5228 int nopt_args, nparams, ngparams, i;
5230 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5231 goto fail;
5233 rmb.opt_types = opt_param_types;
5234 nopt_args = mono_array_length (opt_param_types);
5236 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5237 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5238 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5240 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5241 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5242 sig->call_convention = rmb.call_conv;
5243 sig->generic_param_count = ngparams;
5244 sig->param_count = nparams + nopt_args;
5245 sig->sentinelpos = nparams;
5246 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5248 for (i = 0; i < nparams; i++) {
5249 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5250 sig->params [i] = mono_reflection_type_get_handle (rt);
5253 for (i = 0; i < nopt_args; i++) {
5254 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5255 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5258 sig_token = method_builder_encode_signature (assembly, &rmb);
5260 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5261 if (!mono_error_ok (error))
5262 goto fail;
5263 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5265 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5266 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5268 char *name = mono_string_to_utf8 (rmb.name);
5269 token = mono_image_get_varargs_method_token (
5270 assembly, parent, name, sig_token);
5271 g_free (name);
5272 } else {
5273 g_error ("requested method token for %s\n", klass->name);
5276 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5277 register_dyn_token (assembly, token, obj);
5278 return token;
5279 fail:
5280 g_assert (!mono_error_ok (error));
5281 return 0;
5285 * mono_image_create_token:
5286 * @assembly: a dynamic assembly
5287 * @obj:
5288 * @register_token: Whenever to register the token in the assembly->tokens hash.
5290 * Get a token to insert in the IL code stream for the given MemberInfo.
5291 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5292 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5293 * entry.
5295 guint32
5296 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
5297 gboolean create_open_instance, gboolean register_token,
5298 MonoError *error)
5300 MonoClass *klass;
5301 guint32 token = 0;
5303 mono_error_init (error);
5305 klass = obj->vtable->klass;
5307 /* Check for user defined reflection objects */
5308 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5309 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5310 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5311 return 0;
5314 if (strcmp (klass->name, "MethodBuilder") == 0) {
5315 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5316 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5318 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5319 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5320 else {
5321 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5322 if (!mono_error_ok (error))
5323 return 0;
5325 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5326 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5327 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5328 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5330 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5331 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5332 else {
5333 token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5334 if (!mono_error_ok (error))
5335 return 0;
5337 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5338 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5339 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5340 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5341 if (tb->generic_params) {
5342 token = mono_image_get_generic_field_token (assembly, fb);
5343 } else {
5344 if (tb->module->dynamic_image == assembly) {
5345 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5346 } else {
5347 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5350 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5351 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5352 if (create_open_instance && tb->generic_params) {
5353 MonoType *type;
5354 init_type_builder_generics (obj);
5355 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5356 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5357 token = mono_metadata_token_from_dor (token);
5358 } else if (tb->module->dynamic_image == assembly) {
5359 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5360 } else {
5361 MonoType *type;
5362 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5363 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5365 } else if (strcmp (klass->name, "MonoType") == 0) {
5366 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5367 MonoClass *mc = mono_class_from_mono_type (type);
5368 token = mono_metadata_token_from_dor (
5369 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5370 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5371 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5372 token = mono_metadata_token_from_dor (
5373 mono_image_typedef_or_ref (assembly, type));
5374 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5375 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5376 token = mono_metadata_token_from_dor (
5377 mono_image_typedef_or_ref (assembly, type));
5378 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5379 strcmp (klass->name, "MonoMethod") == 0 ||
5380 strcmp (klass->name, "MonoGenericMethod") == 0 ||
5381 strcmp (klass->name, "MonoGenericCMethod") == 0) {
5382 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5383 if (m->method->is_inflated) {
5384 if (create_open_instance)
5385 token = mono_image_get_methodspec_token (assembly, m->method);
5386 else
5387 token = mono_image_get_inflated_method_token (assembly, m->method);
5388 } else if ((m->method->klass->image == &assembly->image) &&
5389 !m->method->klass->generic_class) {
5390 static guint32 method_table_idx = 0xffffff;
5391 if (m->method->klass->wastypebuilder) {
5392 /* we use the same token as the one that was assigned
5393 * to the Methodbuilder.
5394 * FIXME: do the equivalent for Fields.
5396 token = m->method->token;
5397 } else {
5399 * Each token should have a unique index, but the indexes are
5400 * assigned by managed code, so we don't know about them. An
5401 * easy solution is to count backwards...
5403 method_table_idx --;
5404 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5406 } else {
5407 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5409 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5410 } else if (strcmp (klass->name, "MonoField") == 0) {
5411 MonoReflectionField *f = (MonoReflectionField *)obj;
5412 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5413 static guint32 field_table_idx = 0xffffff;
5414 field_table_idx --;
5415 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5416 } else {
5417 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5419 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5420 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5421 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5422 token = mono_image_get_array_token (assembly, m);
5423 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5424 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5425 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5426 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5427 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5428 token = mono_metadata_token_from_dor (
5429 mono_image_typedef_or_ref (assembly, type));
5430 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5431 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5432 token = mono_image_get_field_on_inst_token (assembly, f);
5433 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5434 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5435 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5436 if (!mono_error_ok (error))
5437 return 0;
5438 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5439 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5440 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5441 if (!mono_error_ok (error))
5442 return 0;
5443 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5444 MonoReflectionType *type = (MonoReflectionType *)obj;
5445 token = mono_metadata_token_from_dor (
5446 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5447 } else {
5448 g_error ("requested token for %s\n", klass->name);
5451 if (register_token)
5452 mono_image_register_token (assembly, token, obj);
5454 return token;
5458 * mono_image_register_token:
5460 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5461 * the Module.ResolveXXXToken () methods to work.
5463 void
5464 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5466 MonoObject *prev;
5468 dynamic_image_lock (assembly);
5469 prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5470 if (prev) {
5471 /* There could be multiple MethodInfo objects with the same token */
5472 //g_assert (prev == obj);
5473 } else {
5474 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5476 dynamic_image_unlock (assembly);
5479 static MonoDynamicImage*
5480 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5482 static const guchar entrycode [16] = {0xff, 0x25, 0};
5483 MonoDynamicImage *image;
5484 int i;
5486 const char *version;
5488 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5489 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5490 else
5491 version = mono_get_runtime_info ()->runtime_version;
5493 #if HAVE_BOEHM_GC
5494 /* The MonoGHashTable's need GC tracking */
5495 image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5496 #else
5497 image = g_new0 (MonoDynamicImage, 1);
5498 #endif
5500 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5502 /*g_print ("created image %p\n", image);*/
5503 /* keep in sync with image.c */
5504 image->image.name = assembly_name;
5505 image->image.assembly_name = image->image.name; /* they may be different */
5506 image->image.module_name = module_name;
5507 image->image.version = g_strdup (version);
5508 image->image.md_version_major = 1;
5509 image->image.md_version_minor = 1;
5510 image->image.dynamic = TRUE;
5512 image->image.references = g_new0 (MonoAssembly*, 1);
5513 image->image.references [0] = NULL;
5515 mono_image_init (&image->image);
5517 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");
5518 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5519 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5520 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5521 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5522 image->handleref = g_hash_table_new (NULL, NULL);
5523 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");
5524 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5525 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");
5526 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");
5527 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5528 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5529 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5530 image->gen_params = g_ptr_array_new ();
5531 image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5533 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5534 string_heap_init (&image->sheap);
5535 mono_image_add_stream_data (&image->us, "", 1);
5536 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5537 /* import tables... */
5538 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5539 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5540 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5541 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5542 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5543 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5544 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5545 stream_data_align (&image->code);
5547 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5549 for (i=0; i < MONO_TABLE_NUM; ++i) {
5550 image->tables [i].next_idx = 1;
5551 image->tables [i].columns = table_sizes [i];
5554 image->image.assembly = (MonoAssembly*)assembly;
5555 image->run = assembly->run;
5556 image->save = assembly->save;
5557 image->pe_kind = 0x1; /* ILOnly */
5558 image->machine = 0x14c; /* I386 */
5560 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5562 dynamic_images_lock ();
5564 if (!dynamic_images)
5565 dynamic_images = g_ptr_array_new ();
5567 g_ptr_array_add (dynamic_images, image);
5569 dynamic_images_unlock ();
5571 return image;
5573 #endif
5575 static void
5576 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5578 g_free (key);
5581 static void
5582 release_hashtable (MonoGHashTable **hash)
5584 if (*hash) {
5585 mono_g_hash_table_destroy (*hash);
5586 *hash = NULL;
5590 void
5591 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5593 release_hashtable (&image->token_fixups);
5594 release_hashtable (&image->handleref_managed);
5595 release_hashtable (&image->tokens);
5596 release_hashtable (&image->remapped_tokens);
5597 release_hashtable (&image->generic_def_objects);
5598 release_hashtable (&image->methodspec);
5601 // Free dynamic image pass one: Free resources but not image itself
5602 void
5603 mono_dynamic_image_free (MonoDynamicImage *image)
5605 MonoDynamicImage *di = image;
5606 GList *list;
5607 int i;
5609 if (di->methodspec)
5610 mono_g_hash_table_destroy (di->methodspec);
5611 if (di->typespec)
5612 g_hash_table_destroy (di->typespec);
5613 if (di->typeref)
5614 g_hash_table_destroy (di->typeref);
5615 if (di->handleref)
5616 g_hash_table_destroy (di->handleref);
5617 if (di->handleref_managed)
5618 mono_g_hash_table_destroy (di->handleref_managed);
5619 if (di->tokens)
5620 mono_g_hash_table_destroy (di->tokens);
5621 if (di->remapped_tokens)
5622 mono_g_hash_table_destroy (di->remapped_tokens);
5623 if (di->generic_def_objects)
5624 mono_g_hash_table_destroy (di->generic_def_objects);
5625 if (di->blob_cache) {
5626 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5627 g_hash_table_destroy (di->blob_cache);
5629 if (di->standalonesig_cache)
5630 g_hash_table_destroy (di->standalonesig_cache);
5631 for (list = di->array_methods; list; list = list->next) {
5632 ArrayMethod *am = (ArrayMethod *)list->data;
5633 g_free (am->sig);
5634 g_free (am->name);
5635 g_free (am);
5637 g_list_free (di->array_methods);
5638 if (di->gen_params) {
5639 for (i = 0; i < di->gen_params->len; i++) {
5640 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5641 mono_gc_deregister_root ((char*) &entry->gparam);
5642 g_free (entry);
5644 g_ptr_array_free (di->gen_params, TRUE);
5646 if (di->token_fixups)
5647 mono_g_hash_table_destroy (di->token_fixups);
5648 if (di->method_to_table_idx)
5649 g_hash_table_destroy (di->method_to_table_idx);
5650 if (di->field_to_table_idx)
5651 g_hash_table_destroy (di->field_to_table_idx);
5652 if (di->method_aux_hash)
5653 g_hash_table_destroy (di->method_aux_hash);
5654 if (di->vararg_aux_hash)
5655 g_hash_table_destroy (di->vararg_aux_hash);
5656 g_free (di->strong_name);
5657 g_free (di->win32_res);
5658 if (di->public_key)
5659 g_free (di->public_key);
5661 /*g_print ("string heap destroy for image %p\n", di);*/
5662 mono_dynamic_stream_reset (&di->sheap);
5663 mono_dynamic_stream_reset (&di->code);
5664 mono_dynamic_stream_reset (&di->resources);
5665 mono_dynamic_stream_reset (&di->us);
5666 mono_dynamic_stream_reset (&di->blob);
5667 mono_dynamic_stream_reset (&di->tstream);
5668 mono_dynamic_stream_reset (&di->guid);
5669 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5670 g_free (di->tables [i].values);
5673 dynamic_images_lock ();
5675 if (dynamic_images)
5676 g_ptr_array_remove (dynamic_images, di);
5678 dynamic_images_unlock ();
5681 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5682 void
5683 mono_dynamic_image_free_image (MonoDynamicImage *image)
5685 /* See create_dynamic_mono_image () */
5686 #if HAVE_BOEHM_GC
5687 /* Allocated using GC_MALLOC */
5688 #else
5689 g_free (image);
5690 #endif
5693 #ifndef DISABLE_REFLECTION_EMIT
5696 * mono_image_basic_init:
5697 * @assembly: an assembly builder object
5699 * Create the MonoImage that represents the assembly builder and setup some
5700 * of the helper hash table and the basic metadata streams.
5702 void
5703 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5705 MonoDynamicAssembly *assembly;
5706 MonoDynamicImage *image;
5707 MonoDomain *domain = mono_object_domain (assemblyb);
5709 if (assemblyb->dynamic_assembly)
5710 return;
5712 #if HAVE_BOEHM_GC
5713 /* assembly->assembly.image might be GC allocated */
5714 assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5715 #else
5716 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5717 #endif
5719 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5721 assembly->assembly.ref_count = 1;
5722 assembly->assembly.dynamic = TRUE;
5723 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5724 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5725 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5726 if (assemblyb->culture)
5727 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5728 else
5729 assembly->assembly.aname.culture = g_strdup ("");
5731 if (assemblyb->version) {
5732 char *vstr = mono_string_to_utf8 (assemblyb->version);
5733 char **version = g_strsplit (vstr, ".", 4);
5734 char **parts = version;
5735 assembly->assembly.aname.major = atoi (*parts++);
5736 assembly->assembly.aname.minor = atoi (*parts++);
5737 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5738 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5740 g_strfreev (version);
5741 g_free (vstr);
5742 } else {
5743 assembly->assembly.aname.major = 0;
5744 assembly->assembly.aname.minor = 0;
5745 assembly->assembly.aname.build = 0;
5746 assembly->assembly.aname.revision = 0;
5749 assembly->run = assemblyb->access != 2;
5750 assembly->save = assemblyb->access != 1;
5751 assembly->domain = domain;
5753 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5754 image->initial_image = TRUE;
5755 assembly->assembly.aname.name = image->image.name;
5756 assembly->assembly.image = &image->image;
5757 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5758 /* -1 to correct for the trailing NULL byte */
5759 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5760 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5762 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5765 mono_domain_assemblies_lock (domain);
5766 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5767 mono_domain_assemblies_unlock (domain);
5769 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5771 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5773 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5776 #endif /* !DISABLE_REFLECTION_EMIT */
5778 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5780 static int
5781 calc_section_size (MonoDynamicImage *assembly)
5783 int nsections = 0;
5785 /* alignment constraints */
5786 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5787 g_assert ((assembly->code.index % 4) == 0);
5788 assembly->meta_size += 3;
5789 assembly->meta_size &= ~3;
5790 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5791 g_assert ((assembly->resources.index % 4) == 0);
5793 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5794 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5795 nsections++;
5797 if (assembly->win32_res) {
5798 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5800 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5801 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5802 nsections++;
5805 assembly->sections [MONO_SECTION_RELOC].size = 12;
5806 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5807 nsections++;
5809 return nsections;
5812 typedef struct {
5813 guint32 id;
5814 guint32 offset;
5815 GSList *children;
5816 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5817 } ResTreeNode;
5819 static int
5820 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5822 ResTreeNode *t1 = (ResTreeNode*)a;
5823 ResTreeNode *t2 = (ResTreeNode*)b;
5825 return t1->id - t2->id;
5829 * resource_tree_create:
5831 * Organize the resources into a resource tree.
5833 static ResTreeNode *
5834 resource_tree_create (MonoArray *win32_resources)
5836 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5837 GSList *l;
5838 int i;
5840 tree = g_new0 (ResTreeNode, 1);
5842 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5843 MonoReflectionWin32Resource *win32_res =
5844 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5846 /* Create node */
5848 /* FIXME: BUG: this stores managed references in unmanaged memory */
5849 lang_node = g_new0 (ResTreeNode, 1);
5850 lang_node->id = win32_res->lang_id;
5851 lang_node->win32_res = win32_res;
5853 /* Create type node if neccesary */
5854 type_node = NULL;
5855 for (l = tree->children; l; l = l->next)
5856 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5857 type_node = (ResTreeNode*)l->data;
5858 break;
5861 if (!type_node) {
5862 type_node = g_new0 (ResTreeNode, 1);
5863 type_node->id = win32_res->res_type;
5866 * The resource types have to be sorted otherwise
5867 * Windows Explorer can't display the version information.
5869 tree->children = g_slist_insert_sorted (tree->children,
5870 type_node, resource_tree_compare_by_id);
5873 /* Create res node if neccesary */
5874 res_node = NULL;
5875 for (l = type_node->children; l; l = l->next)
5876 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5877 res_node = (ResTreeNode*)l->data;
5878 break;
5881 if (!res_node) {
5882 res_node = g_new0 (ResTreeNode, 1);
5883 res_node->id = win32_res->res_id;
5884 type_node->children = g_slist_append (type_node->children, res_node);
5887 res_node->children = g_slist_append (res_node->children, lang_node);
5890 return tree;
5894 * resource_tree_encode:
5896 * Encode the resource tree into the format used in the PE file.
5898 static void
5899 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5901 char *entries;
5902 MonoPEResourceDir dir;
5903 MonoPEResourceDirEntry dir_entry;
5904 MonoPEResourceDataEntry data_entry;
5905 GSList *l;
5906 guint32 res_id_entries;
5909 * For the format of the resource directory, see the article
5910 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5911 * Matt Pietrek
5914 memset (&dir, 0, sizeof (dir));
5915 memset (&dir_entry, 0, sizeof (dir_entry));
5916 memset (&data_entry, 0, sizeof (data_entry));
5918 g_assert (sizeof (dir) == 16);
5919 g_assert (sizeof (dir_entry) == 8);
5920 g_assert (sizeof (data_entry) == 16);
5922 node->offset = p - begin;
5924 /* IMAGE_RESOURCE_DIRECTORY */
5925 res_id_entries = g_slist_length (node->children);
5926 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5928 memcpy (p, &dir, sizeof (dir));
5929 p += sizeof (dir);
5931 /* Reserve space for entries */
5932 entries = p;
5933 p += sizeof (dir_entry) * res_id_entries;
5935 /* Write children */
5936 for (l = node->children; l; l = l->next) {
5937 ResTreeNode *child = (ResTreeNode*)l->data;
5939 if (child->win32_res) {
5940 guint32 size;
5942 child->offset = p - begin;
5944 /* IMAGE_RESOURCE_DATA_ENTRY */
5945 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5946 size = mono_array_length (child->win32_res->res_data);
5947 data_entry.rde_size = GUINT32_TO_LE (size);
5949 memcpy (p, &data_entry, sizeof (data_entry));
5950 p += sizeof (data_entry);
5952 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5953 p += size;
5954 } else {
5955 resource_tree_encode (child, begin, p, &p);
5959 /* IMAGE_RESOURCE_ENTRY */
5960 for (l = node->children; l; l = l->next) {
5961 ResTreeNode *child = (ResTreeNode*)l->data;
5963 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5964 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5966 memcpy (entries, &dir_entry, sizeof (dir_entry));
5967 entries += sizeof (dir_entry);
5970 *endbuf = p;
5973 static void
5974 resource_tree_free (ResTreeNode * node)
5976 GSList * list;
5977 for (list = node->children; list; list = list->next)
5978 resource_tree_free ((ResTreeNode*)list->data);
5979 g_slist_free(node->children);
5980 g_free (node);
5983 static void
5984 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5986 char *buf;
5987 char *p;
5988 guint32 size, i;
5989 MonoReflectionWin32Resource *win32_res;
5990 ResTreeNode *tree;
5992 if (!assemblyb->win32_resources)
5993 return;
5996 * Resources are stored in a three level tree inside the PE file.
5997 * - level one contains a node for each type of resource
5998 * - level two contains a node for each resource
5999 * - level three contains a node for each instance of a resource for a
6000 * specific language.
6003 tree = resource_tree_create (assemblyb->win32_resources);
6005 /* Estimate the size of the encoded tree */
6006 size = 0;
6007 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6008 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6009 size += mono_array_length (win32_res->res_data);
6011 /* Directory structure */
6012 size += mono_array_length (assemblyb->win32_resources) * 256;
6013 p = buf = (char *)g_malloc (size);
6015 resource_tree_encode (tree, p, p, &p);
6017 g_assert (p - buf <= size);
6019 assembly->win32_res = (char *)g_malloc (p - buf);
6020 assembly->win32_res_size = p - buf;
6021 memcpy (assembly->win32_res, buf, p - buf);
6023 g_free (buf);
6024 resource_tree_free (tree);
6027 static void
6028 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6030 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6031 int i;
6033 p += sizeof (MonoPEResourceDir);
6034 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6035 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6036 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6037 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6038 fixup_resource_directory (res_section, child, rva);
6039 } else {
6040 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6041 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6044 p += sizeof (MonoPEResourceDirEntry);
6048 static void
6049 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6051 guint32 dummy;
6052 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6053 g_error ("WriteFile returned %d\n", GetLastError ());
6057 * mono_image_create_pefile:
6058 * @mb: a module builder object
6060 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6061 * assembly->pefile where it can be easily retrieved later in chunks.
6063 gboolean
6064 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6066 MonoMSDOSHeader *msdos;
6067 MonoDotNetHeader *header;
6068 MonoSectionTable *section;
6069 MonoCLIHeader *cli_header;
6070 guint32 size, image_size, virtual_base, text_offset;
6071 guint32 header_start, section_start, file_offset, virtual_offset;
6072 MonoDynamicImage *assembly;
6073 MonoReflectionAssemblyBuilder *assemblyb;
6074 MonoDynamicStream pefile_stream = {0};
6075 MonoDynamicStream *pefile = &pefile_stream;
6076 int i, nsections;
6077 guint32 *rva, value;
6078 guchar *p;
6079 static const unsigned char msheader[] = {
6080 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6081 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6083 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6084 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6085 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6086 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6087 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6090 mono_error_init (error);
6092 assemblyb = mb->assemblyb;
6094 mono_image_basic_init (assemblyb);
6095 assembly = mb->dynamic_image;
6097 assembly->pe_kind = assemblyb->pe_kind;
6098 assembly->machine = assemblyb->machine;
6099 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6100 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6102 if (!mono_image_build_metadata (mb, error))
6103 return FALSE;
6106 if (mb->is_main && assemblyb->resources) {
6107 int len = mono_array_length (assemblyb->resources);
6108 for (i = 0; i < len; ++i)
6109 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6112 if (mb->resources) {
6113 int len = mono_array_length (mb->resources);
6114 for (i = 0; i < len; ++i)
6115 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6118 if (!build_compressed_metadata (assembly, error))
6119 return FALSE;
6121 if (mb->is_main)
6122 assembly_add_win32_resources (assembly, assemblyb);
6124 nsections = calc_section_size (assembly);
6126 /* The DOS header and stub */
6127 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6128 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6130 /* the dotnet header */
6131 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6133 /* the section tables */
6134 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6136 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6137 virtual_offset = VIRT_ALIGN;
6138 image_size = 0;
6140 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6141 if (!assembly->sections [i].size)
6142 continue;
6143 /* align offsets */
6144 file_offset += FILE_ALIGN - 1;
6145 file_offset &= ~(FILE_ALIGN - 1);
6146 virtual_offset += VIRT_ALIGN - 1;
6147 virtual_offset &= ~(VIRT_ALIGN - 1);
6149 assembly->sections [i].offset = file_offset;
6150 assembly->sections [i].rva = virtual_offset;
6152 file_offset += assembly->sections [i].size;
6153 virtual_offset += assembly->sections [i].size;
6154 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6157 file_offset += FILE_ALIGN - 1;
6158 file_offset &= ~(FILE_ALIGN - 1);
6160 image_size += section_start + sizeof (MonoSectionTable) * nsections;
6162 /* back-patch info */
6163 msdos = (MonoMSDOSHeader*)pefile->data;
6164 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6166 header = (MonoDotNetHeader*)(pefile->data + header_start);
6167 header->pesig [0] = 'P';
6168 header->pesig [1] = 'E';
6170 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6171 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6172 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6173 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6174 if (assemblyb->pekind == 1) {
6175 /* it's a dll */
6176 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6177 } else {
6178 /* it's an exe */
6179 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6182 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6184 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6185 header->pe.pe_major = 6;
6186 header->pe.pe_minor = 0;
6187 size = assembly->sections [MONO_SECTION_TEXT].size;
6188 size += FILE_ALIGN - 1;
6189 size &= ~(FILE_ALIGN - 1);
6190 header->pe.pe_code_size = GUINT32_FROM_LE(size);
6191 size = assembly->sections [MONO_SECTION_RSRC].size;
6192 size += FILE_ALIGN - 1;
6193 size &= ~(FILE_ALIGN - 1);
6194 header->pe.pe_data_size = GUINT32_FROM_LE(size);
6195 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6196 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6197 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6198 /* pe_rva_entry_point always at the beginning of the text section */
6199 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6201 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6202 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6203 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6204 header->nt.pe_os_major = GUINT16_FROM_LE (4);
6205 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6206 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6207 size = section_start;
6208 size += FILE_ALIGN - 1;
6209 size &= ~(FILE_ALIGN - 1);
6210 header->nt.pe_header_size = GUINT32_FROM_LE (size);
6211 size = image_size;
6212 size += VIRT_ALIGN - 1;
6213 size &= ~(VIRT_ALIGN - 1);
6214 header->nt.pe_image_size = GUINT32_FROM_LE (size);
6217 // Translate the PEFileKind value to the value expected by the Windows loader
6220 short kind;
6223 // PEFileKinds.Dll == 1
6224 // PEFileKinds.ConsoleApplication == 2
6225 // PEFileKinds.WindowApplication == 3
6227 // need to get:
6228 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6229 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6231 if (assemblyb->pekind == 3)
6232 kind = 2;
6233 else
6234 kind = 3;
6236 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6238 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6239 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6240 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6241 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6242 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6243 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6245 /* fill data directory entries */
6247 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6248 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6250 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6251 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6253 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6254 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6255 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6256 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6257 /* patch entrypoint name */
6258 if (assemblyb->pekind == 1)
6259 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6260 else
6261 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6262 /* patch imported function RVA name */
6263 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6264 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6266 /* the import table */
6267 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6268 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6269 /* patch imported dll RVA name and other entries in the dir */
6270 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6271 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6272 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6273 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6274 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6275 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6277 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6278 value = (assembly->text_rva + assembly->imp_names_offset);
6279 *p++ = (value) & 0xff;
6280 *p++ = (value >> 8) & (0xff);
6281 *p++ = (value >> 16) & (0xff);
6282 *p++ = (value >> 24) & (0xff);
6284 /* the CLI header info */
6285 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6286 cli_header->ch_size = GUINT32_FROM_LE (72);
6287 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6288 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6289 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6290 if (assemblyb->entry_point) {
6291 guint32 table_idx = 0;
6292 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6293 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6294 table_idx = methodb->table_idx;
6295 } else {
6296 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6298 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6299 } else {
6300 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6302 /* The embedded managed resources */
6303 text_offset = assembly->text_rva + assembly->code.index;
6304 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6305 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6306 text_offset += assembly->resources.index;
6307 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6308 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6309 text_offset += assembly->meta_size;
6310 if (assembly->strong_name_size) {
6311 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6312 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6313 text_offset += assembly->strong_name_size;
6316 /* write the section tables and section content */
6317 section = (MonoSectionTable*)(pefile->data + section_start);
6318 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6319 static const char section_names [][7] = {
6320 ".text", ".rsrc", ".reloc"
6322 if (!assembly->sections [i].size)
6323 continue;
6324 strcpy (section->st_name, section_names [i]);
6325 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6326 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6327 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6328 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6329 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6330 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6331 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6332 section ++;
6335 checked_write_file (file, pefile->data, pefile->index);
6337 mono_dynamic_stream_reset (pefile);
6339 for (i = 0; i < MONO_SECTION_MAX; ++i) {
6340 if (!assembly->sections [i].size)
6341 continue;
6343 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6344 g_error ("SetFilePointer returned %d\n", GetLastError ());
6346 switch (i) {
6347 case MONO_SECTION_TEXT:
6348 /* patch entry point */
6349 p = (guchar*)(assembly->code.data + 2);
6350 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6351 *p++ = (value) & 0xff;
6352 *p++ = (value >> 8) & 0xff;
6353 *p++ = (value >> 16) & 0xff;
6354 *p++ = (value >> 24) & 0xff;
6356 checked_write_file (file, assembly->code.data, assembly->code.index);
6357 checked_write_file (file, assembly->resources.data, assembly->resources.index);
6358 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6359 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6362 g_free (assembly->image.raw_metadata);
6363 break;
6364 case MONO_SECTION_RELOC: {
6365 struct {
6366 guint32 page_rva;
6367 guint32 block_size;
6368 guint16 type_and_offset;
6369 guint16 term;
6370 } reloc;
6372 g_assert (sizeof (reloc) == 12);
6374 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6375 reloc.block_size = GUINT32_FROM_LE (12);
6378 * the entrypoint is always at the start of the text section
6379 * 3 is IMAGE_REL_BASED_HIGHLOW
6380 * 2 is patch_size_rva - text_rva
6382 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6383 reloc.term = 0;
6385 checked_write_file (file, &reloc, sizeof (reloc));
6387 break;
6389 case MONO_SECTION_RSRC:
6390 if (assembly->win32_res) {
6392 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6393 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6394 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6396 break;
6397 default:
6398 g_assert_not_reached ();
6402 /* check that the file is properly padded */
6403 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6404 g_error ("SetFilePointer returned %d\n", GetLastError ());
6405 if (! SetEndOfFile (file))
6406 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6408 mono_dynamic_stream_reset (&assembly->code);
6409 mono_dynamic_stream_reset (&assembly->us);
6410 mono_dynamic_stream_reset (&assembly->blob);
6411 mono_dynamic_stream_reset (&assembly->guid);
6412 mono_dynamic_stream_reset (&assembly->sheap);
6414 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6415 g_hash_table_destroy (assembly->blob_cache);
6416 assembly->blob_cache = NULL;
6418 return TRUE;
6421 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6423 gboolean
6424 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6426 g_assert_not_reached ();
6429 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6431 #ifndef DISABLE_REFLECTION_EMIT
6433 MonoReflectionModule *
6434 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6436 MonoError error;
6437 MonoReflectionModule *result = NULL;
6438 char *name;
6439 MonoImage *image;
6440 MonoImageOpenStatus status;
6441 MonoDynamicAssembly *assembly;
6442 guint32 module_count;
6443 MonoImage **new_modules;
6444 gboolean *new_modules_loaded;
6446 name = mono_string_to_utf8 (fileName);
6448 image = mono_image_open (name, &status);
6449 if (!image) {
6450 MonoException *exc;
6451 if (status == MONO_IMAGE_ERROR_ERRNO)
6452 exc = mono_get_exception_file_not_found (fileName);
6453 else
6454 exc = mono_get_exception_bad_image_format (name);
6455 g_free (name);
6456 mono_raise_exception (exc);
6459 g_free (name);
6461 assembly = ab->dynamic_assembly;
6462 image->assembly = (MonoAssembly*)assembly;
6464 module_count = image->assembly->image->module_count;
6465 new_modules = g_new0 (MonoImage *, module_count + 1);
6466 new_modules_loaded = g_new0 (gboolean, module_count + 1);
6468 if (image->assembly->image->modules)
6469 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6470 if (image->assembly->image->modules_loaded)
6471 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6472 new_modules [module_count] = image;
6473 new_modules_loaded [module_count] = TRUE;
6474 mono_image_addref (image);
6476 g_free (image->assembly->image->modules);
6477 image->assembly->image->modules = new_modules;
6478 image->assembly->image->modules_loaded = new_modules_loaded;
6479 image->assembly->image->module_count ++;
6481 mono_assembly_load_references (image, &status);
6482 if (status) {
6483 mono_image_close (image);
6484 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6487 result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6488 mono_error_raise_exception (&error); /* FIXME don't raise here */
6489 return result;
6492 #endif /* DISABLE_REFLECTION_EMIT */
6495 * We need to return always the same object for MethodInfo, FieldInfo etc..
6496 * but we need to consider the reflected type.
6497 * type uses a different hash, since it uses custom hash/equal functions.
6500 typedef struct {
6501 gpointer item;
6502 MonoClass *refclass;
6503 } ReflectedEntry;
6505 static gboolean
6506 reflected_equal (gconstpointer a, gconstpointer b) {
6507 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6508 const ReflectedEntry *eb = (const ReflectedEntry *)b;
6510 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6513 static guint
6514 reflected_hash (gconstpointer a) {
6515 const ReflectedEntry *ea = (const ReflectedEntry *)a;
6516 return mono_aligned_addr_hash (ea->item);
6519 #define CHECK_OBJECT(t,p,k) \
6520 do { \
6521 t _obj; \
6522 ReflectedEntry e; \
6523 e.item = (p); \
6524 e.refclass = (k); \
6525 mono_domain_lock (domain); \
6526 if (!domain->refobject_hash) \
6527 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"); \
6528 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6529 mono_domain_unlock (domain); \
6530 return _obj; \
6532 mono_domain_unlock (domain); \
6533 } while (0)
6535 #ifdef HAVE_BOEHM_GC
6536 /* ReflectedEntry doesn't need to be GC tracked */
6537 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6538 #define FREE_REFENTRY(entry) g_free ((entry))
6539 #define REFENTRY_REQUIRES_CLEANUP
6540 #else
6541 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6542 /* FIXME: */
6543 #define FREE_REFENTRY(entry)
6544 #endif
6546 #define CACHE_OBJECT(t,p,o,k) \
6547 do { \
6548 t _obj; \
6549 ReflectedEntry pe; \
6550 pe.item = (p); \
6551 pe.refclass = (k); \
6552 mono_domain_lock (domain); \
6553 if (!domain->refobject_hash) \
6554 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"); \
6555 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6556 if (!_obj) { \
6557 ReflectedEntry *e = ALLOC_REFENTRY; \
6558 e->item = (p); \
6559 e->refclass = (k); \
6560 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6561 _obj = o; \
6563 mono_domain_unlock (domain); \
6564 return _obj; \
6565 } while (0)
6567 static void
6568 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6570 mono_domain_lock (domain);
6571 if (domain->refobject_hash) {
6572 ReflectedEntry pe;
6573 gpointer orig_pe, orig_value;
6575 pe.item = o;
6576 pe.refclass = klass;
6577 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6578 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6579 FREE_REFENTRY (orig_pe);
6582 mono_domain_unlock (domain);
6585 #ifdef REFENTRY_REQUIRES_CLEANUP
6586 static void
6587 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6589 FREE_REFENTRY (key);
6591 #endif
6593 void
6594 mono_reflection_cleanup_domain (MonoDomain *domain)
6596 if (domain->refobject_hash) {
6597 /*let's avoid scanning the whole hashtable if not needed*/
6598 #ifdef REFENTRY_REQUIRES_CLEANUP
6599 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6600 #endif
6601 mono_g_hash_table_destroy (domain->refobject_hash);
6602 domain->refobject_hash = NULL;
6606 #ifndef DISABLE_REFLECTION_EMIT
6607 static gpointer
6608 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6610 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6613 static gpointer
6614 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6616 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6619 void
6620 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6622 MonoDynamicImage *image = moduleb->dynamic_image;
6623 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6624 if (!image) {
6625 MonoError error;
6626 int module_count;
6627 MonoImage **new_modules;
6628 MonoImage *ass;
6629 char *name, *fqname;
6631 * FIXME: we already created an image in mono_image_basic_init (), but
6632 * we don't know which module it belongs to, since that is only
6633 * determined at assembly save time.
6635 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6636 name = mono_string_to_utf8 (ab->name);
6637 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6638 if (!mono_error_ok (&error)) {
6639 g_free (name);
6640 mono_error_raise_exception (&error);
6642 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6644 moduleb->module.image = &image->image;
6645 moduleb->dynamic_image = image;
6646 register_module (mono_object_domain (moduleb), moduleb, image);
6648 /* register the module with the assembly */
6649 ass = ab->dynamic_assembly->assembly.image;
6650 module_count = ass->module_count;
6651 new_modules = g_new0 (MonoImage *, module_count + 1);
6653 if (ass->modules)
6654 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6655 new_modules [module_count] = &image->image;
6656 mono_image_addref (&image->image);
6658 g_free (ass->modules);
6659 ass->modules = new_modules;
6660 ass->module_count ++;
6664 void
6665 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6667 MonoDynamicImage *image = moduleb->dynamic_image;
6669 g_assert (type->type);
6670 image->wrappers_type = mono_class_from_mono_type (type->type);
6673 #endif
6676 * mono_assembly_get_object:
6677 * @domain: an app domain
6678 * @assembly: an assembly
6680 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6682 MonoReflectionAssembly*
6683 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6685 MonoError error;
6686 MonoReflectionAssembly *result;
6687 result = mono_assembly_get_object_checked (domain, assembly, &error);
6688 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6689 return result;
6692 * mono_assembly_get_object_checked:
6693 * @domain: an app domain
6694 * @assembly: an assembly
6696 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6698 MonoReflectionAssembly*
6699 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6701 MonoReflectionAssembly *res;
6703 mono_error_init (error);
6705 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6706 res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6707 if (!res)
6708 return NULL;
6709 res->assembly = assembly;
6711 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6716 MonoReflectionModule*
6717 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6719 MonoError error;
6720 MonoReflectionModule *result;
6721 result = mono_module_get_object_checked (domain, image, &error);
6722 mono_error_raise_exception (&error);
6723 return result;
6726 MonoReflectionModule*
6727 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6729 MonoReflectionModule *res;
6730 char* basename;
6732 mono_error_init (error);
6733 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6734 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6735 if (!res)
6736 return NULL;
6738 res->image = image;
6739 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6740 if (!assm_obj)
6741 return NULL;
6742 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6744 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6745 basename = g_path_get_basename (image->name);
6746 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6747 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6749 g_free (basename);
6751 if (image->assembly->image == image) {
6752 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6753 } else {
6754 int i;
6755 res->token = 0;
6756 if (image->assembly->image->modules) {
6757 for (i = 0; i < image->assembly->image->module_count; i++) {
6758 if (image->assembly->image->modules [i] == image)
6759 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6761 g_assert (res->token);
6765 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6768 MonoReflectionModule*
6769 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6771 MonoError error;
6772 MonoReflectionModule *result;
6773 result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6774 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6775 return result;
6778 MonoReflectionModule*
6779 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6781 MonoReflectionModule *res;
6782 MonoTableInfo *table;
6783 guint32 cols [MONO_FILE_SIZE];
6784 const char *name;
6785 guint32 i, name_idx;
6786 const char *val;
6788 mono_error_init (error);
6790 res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6791 if (!res)
6792 return NULL;
6794 table = &image->tables [MONO_TABLE_FILE];
6795 g_assert (table_index < table->rows);
6796 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6798 res->image = NULL;
6799 MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6800 if (!assm_obj)
6801 return NULL;
6802 MONO_OBJECT_SETREF (res, assembly, assm_obj);
6803 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6805 /* Check whenever the row has a corresponding row in the moduleref table */
6806 table = &image->tables [MONO_TABLE_MODULEREF];
6807 for (i = 0; i < table->rows; ++i) {
6808 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6809 val = mono_metadata_string_heap (image, name_idx);
6810 if (strcmp (val, name) == 0)
6811 res->image = image->modules [i];
6814 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6815 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6816 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6817 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6818 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6820 return res;
6823 static gboolean
6824 verify_safe_for_managed_space (MonoType *type)
6826 switch (type->type) {
6827 #ifdef DEBUG_HARDER
6828 case MONO_TYPE_ARRAY:
6829 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6830 case MONO_TYPE_PTR:
6831 return verify_safe_for_managed_space (type->data.type);
6832 case MONO_TYPE_SZARRAY:
6833 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6834 case MONO_TYPE_GENERICINST: {
6835 MonoGenericInst *inst = type->data.generic_class->inst;
6836 int i;
6837 if (!inst->is_open)
6838 break;
6839 for (i = 0; i < inst->type_argc; ++i)
6840 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6841 return FALSE;
6842 return TRUE;
6844 #endif
6845 case MONO_TYPE_VAR:
6846 case MONO_TYPE_MVAR:
6847 return TRUE;
6848 default:
6849 return TRUE;
6853 static MonoType*
6854 mono_type_normalize (MonoType *type)
6856 int i;
6857 MonoGenericClass *gclass;
6858 MonoGenericInst *ginst;
6859 MonoClass *gtd;
6860 MonoGenericContainer *gcontainer;
6861 MonoType **argv = NULL;
6862 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6864 if (type->type != MONO_TYPE_GENERICINST)
6865 return type;
6867 gclass = type->data.generic_class;
6868 ginst = gclass->context.class_inst;
6869 if (!ginst->is_open)
6870 return type;
6872 gtd = gclass->container_class;
6873 gcontainer = gtd->generic_container;
6874 argv = g_newa (MonoType*, ginst->type_argc);
6876 for (i = 0; i < ginst->type_argc; ++i) {
6877 MonoType *t = ginst->type_argv [i], *norm;
6878 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6879 is_denorm_gtd = FALSE;
6880 norm = mono_type_normalize (t);
6881 argv [i] = norm;
6882 if (norm != t)
6883 requires_rebind = TRUE;
6886 if (is_denorm_gtd)
6887 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6889 if (requires_rebind) {
6890 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6891 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6894 return type;
6897 * mono_type_get_object:
6898 * @domain: an app domain
6899 * @type: a type
6901 * Return an System.MonoType object representing the type @type.
6903 MonoReflectionType*
6904 mono_type_get_object (MonoDomain *domain, MonoType *type)
6906 MonoError error;
6907 MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6908 mono_error_raise_exception (&error);
6910 return ret;
6913 MonoReflectionType*
6914 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6916 MonoType *norm_type;
6917 MonoReflectionType *res;
6918 MonoClass *klass;
6920 mono_error_init (error);
6922 klass = mono_class_from_mono_type (type);
6924 /*we must avoid using @type as it might have come
6925 * from a mono_metadata_type_dup and the caller
6926 * expects that is can be freed.
6927 * Using the right type from
6929 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6931 /* void is very common */
6932 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6933 return (MonoReflectionType*)domain->typeof_void;
6936 * If the vtable of the given class was already created, we can use
6937 * the MonoType from there and avoid all locking and hash table lookups.
6939 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6940 * that the resulting object is different.
6942 if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6943 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6944 if (vtable && vtable->type)
6945 return (MonoReflectionType *)vtable->type;
6948 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6949 mono_domain_lock (domain);
6950 if (!domain->type_hash)
6951 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6952 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6953 if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6954 mono_domain_unlock (domain);
6955 mono_loader_unlock ();
6956 return res;
6959 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6960 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6961 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6962 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6963 * artifact of how generics are encoded and should be transparent to managed code so we
6964 * need to weed out this diference when retrieving managed System.Type objects.
6966 norm_type = mono_type_normalize (type);
6967 if (norm_type != type) {
6968 res = mono_type_get_object_checked (domain, norm_type, error);
6969 if (!mono_error_ok (error))
6970 return NULL;
6971 mono_g_hash_table_insert (domain->type_hash, type, res);
6972 mono_domain_unlock (domain);
6973 mono_loader_unlock ();
6974 return res;
6977 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6978 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6979 g_assert (0);
6981 if (!verify_safe_for_managed_space (type)) {
6982 mono_domain_unlock (domain);
6983 mono_loader_unlock ();
6984 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
6985 return NULL;
6988 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6989 gboolean is_type_done = TRUE;
6990 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6991 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6992 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6994 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6995 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6997 if (gparam->owner && gparam->owner->is_method) {
6998 MonoMethod *method = gparam->owner->owner.method;
6999 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7000 is_type_done = FALSE;
7001 } else if (gparam->owner && !gparam->owner->is_method) {
7002 MonoClass *klass = gparam->owner->owner.klass;
7003 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7004 is_type_done = FALSE;
7008 /* g_assert_not_reached (); */
7009 /* should this be considered an error condition? */
7010 if (is_type_done && !type->byref) {
7011 mono_domain_unlock (domain);
7012 mono_loader_unlock ();
7013 return (MonoReflectionType *)mono_class_get_ref_info (klass);
7016 /* This is stored in vtables/JITted code so it has to be pinned */
7017 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7018 if (!mono_error_ok (error))
7019 return NULL;
7021 res->type = type;
7022 mono_g_hash_table_insert (domain->type_hash, type, res);
7024 if (type->type == MONO_TYPE_VOID)
7025 domain->typeof_void = (MonoObject*)res;
7027 mono_domain_unlock (domain);
7028 mono_loader_unlock ();
7029 return res;
7033 * mono_method_get_object:
7034 * @domain: an app domain
7035 * @method: a method
7036 * @refclass: the reflected type (can be NULL)
7038 * Return an System.Reflection.MonoMethod object representing the method @method.
7040 MonoReflectionMethod*
7041 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7043 MonoError error;
7044 MonoReflectionMethod *ret = NULL;
7045 ret = mono_method_get_object_checked (domain, method, refclass, &error);
7046 mono_error_raise_exception (&error);
7047 return ret;
7051 * mono_method_get_object_checked:
7052 * @domain: an app domain
7053 * @method: a method
7054 * @refclass: the reflected type (can be NULL)
7055 * @error: set on error.
7057 * Return an System.Reflection.MonoMethod object representing the method @method.
7058 * Returns NULL and sets @error on error.
7060 MonoReflectionMethod*
7061 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7064 * We use the same C representation for methods and constructors, but the type
7065 * name in C# is different.
7067 MonoReflectionType *rt;
7068 MonoClass *klass;
7069 MonoReflectionMethod *ret;
7071 mono_error_init (error);
7073 if (method->is_inflated) {
7074 MonoReflectionGenericMethod *gret;
7076 if (!refclass)
7077 refclass = method->klass;
7078 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7079 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7080 klass = mono_class_get_mono_generic_cmethod_class ();
7081 } else {
7082 klass = mono_class_get_mono_generic_method_class ();
7084 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7085 if (!mono_error_ok (error))
7086 goto leave;
7087 gret->method.method = method;
7089 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7091 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7092 if (!mono_error_ok (error))
7093 goto leave;
7095 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7097 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7100 if (!refclass)
7101 refclass = method->klass;
7103 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7104 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7105 klass = mono_class_get_mono_cmethod_class ();
7107 else {
7108 klass = mono_class_get_mono_method_class ();
7110 ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7111 if (!mono_error_ok (error))
7112 goto leave;
7113 ret->method = method;
7115 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7116 if (!mono_error_ok (error))
7117 goto leave;
7119 MONO_OBJECT_SETREF (ret, reftype, rt);
7121 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7123 leave:
7124 g_assert (!mono_error_ok (error));
7125 return NULL;
7129 * mono_method_clear_object:
7131 * Clear the cached reflection objects for the dynamic method METHOD.
7133 void
7134 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7136 MonoClass *klass;
7137 g_assert (method_is_dynamic (method));
7139 klass = method->klass;
7140 while (klass) {
7141 clear_cached_object (domain, method, klass);
7142 klass = klass->parent;
7144 /* Added by mono_param_get_objects () */
7145 clear_cached_object (domain, &(method->signature), NULL);
7146 klass = method->klass;
7147 while (klass) {
7148 clear_cached_object (domain, &(method->signature), klass);
7149 klass = klass->parent;
7154 * mono_field_get_object:
7155 * @domain: an app domain
7156 * @klass: a type
7157 * @field: a field
7159 * Return an System.Reflection.MonoField object representing the field @field
7160 * in class @klass.
7162 MonoReflectionField*
7163 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7165 MonoError error;
7166 MonoReflectionField *result;
7167 result = mono_field_get_object_checked (domain, klass, field, &error);
7168 mono_error_raise_exception (&error);
7169 return result;
7173 * mono_field_get_object_checked:
7174 * @domain: an app domain
7175 * @klass: a type
7176 * @field: a field
7177 * @error: set on error
7179 * Return an System.Reflection.MonoField object representing the field @field
7180 * in class @klass. On error, returns NULL and sets @error.
7182 MonoReflectionField*
7183 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7185 MonoReflectionType *rt;
7186 MonoReflectionField *res;
7188 mono_error_init (error);
7190 CHECK_OBJECT (MonoReflectionField *, field, klass);
7191 res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7192 if (!res)
7193 return NULL;
7194 res->klass = klass;
7195 res->field = field;
7196 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7198 if (is_field_on_inst (field)) {
7199 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7201 rt = mono_type_get_object_checked (domain, field->type, error);
7202 if (!mono_error_ok (error))
7203 return NULL;
7205 MONO_OBJECT_SETREF (res, type, rt);
7206 } else {
7207 if (field->type) {
7208 rt = mono_type_get_object_checked (domain, field->type, error);
7209 if (!mono_error_ok (error))
7210 return NULL;
7212 MONO_OBJECT_SETREF (res, type, rt);
7214 res->attrs = mono_field_get_flags (field);
7216 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7220 * mono_property_get_object:
7221 * @domain: an app domain
7222 * @klass: a type
7223 * @property: a property
7225 * Return an System.Reflection.MonoProperty object representing the property @property
7226 * in class @klass.
7228 MonoReflectionProperty*
7229 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7231 MonoError error;
7232 MonoReflectionProperty *result;
7233 result = mono_property_get_object_checked (domain, klass, property, &error);
7234 mono_error_raise_exception (&error);
7235 return result;
7239 * mono_property_get_object:
7240 * @domain: an app domain
7241 * @klass: a type
7242 * @property: a property
7243 * @error: set on error
7245 * Return an System.Reflection.MonoProperty object representing the property @property
7246 * in class @klass. On error returns NULL and sets @error.
7248 MonoReflectionProperty*
7249 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7251 MonoReflectionProperty *res;
7253 mono_error_init (error);
7255 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7256 res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7257 if (!res)
7258 return NULL;
7259 res->klass = klass;
7260 res->property = property;
7261 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7265 * mono_event_get_object:
7266 * @domain: an app domain
7267 * @klass: a type
7268 * @event: a event
7270 * Return an System.Reflection.MonoEvent object representing the event @event
7271 * in class @klass.
7273 MonoReflectionEvent*
7274 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7276 MonoError error;
7277 MonoReflectionEvent *result;
7278 result = mono_event_get_object_checked (domain, klass, event, &error);
7279 mono_error_raise_exception (&error);
7280 return result;
7284 * mono_event_get_object_checked:
7285 * @domain: an app domain
7286 * @klass: a type
7287 * @event: a event
7288 * @error: set on error
7290 * Return an System.Reflection.MonoEvent object representing the event @event
7291 * in class @klass. On failure sets @error and returns NULL
7293 MonoReflectionEvent*
7294 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7296 MonoReflectionEvent *res;
7297 MonoReflectionMonoEvent *mono_event;
7299 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7300 mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7301 if (!mono_event)
7302 return NULL;
7303 mono_event->klass = klass;
7304 mono_event->event = event;
7305 res = (MonoReflectionEvent*)mono_event;
7306 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7310 * mono_get_reflection_missing_object:
7311 * @domain: Domain where the object lives
7313 * Returns the System.Reflection.Missing.Value singleton object
7314 * (of type System.Reflection.Missing).
7316 * Used as the value for ParameterInfo.DefaultValue when Optional
7317 * is present
7319 static MonoObject *
7320 mono_get_reflection_missing_object (MonoDomain *domain)
7322 MonoObject *obj;
7323 static MonoClassField *missing_value_field = NULL;
7325 if (!missing_value_field) {
7326 MonoClass *missing_klass;
7327 missing_klass = mono_class_get_missing_class ();
7328 mono_class_init (missing_klass);
7329 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7330 g_assert (missing_value_field);
7332 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
7333 g_assert (obj);
7334 return obj;
7337 static MonoObject*
7338 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7340 if (!*dbnull)
7341 *dbnull = mono_get_dbnull_object (domain);
7342 return *dbnull;
7345 static MonoObject*
7346 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7348 if (!*reflection_missing)
7349 *reflection_missing = mono_get_reflection_missing_object (domain);
7350 return *reflection_missing;
7354 * mono_param_get_objects:
7355 * @domain: an app domain
7356 * @method: a method
7358 * Return an System.Reflection.ParameterInfo array object representing the parameters
7359 * in the method @method.
7361 MonoArray*
7362 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7364 static MonoClass *System_Reflection_ParameterInfo;
7365 static MonoClass *System_Reflection_ParameterInfo_array;
7366 MonoArray *res = NULL;
7367 MonoReflectionMethod *member = NULL;
7368 MonoReflectionParameter *param = NULL;
7369 char **names = NULL, **blobs = NULL;
7370 guint32 *types = NULL;
7371 MonoType *type = NULL;
7372 MonoObject *dbnull = NULL;
7373 MonoObject *missing = NULL;
7374 MonoMarshalSpec **mspecs = NULL;
7375 MonoMethodSignature *sig = NULL;
7376 MonoVTable *pinfo_vtable;
7377 MonoReflectionType *rt;
7378 int i;
7380 mono_error_init (error);
7382 if (!System_Reflection_ParameterInfo_array) {
7383 MonoClass *klass;
7385 klass = mono_class_get_mono_parameter_info_class ();
7387 mono_memory_barrier ();
7388 System_Reflection_ParameterInfo = klass;
7391 klass = mono_array_class_get (klass, 1);
7392 mono_memory_barrier ();
7393 System_Reflection_ParameterInfo_array = klass;
7396 sig = mono_method_signature_checked (method, error);
7397 if (!mono_error_ok (error))
7398 goto leave;
7400 if (!sig->param_count) {
7401 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7402 if (!res)
7403 goto leave;
7405 return res;
7408 /* Note: the cache is based on the address of the signature into the method
7409 * since we already cache MethodInfos with the method as keys.
7411 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7413 member = mono_method_get_object_checked (domain, method, refclass, error);
7414 if (!member)
7415 goto leave;
7416 names = g_new (char *, sig->param_count);
7417 mono_method_get_param_names (method, (const char **) names);
7419 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7420 mono_method_get_marshal_info (method, mspecs);
7422 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7423 if (!res)
7424 goto leave;
7426 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7427 for (i = 0; i < sig->param_count; ++i) {
7428 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7429 if (!param)
7430 goto leave;
7432 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7433 if (!rt)
7434 goto leave;
7436 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7438 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7440 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7442 param->PositionImpl = i;
7443 param->AttrsImpl = sig->params [i]->attrs;
7445 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7446 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7447 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7448 else
7449 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7450 } else {
7452 if (!blobs) {
7453 blobs = g_new0 (char *, sig->param_count);
7454 types = g_new0 (guint32, sig->param_count);
7455 get_default_param_value_blobs (method, blobs, types);
7458 /* Build MonoType for the type from the Constant Table */
7459 if (!type)
7460 type = g_new0 (MonoType, 1);
7461 type->type = (MonoTypeEnum)types [i];
7462 type->data.klass = NULL;
7463 if (types [i] == MONO_TYPE_CLASS)
7464 type->data.klass = mono_defaults.object_class;
7465 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7466 /* For enums, types [i] contains the base type */
7468 type->type = MONO_TYPE_VALUETYPE;
7469 type->data.klass = mono_class_from_mono_type (sig->params [i]);
7470 } else
7471 type->data.klass = mono_class_from_mono_type (type);
7473 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7475 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7476 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7477 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7478 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7479 else
7480 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7485 if (mspecs [i + 1]) {
7486 MonoReflectionMarshalAsAttribute* mobj;
7487 mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7488 if (!mobj)
7489 goto leave;
7490 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7493 mono_array_setref (res, i, param);
7496 leave:
7497 g_free (names);
7498 g_free (blobs);
7499 g_free (types);
7500 g_free (type);
7502 if (sig) {
7503 for (i = sig->param_count; i >= 0; i--) {
7504 if (mspecs [i])
7505 mono_metadata_free_marshal_spec (mspecs [i]);
7508 g_free (mspecs);
7510 if (!is_ok (error))
7511 return NULL;
7513 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7516 MonoArray*
7517 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7519 MonoError error;
7520 MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7521 mono_error_assert_ok (&error);
7522 return result;
7526 * mono_method_body_get_object:
7527 * @domain: an app domain
7528 * @method: a method
7530 * Return an System.Reflection.MethodBody object representing the method @method.
7532 MonoReflectionMethodBody*
7533 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7535 MonoError error;
7536 MonoReflectionMethodBody *ret;
7537 MonoMethodHeader *header;
7538 MonoImage *image;
7539 MonoReflectionType *rt;
7540 guint32 method_rva, local_var_sig_token;
7541 char *ptr;
7542 unsigned char format, flags;
7543 int i;
7545 /* for compatibility with .net */
7546 if (method_is_dynamic (method))
7547 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7549 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7551 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7552 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7553 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7554 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7555 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7556 return NULL;
7558 image = method->klass->image;
7559 header = mono_method_get_header (method);
7561 if (!image_is_dynamic (image)) {
7562 /* Obtain local vars signature token */
7563 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7564 ptr = mono_image_rva_map (image, method_rva);
7565 flags = *(const unsigned char *) ptr;
7566 format = flags & METHOD_HEADER_FORMAT_MASK;
7567 switch (format){
7568 case METHOD_HEADER_TINY_FORMAT:
7569 local_var_sig_token = 0;
7570 break;
7571 case METHOD_HEADER_FAT_FORMAT:
7572 ptr += 2;
7573 ptr += 2;
7574 ptr += 4;
7575 local_var_sig_token = read32 (ptr);
7576 break;
7577 default:
7578 g_assert_not_reached ();
7580 } else
7581 local_var_sig_token = 0; //FIXME
7583 ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7584 mono_error_raise_exception (&error); /* FIXME don't raise here */
7586 ret->init_locals = header->init_locals;
7587 ret->max_stack = header->max_stack;
7588 ret->local_var_sig_token = local_var_sig_token;
7589 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7590 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7592 /* Locals */
7593 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7594 for (i = 0; i < header->num_locals; ++i) {
7595 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7596 mono_error_raise_exception (&error); /* FIXME don't raise here */
7598 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7599 mono_error_raise_exception (&error); /* FIXME don't raise here */
7601 MONO_OBJECT_SETREF (info, local_type, rt);
7603 info->is_pinned = header->locals [i]->pinned;
7604 info->local_index = i;
7605 mono_array_setref (ret->locals, i, info);
7608 /* Exceptions */
7609 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7610 for (i = 0; i < header->num_clauses; ++i) {
7611 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7612 mono_error_raise_exception (&error); /* FIXME don't raise here */
7613 MonoExceptionClause *clause = &header->clauses [i];
7615 info->flags = clause->flags;
7616 info->try_offset = clause->try_offset;
7617 info->try_length = clause->try_len;
7618 info->handler_offset = clause->handler_offset;
7619 info->handler_length = clause->handler_len;
7620 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7621 info->filter_offset = clause->data.filter_offset;
7622 else if (clause->data.catch_class) {
7623 rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7624 mono_error_raise_exception (&error); /* FIXME don't raise here */
7626 MONO_OBJECT_SETREF (info, catch_type, rt);
7629 mono_array_setref (ret->clauses, i, info);
7632 mono_metadata_free_mh (header);
7633 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7634 return ret;
7638 * mono_get_dbnull_object:
7639 * @domain: Domain where the object lives
7641 * Returns the System.DBNull.Value singleton object
7643 * Used as the value for ParameterInfo.DefaultValue
7645 MonoObject *
7646 mono_get_dbnull_object (MonoDomain *domain)
7648 MonoObject *obj;
7649 static MonoClassField *dbnull_value_field = NULL;
7651 if (!dbnull_value_field) {
7652 MonoClass *dbnull_klass;
7653 dbnull_klass = mono_class_get_dbnull_class ();
7654 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7655 g_assert (dbnull_value_field);
7657 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7658 g_assert (obj);
7659 return obj;
7662 static void
7663 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7665 guint32 param_index, i, lastp, crow = 0;
7666 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7667 gint32 idx;
7669 MonoClass *klass = method->klass;
7670 MonoImage *image = klass->image;
7671 MonoMethodSignature *methodsig = mono_method_signature (method);
7673 MonoTableInfo *constt;
7674 MonoTableInfo *methodt;
7675 MonoTableInfo *paramt;
7677 if (!methodsig->param_count)
7678 return;
7680 mono_class_init (klass);
7682 if (image_is_dynamic (klass->image)) {
7683 MonoReflectionMethodAux *aux;
7684 if (method->is_inflated)
7685 method = ((MonoMethodInflated*)method)->declaring;
7686 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7687 if (aux && aux->param_defaults) {
7688 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7689 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7691 return;
7694 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7695 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7696 constt = &image->tables [MONO_TABLE_CONSTANT];
7698 idx = mono_method_get_index (method) - 1;
7699 g_assert (idx != -1);
7701 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7702 if (idx + 1 < methodt->rows)
7703 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7704 else
7705 lastp = paramt->rows + 1;
7707 for (i = param_index; i < lastp; ++i) {
7708 guint32 paramseq;
7710 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7711 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7713 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7714 continue;
7716 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7717 if (!crow) {
7718 continue;
7721 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7722 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7723 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7726 return;
7729 MonoObject *
7730 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7732 MonoError error;
7733 void *retval;
7734 MonoClass *klass;
7735 MonoObject *object;
7736 MonoType *basetype = type;
7738 if (!blob)
7739 return NULL;
7741 klass = mono_class_from_mono_type (type);
7742 if (klass->valuetype) {
7743 object = mono_object_new_checked (domain, klass, &error);
7744 mono_error_raise_exception (&error); /* FIXME don't raise here */
7745 retval = ((gchar *) object + sizeof (MonoObject));
7746 if (klass->enumtype)
7747 basetype = mono_class_enum_basetype (klass);
7748 } else {
7749 retval = &object;
7752 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7753 return object;
7754 else
7755 return NULL;
7758 static int
7759 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7760 int found_sep;
7761 char *s;
7762 gboolean quoted = FALSE;
7764 memset (assembly, 0, sizeof (MonoAssemblyName));
7765 assembly->culture = "";
7766 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7768 if (*p == '"') {
7769 quoted = TRUE;
7770 p++;
7772 assembly->name = p;
7773 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7774 p++;
7775 if (quoted) {
7776 if (*p != '"')
7777 return 1;
7778 *p = 0;
7779 p++;
7781 if (*p != ',')
7782 return 1;
7783 *p = 0;
7784 /* Remove trailing whitespace */
7785 s = p - 1;
7786 while (*s && g_ascii_isspace (*s))
7787 *s-- = 0;
7788 p ++;
7789 while (g_ascii_isspace (*p))
7790 p++;
7791 while (*p) {
7792 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7793 p += 8;
7794 assembly->major = strtoul (p, &s, 10);
7795 if (s == p || *s != '.')
7796 return 1;
7797 p = ++s;
7798 assembly->minor = strtoul (p, &s, 10);
7799 if (s == p || *s != '.')
7800 return 1;
7801 p = ++s;
7802 assembly->build = strtoul (p, &s, 10);
7803 if (s == p || *s != '.')
7804 return 1;
7805 p = ++s;
7806 assembly->revision = strtoul (p, &s, 10);
7807 if (s == p)
7808 return 1;
7809 p = s;
7810 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7811 p += 8;
7812 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7813 assembly->culture = "";
7814 p += 7;
7815 } else {
7816 assembly->culture = p;
7817 while (*p && *p != ',') {
7818 p++;
7821 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7822 p += 15;
7823 if (strncmp (p, "null", 4) == 0) {
7824 p += 4;
7825 } else {
7826 int len;
7827 gchar *start = p;
7828 while (*p && *p != ',') {
7829 p++;
7831 len = (p - start + 1);
7832 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7833 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7834 g_strlcpy ((char*)assembly->public_key_token, start, len);
7836 } else {
7837 while (*p && *p != ',')
7838 p++;
7840 found_sep = 0;
7841 while (g_ascii_isspace (*p) || *p == ',') {
7842 *p++ = 0;
7843 found_sep = 1;
7844 continue;
7846 /* failed */
7847 if (!found_sep)
7848 return 1;
7851 return 0;
7855 * mono_reflection_parse_type:
7856 * @name: type name
7858 * Parse a type name as accepted by the GetType () method and output the info
7859 * extracted in the info structure.
7860 * the name param will be mangled, so, make a copy before passing it to this function.
7861 * The fields in info will be valid until the memory pointed to by name is valid.
7863 * See also mono_type_get_name () below.
7865 * Returns: 0 on parse error.
7867 static int
7868 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7869 MonoTypeNameParse *info)
7871 char *start, *p, *w, *last_point, *startn;
7872 int in_modifiers = 0;
7873 int isbyref = 0, rank = 0, isptr = 0;
7875 start = p = w = name;
7877 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7878 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7879 info->name = info->name_space = NULL;
7880 info->nested = NULL;
7881 info->modifiers = NULL;
7882 info->type_arguments = NULL;
7884 /* last_point separates the namespace from the name */
7885 last_point = NULL;
7886 /* Skips spaces */
7887 while (*p == ' ') p++, start++, w++, name++;
7889 while (*p) {
7890 switch (*p) {
7891 case '+':
7892 *p = 0; /* NULL terminate the name */
7893 startn = p + 1;
7894 info->nested = g_list_append (info->nested, startn);
7895 /* we have parsed the nesting namespace + name */
7896 if (info->name)
7897 break;
7898 if (last_point) {
7899 info->name_space = start;
7900 *last_point = 0;
7901 info->name = last_point + 1;
7902 } else {
7903 info->name_space = (char *)"";
7904 info->name = start;
7906 break;
7907 case '.':
7908 last_point = p;
7909 break;
7910 case '\\':
7911 ++p;
7912 break;
7913 case '&':
7914 case '*':
7915 case '[':
7916 case ',':
7917 case ']':
7918 in_modifiers = 1;
7919 break;
7920 default:
7921 break;
7923 if (in_modifiers)
7924 break;
7925 // *w++ = *p++;
7926 p++;
7929 if (!info->name) {
7930 if (last_point) {
7931 info->name_space = start;
7932 *last_point = 0;
7933 info->name = last_point + 1;
7934 } else {
7935 info->name_space = (char *)"";
7936 info->name = start;
7939 while (*p) {
7940 switch (*p) {
7941 case '&':
7942 if (isbyref) /* only one level allowed by the spec */
7943 return 0;
7944 isbyref = 1;
7945 isptr = 0;
7946 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7947 *p++ = 0;
7948 break;
7949 case '*':
7950 if (isbyref) /* pointer to ref not okay */
7951 return 0;
7952 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7953 isptr = 1;
7954 *p++ = 0;
7955 break;
7956 case '[':
7957 if (isbyref) /* array of ref and generic ref are not okay */
7958 return 0;
7959 //Decide if it's an array of a generic argument list
7960 *p++ = 0;
7962 if (!*p) //XXX test
7963 return 0;
7964 if (*p == ',' || *p == '*' || *p == ']') { //array
7965 isptr = 0;
7966 rank = 1;
7967 while (*p) {
7968 if (*p == ']')
7969 break;
7970 if (*p == ',')
7971 rank++;
7972 else if (*p == '*') /* '*' means unknown lower bound */
7973 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7974 else
7975 return 0;
7976 ++p;
7978 if (*p++ != ']')
7979 return 0;
7980 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7981 } else {
7982 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7983 return 0;
7984 isptr = 0;
7985 info->type_arguments = g_ptr_array_new ();
7986 while (*p) {
7987 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7988 gboolean fqname = FALSE;
7990 g_ptr_array_add (info->type_arguments, subinfo);
7992 while (*p == ' ') p++;
7993 if (*p == '[') {
7994 p++;
7995 fqname = TRUE;
7998 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7999 return 0;
8001 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8002 if (fqname && (*p != ']')) {
8003 char *aname;
8005 if (*p != ',')
8006 return 0;
8007 *p++ = 0;
8009 aname = p;
8010 while (*p && (*p != ']'))
8011 p++;
8013 if (*p != ']')
8014 return 0;
8016 *p++ = 0;
8017 while (*aname) {
8018 if (g_ascii_isspace (*aname)) {
8019 ++aname;
8020 continue;
8022 break;
8024 if (!*aname ||
8025 !assembly_name_to_aname (&subinfo->assembly, aname))
8026 return 0;
8027 } else if (fqname && (*p == ']')) {
8028 *p++ = 0;
8030 if (*p == ']') {
8031 *p++ = 0;
8032 break;
8033 } else if (!*p) {
8034 return 0;
8036 *p++ = 0;
8039 break;
8040 case ']':
8041 if (is_recursed)
8042 goto end;
8043 return 0;
8044 case ',':
8045 if (is_recursed)
8046 goto end;
8047 *p++ = 0;
8048 while (*p) {
8049 if (g_ascii_isspace (*p)) {
8050 ++p;
8051 continue;
8053 break;
8055 if (!*p)
8056 return 0; /* missing assembly name */
8057 if (!assembly_name_to_aname (&info->assembly, p))
8058 return 0;
8059 break;
8060 default:
8061 return 0;
8063 if (info->assembly.name)
8064 break;
8066 // *w = 0; /* terminate class name */
8067 end:
8068 if (!info->name || !*info->name)
8069 return 0;
8070 if (endptr)
8071 *endptr = p;
8072 /* add other consistency checks */
8073 return 1;
8078 * mono_identifier_unescape_type_name_chars:
8079 * @identifier: the display name of a mono type
8081 * Returns:
8082 * The name in internal form, that is without escaping backslashes.
8084 * The string is modified in place!
8086 char*
8087 mono_identifier_unescape_type_name_chars(char* identifier)
8089 char *w, *r;
8090 if (!identifier)
8091 return NULL;
8092 for (w = r = identifier; *r != 0; r++)
8094 char c = *r;
8095 if (c == '\\') {
8096 r++;
8097 if (*r == 0)
8098 break;
8099 c = *r;
8101 *w = c;
8102 w++;
8104 if (w != r)
8105 *w = 0;
8106 return identifier;
8109 void
8110 mono_identifier_unescape_info (MonoTypeNameParse* info);
8112 static void
8113 unescape_each_type_argument(void* data, void* user_data)
8115 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8116 mono_identifier_unescape_info (info);
8119 static void
8120 unescape_each_nested_name (void* data, void* user_data)
8122 char* nested_name = (char*) data;
8123 mono_identifier_unescape_type_name_chars(nested_name);
8127 * mono_identifier_unescape_info:
8129 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8131 * Returns: nothing.
8133 * Destructively updates the info by unescaping the identifiers that
8134 * comprise the type namespace, name, nested types (if any) and
8135 * generic type arguments (if any).
8137 * The resulting info has the names in internal form.
8140 void
8141 mono_identifier_unescape_info (MonoTypeNameParse *info)
8143 if (!info)
8144 return;
8145 mono_identifier_unescape_type_name_chars(info->name_space);
8146 mono_identifier_unescape_type_name_chars(info->name);
8147 // but don't escape info->assembly
8148 if (info->type_arguments)
8149 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8150 if (info->nested)
8151 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8155 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8157 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8158 if (ok) {
8159 mono_identifier_unescape_info (info);
8161 return ok;
8164 static MonoType*
8165 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8167 gboolean type_resolve = FALSE;
8168 MonoType *type;
8169 MonoImage *rootimage = image;
8171 if (info->assembly.name) {
8172 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8173 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8175 * This could happen in the AOT compiler case when the search hook is not
8176 * installed.
8178 assembly = image->assembly;
8179 if (!assembly) {
8180 /* then we must load the assembly ourselve - see #60439 */
8181 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8182 if (!assembly)
8183 return NULL;
8185 image = assembly->image;
8186 } else if (!image) {
8187 image = mono_defaults.corlib;
8190 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8191 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8192 image = mono_defaults.corlib;
8193 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8196 return type;
8200 * mono_reflection_get_type_internal:
8202 * Returns: may return NULL on success, sets error on failure.
8204 static MonoType*
8205 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8207 MonoClass *klass;
8208 GList *mod;
8209 int modval;
8210 gboolean bounded = FALSE;
8212 mono_error_init (error);
8213 if (!image)
8214 image = mono_defaults.corlib;
8216 if (!rootimage)
8217 rootimage = mono_defaults.corlib;
8219 if (ignorecase)
8220 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8221 else
8222 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8224 if (!klass)
8225 return NULL;
8227 for (mod = info->nested; mod; mod = mod->next) {
8228 gpointer iter = NULL;
8229 MonoClass *parent;
8231 parent = klass;
8232 mono_class_init (parent);
8234 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8235 char *lastp;
8236 char *nested_name, *nested_nspace;
8237 gboolean match = TRUE;
8239 lastp = strrchr ((const char *)mod->data, '.');
8240 if (lastp) {
8241 /* Nested classes can have namespaces */
8242 int nspace_len;
8244 nested_name = g_strdup (lastp + 1);
8245 nspace_len = lastp - (char*)mod->data;
8246 nested_nspace = (char *)g_malloc (nspace_len + 1);
8247 memcpy (nested_nspace, mod->data, nspace_len);
8248 nested_nspace [nspace_len] = '\0';
8250 } else {
8251 nested_name = (char *)mod->data;
8252 nested_nspace = NULL;
8255 if (nested_nspace) {
8256 if (ignorecase) {
8257 if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8258 match = FALSE;
8259 } else {
8260 if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8261 match = FALSE;
8264 if (match) {
8265 if (ignorecase) {
8266 if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8267 match = FALSE;
8268 } else {
8269 if (strcmp (klass->name, nested_name) != 0)
8270 match = FALSE;
8273 if (lastp) {
8274 g_free (nested_name);
8275 g_free (nested_nspace);
8277 if (match)
8278 break;
8281 if (!klass)
8282 break;
8284 if (!klass)
8285 return NULL;
8287 if (info->type_arguments) {
8288 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8289 MonoReflectionType *the_type;
8290 MonoType *instance;
8291 int i;
8293 for (i = 0; i < info->type_arguments->len; i++) {
8294 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8296 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8297 if (!type_args [i]) {
8298 g_free (type_args);
8299 return NULL;
8303 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8304 if (!the_type)
8305 return NULL;
8307 instance = mono_reflection_bind_generic_parameters (
8308 the_type, info->type_arguments->len, type_args);
8310 g_free (type_args);
8311 if (!instance)
8312 return NULL;
8314 klass = mono_class_from_mono_type (instance);
8317 for (mod = info->modifiers; mod; mod = mod->next) {
8318 modval = GPOINTER_TO_UINT (mod->data);
8319 if (!modval) { /* byref: must be last modifier */
8320 return &klass->this_arg;
8321 } else if (modval == -1) {
8322 klass = mono_ptr_class_get (&klass->byval_arg);
8323 } else if (modval == -2) {
8324 bounded = TRUE;
8325 } else { /* array rank */
8326 klass = mono_bounded_array_class_get (klass, modval, bounded);
8330 return &klass->byval_arg;
8334 * mono_reflection_get_type:
8335 * @image: a metadata context
8336 * @info: type description structure
8337 * @ignorecase: flag for case-insensitive string compares
8338 * @type_resolve: whenever type resolve was already tried
8340 * Build a MonoType from the type description in @info.
8344 MonoType*
8345 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8346 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8349 static MonoType*
8350 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8352 MonoReflectionAssemblyBuilder *abuilder;
8353 MonoType *type;
8354 int i;
8356 mono_error_init (error);
8357 g_assert (assembly_is_dynamic (assembly));
8358 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8359 if (!abuilder)
8360 return NULL;
8362 /* Enumerate all modules */
8364 type = NULL;
8365 if (abuilder->modules) {
8366 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8367 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8368 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8369 if (type)
8370 break;
8371 if (!mono_error_ok (error))
8372 return NULL;
8376 if (!type && abuilder->loaded_modules) {
8377 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8378 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8379 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8380 if (type)
8381 break;
8382 if (!mono_error_ok (error))
8383 return NULL;
8387 return type;
8390 MonoType*
8391 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8393 MonoError error;
8394 MonoType *type;
8395 MonoReflectionAssembly *assembly;
8396 GString *fullName;
8397 GList *mod;
8399 if (image && image_is_dynamic (image))
8400 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8401 else {
8402 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8404 if (!mono_error_ok (&error))
8405 mono_error_raise_exception (&error); /* FIXME don't raise here */
8407 if (type)
8408 return type;
8409 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8410 return NULL;
8412 if (type_resolve) {
8413 if (*type_resolve)
8414 return NULL;
8415 else
8416 *type_resolve = TRUE;
8419 /* Reconstruct the type name */
8420 fullName = g_string_new ("");
8421 if (info->name_space && (info->name_space [0] != '\0'))
8422 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8423 else
8424 g_string_printf (fullName, "%s", info->name);
8425 for (mod = info->nested; mod; mod = mod->next)
8426 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8428 assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8429 mono_error_raise_exception (&error); /* FIXME don't raise here */
8431 if (assembly) {
8432 if (assembly_is_dynamic (assembly->assembly))
8433 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8434 info, ignorecase, &error);
8435 else
8436 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
8437 info, ignorecase, &error);
8439 g_string_free (fullName, TRUE);
8440 if (!mono_error_ok (&error))
8441 mono_error_raise_exception (&error); /* FIXME don't raise here */
8442 return type;
8445 void
8446 mono_reflection_free_type_info (MonoTypeNameParse *info)
8448 g_list_free (info->modifiers);
8449 g_list_free (info->nested);
8451 if (info->type_arguments) {
8452 int i;
8454 for (i = 0; i < info->type_arguments->len; i++) {
8455 MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8457 mono_reflection_free_type_info (subinfo);
8458 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8459 g_free (subinfo);
8462 g_ptr_array_free (info->type_arguments, TRUE);
8467 * mono_reflection_type_from_name:
8468 * @name: type name.
8469 * @image: a metadata context (can be NULL).
8471 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8472 * it defaults to get the type from @image or, if @image is NULL or loading
8473 * from it fails, uses corlib.
8476 MonoType*
8477 mono_reflection_type_from_name (char *name, MonoImage *image)
8479 MonoType *type = NULL;
8480 MonoTypeNameParse info;
8481 char *tmp;
8483 /* Make a copy since parse_type modifies its argument */
8484 tmp = g_strdup (name);
8486 /*g_print ("requested type %s\n", str);*/
8487 if (mono_reflection_parse_type (tmp, &info)) {
8488 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8491 g_free (tmp);
8492 mono_reflection_free_type_info (&info);
8493 return type;
8497 * mono_reflection_get_token:
8499 * Return the metadata token of OBJ which should be an object
8500 * representing a metadata element.
8502 guint32
8503 mono_reflection_get_token (MonoObject *obj)
8505 MonoClass *klass;
8506 guint32 token = 0;
8508 klass = obj->vtable->klass;
8510 if (strcmp (klass->name, "MethodBuilder") == 0) {
8511 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8513 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8514 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8515 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8517 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8518 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8519 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8521 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8522 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8523 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8524 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8525 } else if (strcmp (klass->name, "MonoType") == 0) {
8526 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8527 MonoClass *mc = mono_class_from_mono_type (type);
8528 if (!mono_class_init (mc))
8529 mono_raise_exception (mono_class_get_exception_for_failure (mc));
8531 token = mc->type_token;
8532 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8533 strcmp (klass->name, "MonoMethod") == 0 ||
8534 strcmp (klass->name, "MonoGenericMethod") == 0 ||
8535 strcmp (klass->name, "MonoGenericCMethod") == 0) {
8536 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8537 if (m->method->is_inflated) {
8538 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8539 return inflated->declaring->token;
8540 } else {
8541 token = m->method->token;
8543 } else if (strcmp (klass->name, "MonoField") == 0) {
8544 MonoReflectionField *f = (MonoReflectionField*)obj;
8546 if (is_field_on_inst (f->field)) {
8547 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8549 if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8550 int field_index = f->field - dgclass->fields;
8551 MonoObject *obj;
8553 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8554 obj = dgclass->field_objects [field_index];
8555 return mono_reflection_get_token (obj);
8558 token = mono_class_get_field_token (f->field);
8559 } else if (strcmp (klass->name, "MonoProperty") == 0) {
8560 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8562 token = mono_class_get_property_token (p->property);
8563 } else if (strcmp (klass->name, "MonoEvent") == 0) {
8564 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8566 token = mono_class_get_event_token (p->event);
8567 } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8568 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8569 MonoClass *member_class = mono_object_class (p->MemberImpl);
8570 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8572 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8573 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8574 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8576 token = m->token;
8577 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8578 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8579 } else {
8580 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8581 MonoException *ex = mono_get_exception_not_implemented (msg);
8582 g_free (msg);
8583 mono_raise_exception (ex);
8586 return token;
8589 static MonoClass*
8590 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8592 char *n;
8593 MonoType *t;
8594 int slen = mono_metadata_decode_value (p, &p);
8596 mono_error_init (error);
8598 n = (char *)g_memdup (p, slen + 1);
8599 n [slen] = 0;
8600 t = mono_reflection_type_from_name (n, image);
8601 if (!t) {
8602 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8603 /* We don't free n, it's consumed by mono_error */
8604 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8605 return NULL;
8607 g_free (n);
8608 p += slen;
8609 *end = p;
8610 return mono_class_from_mono_type (t);
8613 static void*
8614 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8616 int slen, type = t->type;
8617 MonoClass *tklass = t->data.klass;
8619 mono_error_init (error);
8621 handle_enum:
8622 switch (type) {
8623 case MONO_TYPE_U1:
8624 case MONO_TYPE_I1:
8625 case MONO_TYPE_BOOLEAN: {
8626 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8627 *bval = *p;
8628 *end = p + 1;
8629 return bval;
8631 case MONO_TYPE_CHAR:
8632 case MONO_TYPE_U2:
8633 case MONO_TYPE_I2: {
8634 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8635 *val = read16 (p);
8636 *end = p + 2;
8637 return val;
8639 #if SIZEOF_VOID_P == 4
8640 case MONO_TYPE_U:
8641 case MONO_TYPE_I:
8642 #endif
8643 case MONO_TYPE_R4:
8644 case MONO_TYPE_U4:
8645 case MONO_TYPE_I4: {
8646 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8647 *val = read32 (p);
8648 *end = p + 4;
8649 return val;
8651 #if SIZEOF_VOID_P == 8
8652 case MONO_TYPE_U: /* error out instead? this should probably not happen */
8653 case MONO_TYPE_I:
8654 #endif
8655 case MONO_TYPE_U8:
8656 case MONO_TYPE_I8: {
8657 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8658 *val = read64 (p);
8659 *end = p + 8;
8660 return val;
8662 case MONO_TYPE_R8: {
8663 double *val = (double *)g_malloc (sizeof (double));
8664 readr8 (p, val);
8665 *end = p + 8;
8666 return val;
8668 case MONO_TYPE_VALUETYPE:
8669 if (t->data.klass->enumtype) {
8670 type = mono_class_enum_basetype (t->data.klass)->type;
8671 goto handle_enum;
8672 } else {
8673 MonoClass *k = t->data.klass;
8675 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8676 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8677 *val = read64 (p);
8678 *end = p + 8;
8679 return val;
8682 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8683 break;
8685 case MONO_TYPE_STRING:
8686 if (*p == (char)0xFF) {
8687 *end = p + 1;
8688 return NULL;
8690 slen = mono_metadata_decode_value (p, &p);
8691 *end = p + slen;
8692 return mono_string_new_len (mono_domain_get (), p, slen);
8693 case MONO_TYPE_CLASS: {
8694 MonoReflectionType *rt;
8695 char *n;
8696 MonoType *t;
8697 if (*p == (char)0xFF) {
8698 *end = p + 1;
8699 return NULL;
8701 handle_type:
8702 slen = mono_metadata_decode_value (p, &p);
8703 n = (char *)g_memdup (p, slen + 1);
8704 n [slen] = 0;
8705 t = mono_reflection_type_from_name (n, image);
8706 if (!t) {
8707 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8708 /* We don't free n, it's consumed by mono_error */
8709 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8710 return NULL;
8712 g_free (n);
8713 *end = p + slen;
8715 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8716 if (!mono_error_ok (error))
8717 return NULL;
8719 return rt;
8721 case MONO_TYPE_OBJECT: {
8722 char subt = *p++;
8723 MonoObject *obj;
8724 MonoClass *subc = NULL;
8725 void *val;
8727 if (subt == 0x50) {
8728 goto handle_type;
8729 } else if (subt == 0x0E) {
8730 type = MONO_TYPE_STRING;
8731 goto handle_enum;
8732 } else if (subt == 0x1D) {
8733 MonoType simple_type = {{0}};
8734 int etype = *p;
8735 p ++;
8737 type = MONO_TYPE_SZARRAY;
8738 if (etype == 0x50) {
8739 tklass = mono_defaults.systemtype_class;
8740 } else if (etype == 0x55) {
8741 tklass = load_cattr_enum_type (image, p, &p, error);
8742 if (!mono_error_ok (error))
8743 return NULL;
8744 } else {
8745 if (etype == 0x51)
8746 /* See Partition II, Appendix B3 */
8747 etype = MONO_TYPE_OBJECT;
8748 simple_type.type = (MonoTypeEnum)etype;
8749 tklass = mono_class_from_mono_type (&simple_type);
8751 goto handle_enum;
8752 } else if (subt == 0x55) {
8753 char *n;
8754 MonoType *t;
8755 slen = mono_metadata_decode_value (p, &p);
8756 n = (char *)g_memdup (p, slen + 1);
8757 n [slen] = 0;
8758 t = mono_reflection_type_from_name (n, image);
8759 if (!t) {
8760 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8761 /* We don't free n, it's consumed by mono_error */
8762 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8763 return NULL;
8765 g_free (n);
8766 p += slen;
8767 subc = mono_class_from_mono_type (t);
8768 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8769 MonoType simple_type = {{0}};
8770 simple_type.type = (MonoTypeEnum)subt;
8771 subc = mono_class_from_mono_type (&simple_type);
8772 } else {
8773 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8775 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8776 obj = NULL;
8777 if (mono_error_ok (error)) {
8778 obj = mono_object_new_checked (mono_domain_get (), subc, error);
8779 g_assert (!subc->has_references);
8780 if (mono_error_ok (error))
8781 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8784 g_free (val);
8785 return obj;
8787 case MONO_TYPE_SZARRAY: {
8788 MonoArray *arr;
8789 guint32 i, alen, basetype;
8790 alen = read32 (p);
8791 p += 4;
8792 if (alen == 0xffffffff) {
8793 *end = p;
8794 return NULL;
8796 arr = mono_array_new (mono_domain_get(), tklass, alen);
8797 basetype = tklass->byval_arg.type;
8798 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8799 basetype = mono_class_enum_basetype (tklass)->type;
8800 switch (basetype)
8802 case MONO_TYPE_U1:
8803 case MONO_TYPE_I1:
8804 case MONO_TYPE_BOOLEAN:
8805 for (i = 0; i < alen; i++) {
8806 MonoBoolean val = *p++;
8807 mono_array_set (arr, MonoBoolean, i, val);
8809 break;
8810 case MONO_TYPE_CHAR:
8811 case MONO_TYPE_U2:
8812 case MONO_TYPE_I2:
8813 for (i = 0; i < alen; i++) {
8814 guint16 val = read16 (p);
8815 mono_array_set (arr, guint16, i, val);
8816 p += 2;
8818 break;
8819 case MONO_TYPE_R4:
8820 case MONO_TYPE_U4:
8821 case MONO_TYPE_I4:
8822 for (i = 0; i < alen; i++) {
8823 guint32 val = read32 (p);
8824 mono_array_set (arr, guint32, i, val);
8825 p += 4;
8827 break;
8828 case MONO_TYPE_R8:
8829 for (i = 0; i < alen; i++) {
8830 double val;
8831 readr8 (p, &val);
8832 mono_array_set (arr, double, i, val);
8833 p += 8;
8835 break;
8836 case MONO_TYPE_U8:
8837 case MONO_TYPE_I8:
8838 for (i = 0; i < alen; i++) {
8839 guint64 val = read64 (p);
8840 mono_array_set (arr, guint64, i, val);
8841 p += 8;
8843 break;
8844 case MONO_TYPE_CLASS:
8845 case MONO_TYPE_OBJECT:
8846 case MONO_TYPE_STRING:
8847 case MONO_TYPE_SZARRAY:
8848 for (i = 0; i < alen; i++) {
8849 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8850 if (!mono_error_ok (error))
8851 return NULL;
8852 mono_array_setref (arr, i, item);
8854 break;
8855 default:
8856 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8858 *end=p;
8859 return arr;
8861 default:
8862 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8864 return NULL;
8867 static MonoObject*
8868 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
8870 static MonoMethod *ctor;
8871 MonoObject *retval;
8872 void *params [2], *unboxed;
8874 mono_error_init (error);
8876 if (!ctor)
8877 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
8879 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
8880 return_val_if_nok (error, NULL);
8882 params [1] = val;
8883 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
8884 return_val_if_nok (error, NULL);
8885 unboxed = mono_object_unbox (retval);
8887 mono_runtime_invoke_checked (ctor, unboxed, params, error);
8888 return_val_if_nok (error, NULL);
8890 return retval;
8893 static MonoObject*
8894 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
8896 static MonoMethod *ctor;
8897 MonoObject *retval;
8898 void *unboxed, *params [2];
8900 mono_error_init (error);
8902 if (!ctor)
8903 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
8905 params [0] = minfo;
8906 params [1] = typedarg;
8907 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
8908 return_val_if_nok (error, NULL);
8910 unboxed = mono_object_unbox (retval);
8912 mono_runtime_invoke_checked (ctor, unboxed, params, error);
8913 return_val_if_nok (error, NULL);
8915 return retval;
8918 static gboolean
8919 type_is_reference (MonoType *type)
8921 switch (type->type) {
8922 case MONO_TYPE_BOOLEAN:
8923 case MONO_TYPE_CHAR:
8924 case MONO_TYPE_U:
8925 case MONO_TYPE_I:
8926 case MONO_TYPE_U1:
8927 case MONO_TYPE_I1:
8928 case MONO_TYPE_U2:
8929 case MONO_TYPE_I2:
8930 case MONO_TYPE_U4:
8931 case MONO_TYPE_I4:
8932 case MONO_TYPE_U8:
8933 case MONO_TYPE_I8:
8934 case MONO_TYPE_R8:
8935 case MONO_TYPE_R4:
8936 case MONO_TYPE_VALUETYPE:
8937 return FALSE;
8938 default:
8939 return TRUE;
8943 static void
8944 free_param_data (MonoMethodSignature *sig, void **params) {
8945 int i;
8946 for (i = 0; i < sig->param_count; ++i) {
8947 if (!type_is_reference (sig->params [i]))
8948 g_free (params [i]);
8953 * Find the field index in the metadata FieldDef table.
8955 static guint32
8956 find_field_index (MonoClass *klass, MonoClassField *field) {
8957 int i;
8959 for (i = 0; i < klass->field.count; ++i) {
8960 if (field == &klass->fields [i])
8961 return klass->field.first + 1 + i;
8963 return 0;
8967 * Find the property index in the metadata Property table.
8969 static guint32
8970 find_property_index (MonoClass *klass, MonoProperty *property) {
8971 int i;
8973 for (i = 0; i < klass->ext->property.count; ++i) {
8974 if (property == &klass->ext->properties [i])
8975 return klass->ext->property.first + 1 + i;
8977 return 0;
8981 * Find the event index in the metadata Event table.
8983 static guint32
8984 find_event_index (MonoClass *klass, MonoEvent *event) {
8985 int i;
8987 for (i = 0; i < klass->ext->event.count; ++i) {
8988 if (event == &klass->ext->events [i])
8989 return klass->ext->event.first + 1 + i;
8991 return 0;
8994 static MonoObject*
8995 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8997 const char *p = (const char*)data;
8998 const char *named;
8999 guint32 i, j, num_named;
9000 MonoObject *attr;
9001 void *params_buf [32];
9002 void **params = NULL;
9003 MonoMethodSignature *sig;
9004 MonoObject *exc = NULL;
9006 mono_error_init (error);
9008 mono_class_init (method->klass);
9010 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9011 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9012 return NULL;
9015 if (len == 0) {
9016 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9017 if (!mono_error_ok (error)) return NULL;
9019 mono_runtime_invoke_checked (method, attr, NULL, error);
9020 if (!mono_error_ok (error))
9021 return NULL;
9023 return attr;
9026 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9027 return NULL;
9029 /*g_print ("got attr %s\n", method->klass->name);*/
9031 sig = mono_method_signature (method);
9032 if (sig->param_count < 32) {
9033 params = params_buf;
9034 memset (params, 0, sizeof (void*) * sig->param_count);
9035 } else {
9036 /* Allocate using GC so it gets GC tracking */
9037 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9040 /* skip prolog */
9041 p += 2;
9042 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9043 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9044 if (!mono_error_ok (error))
9045 goto fail;
9048 named = p;
9049 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9050 if (!mono_error_ok (error)) goto fail;
9052 mono_runtime_try_invoke (method, attr, params, &exc, error);
9053 if (!mono_error_ok (error))
9054 goto fail;
9055 if (exc)
9056 goto fail;
9058 num_named = read16 (named);
9059 named += 2;
9060 for (j = 0; j < num_named; j++) {
9061 gint name_len;
9062 char *name, named_type, data_type;
9063 named_type = *named++;
9064 data_type = *named++; /* type of data */
9065 if (data_type == MONO_TYPE_SZARRAY)
9066 data_type = *named++;
9067 if (data_type == MONO_TYPE_ENUM) {
9068 gint type_len;
9069 char *type_name;
9070 type_len = mono_metadata_decode_blob_size (named, &named);
9071 type_name = (char *)g_malloc (type_len + 1);
9072 memcpy (type_name, named, type_len);
9073 type_name [type_len] = 0;
9074 named += type_len;
9075 /* FIXME: lookup the type and check type consistency */
9076 g_free (type_name);
9078 name_len = mono_metadata_decode_blob_size (named, &named);
9079 name = (char *)g_malloc (name_len + 1);
9080 memcpy (name, named, name_len);
9081 name [name_len] = 0;
9082 named += name_len;
9083 if (named_type == 0x53) {
9084 MonoClassField *field;
9085 void *val;
9087 /* how this fail is a blackbox */
9088 field = mono_class_get_field_from_name (mono_object_class (attr), name);
9089 if (!field) {
9090 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9091 g_free (name);
9092 goto fail;
9095 val = load_cattr_value (image, field->type, named, &named, error);
9096 if (!mono_error_ok (error)) {
9097 g_free (name);
9098 if (!type_is_reference (field->type))
9099 g_free (val);
9100 goto fail;
9103 mono_field_set_value (attr, field, val);
9104 if (!type_is_reference (field->type))
9105 g_free (val);
9106 } else if (named_type == 0x54) {
9107 MonoProperty *prop;
9108 void *pparams [1];
9109 MonoType *prop_type;
9111 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9113 if (!prop) {
9114 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9115 g_free (name);
9116 goto fail;
9119 if (!prop->set) {
9120 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9121 g_free (name);
9122 goto fail;
9125 /* can we have more that 1 arg in a custom attr named property? */
9126 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9127 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9129 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9130 if (!mono_error_ok (error)) {
9131 g_free (name);
9132 if (!type_is_reference (prop_type))
9133 g_free (pparams [0]);
9134 goto fail;
9138 mono_property_set_value (prop, attr, pparams, NULL);
9139 if (!type_is_reference (prop_type))
9140 g_free (pparams [0]);
9142 g_free (name);
9145 free_param_data (method->signature, params);
9146 if (params != params_buf)
9147 mono_gc_free_fixed (params);
9149 return attr;
9151 fail:
9152 free_param_data (method->signature, params);
9153 if (params != params_buf)
9154 mono_gc_free_fixed (params);
9155 if (exc)
9156 mono_raise_exception ((MonoException*)exc);
9157 return NULL;
9161 * mono_reflection_create_custom_attr_data_args:
9163 * Create an array of typed and named arguments from the cattr blob given by DATA.
9164 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9165 * NAMED_ARG_INFO will contain information about the named arguments.
9167 void
9168 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)
9170 MonoArray *typedargs, *namedargs;
9171 MonoClass *attrklass;
9172 MonoDomain *domain;
9173 const char *p = (const char*)data;
9174 const char *named;
9175 guint32 i, j, num_named;
9176 CattrNamedArg *arginfo = NULL;
9178 *typed_args = NULL;
9179 *named_args = NULL;
9180 *named_arg_info = NULL;
9182 mono_error_init (error);
9184 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9185 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9186 return;
9189 mono_class_init (method->klass);
9191 domain = mono_domain_get ();
9193 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9194 return;
9196 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9198 /* skip prolog */
9199 p += 2;
9200 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9201 MonoObject *obj;
9202 void *val;
9204 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9205 if (!mono_error_ok (error)) {
9206 if (!type_is_reference (mono_method_signature (method)->params [i]))
9207 g_free (val);
9208 return;
9211 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9212 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9213 mono_array_setref (typedargs, i, obj);
9215 if (!type_is_reference (mono_method_signature (method)->params [i]))
9216 g_free (val);
9219 named = p;
9220 num_named = read16 (named);
9221 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9222 named += 2;
9223 attrklass = method->klass;
9225 arginfo = g_new0 (CattrNamedArg, num_named);
9226 *named_arg_info = arginfo;
9228 for (j = 0; j < num_named; j++) {
9229 gint name_len;
9230 char *name, named_type, data_type;
9231 named_type = *named++;
9232 data_type = *named++; /* type of data */
9233 if (data_type == MONO_TYPE_SZARRAY)
9234 data_type = *named++;
9235 if (data_type == MONO_TYPE_ENUM) {
9236 gint type_len;
9237 char *type_name;
9238 type_len = mono_metadata_decode_blob_size (named, &named);
9239 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9240 goto fail;
9242 type_name = (char *)g_malloc (type_len + 1);
9243 memcpy (type_name, named, type_len);
9244 type_name [type_len] = 0;
9245 named += type_len;
9246 /* FIXME: lookup the type and check type consistency */
9247 g_free (type_name);
9249 name_len = mono_metadata_decode_blob_size (named, &named);
9250 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9251 goto fail;
9252 name = (char *)g_malloc (name_len + 1);
9253 memcpy (name, named, name_len);
9254 name [name_len] = 0;
9255 named += name_len;
9256 if (named_type == 0x53) {
9257 MonoObject *obj;
9258 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9259 void *val;
9261 if (!field) {
9262 g_free (name);
9263 goto fail;
9266 arginfo [j].type = field->type;
9267 arginfo [j].field = field;
9269 val = load_cattr_value (image, field->type, named, &named, error);
9270 if (!mono_error_ok (error)) {
9271 if (!type_is_reference (field->type))
9272 g_free (val);
9273 g_free (name);
9274 return;
9277 obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9278 mono_array_setref (namedargs, j, obj);
9279 if (!type_is_reference (field->type))
9280 g_free (val);
9281 } else if (named_type == 0x54) {
9282 MonoObject *obj;
9283 MonoType *prop_type;
9284 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9285 void *val;
9287 if (!prop || !prop->set) {
9288 g_free (name);
9289 goto fail;
9292 prop_type = prop->get? mono_method_signature (prop->get)->ret :
9293 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9295 arginfo [j].type = prop_type;
9296 arginfo [j].prop = prop;
9298 val = load_cattr_value (image, prop_type, named, &named, error);
9299 if (!mono_error_ok (error)) {
9300 if (!type_is_reference (prop_type))
9301 g_free (val);
9302 g_free (name);
9303 return;
9306 obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9307 mono_array_setref (namedargs, j, obj);
9308 if (!type_is_reference (prop_type))
9309 g_free (val);
9311 g_free (name);
9314 *typed_args = typedargs;
9315 *named_args = namedargs;
9316 return;
9317 fail:
9318 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9319 g_free (arginfo);
9320 *named_arg_info = NULL;
9323 void
9324 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9326 MonoDomain *domain;
9327 MonoArray *typedargs, *namedargs;
9328 MonoImage *image;
9329 MonoMethod *method;
9330 CattrNamedArg *arginfo = NULL;
9331 MonoError error;
9332 int i;
9334 mono_error_init (&error);
9336 *ctor_args = NULL;
9337 *named_args = NULL;
9339 if (len == 0)
9340 return;
9342 image = assembly->assembly->image;
9343 method = ref_method->method;
9344 domain = mono_object_domain (ref_method);
9346 if (!mono_class_init (method->klass))
9347 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9349 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9350 if (!mono_error_ok (&error))
9351 goto leave;
9353 if (mono_loader_get_last_error ()) {
9354 mono_error_set_from_loader_error (&error);
9355 goto leave;
9358 if (!typedargs || !namedargs)
9359 goto leave;
9361 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9362 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9363 MonoObject *typedarg;
9365 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9366 if (!is_ok (&error))
9367 goto leave;
9368 mono_array_setref (typedargs, i, typedarg);
9371 for (i = 0; i < mono_array_length (namedargs); ++i) {
9372 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9373 MonoObject *typedarg, *namedarg, *minfo;
9375 if (arginfo [i].prop) {
9376 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9377 if (!minfo)
9378 goto leave;
9379 } else {
9380 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9381 if (!mono_error_ok (&error))
9382 goto leave;
9385 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9386 if (!is_ok (&error))
9387 goto leave;
9388 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9389 if (!is_ok (&error))
9390 goto leave;
9392 mono_array_setref (namedargs, i, namedarg);
9395 *ctor_args = typedargs;
9396 *named_args = namedargs;
9397 leave:
9398 g_free (arginfo);
9399 mono_error_raise_exception (&error);
9403 static MonoObject*
9404 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9406 static MonoMethod *ctor;
9408 MonoDomain *domain;
9409 MonoObject *attr;
9410 void *params [4];
9412 mono_error_init (error);
9414 g_assert (image->assembly);
9416 if (!ctor)
9417 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9419 domain = mono_domain_get ();
9420 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9421 return_val_if_nok (error, NULL);
9422 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9423 return_val_if_nok (error, NULL);
9424 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9425 return_val_if_nok (error, NULL);
9426 params [2] = (gpointer)&cattr->data;
9427 params [3] = &cattr->data_size;
9429 mono_runtime_invoke_checked (ctor, attr, params, error);
9430 return_val_if_nok (error, NULL);
9431 return attr;
9434 static MonoArray*
9435 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9437 MonoArray *result;
9438 MonoObject *attr;
9439 int i, n;
9441 mono_error_init (error);
9443 n = 0;
9444 for (i = 0; i < cinfo->num_attrs; ++i) {
9445 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9446 n ++;
9449 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9450 n = 0;
9451 for (i = 0; i < cinfo->num_attrs; ++i) {
9452 if (!cinfo->attrs [i].ctor) {
9453 /* The cattr type is not finished yet */
9454 /* We should include the type name but cinfo doesn't contain it */
9455 mono_error_set_type_load_name (error, NULL, NULL, "");
9456 return NULL;
9458 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9459 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9460 if (!mono_error_ok (error))
9461 return result;
9462 mono_array_setref (result, n, attr);
9463 n ++;
9466 return result;
9469 MonoArray*
9470 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9472 MonoError error;
9473 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9474 mono_error_assert_ok (&error); /*FIXME proper error handling*/
9476 return result;
9479 static MonoArray*
9480 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9482 MonoArray *result;
9483 MonoObject *attr;
9484 int i;
9486 mono_error_init (error);
9487 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9488 for (i = 0; i < cinfo->num_attrs; ++i) {
9489 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9490 return_val_if_nok (error, NULL);
9491 mono_array_setref (result, i, attr);
9493 return result;
9497 * mono_custom_attrs_from_index:
9499 * Returns: NULL if no attributes are found or if a loading error occurs.
9501 MonoCustomAttrInfo*
9502 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9504 MonoError error;
9505 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9506 mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9507 return result;
9510 * mono_custom_attrs_from_index_checked:
9512 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9514 MonoCustomAttrInfo*
9515 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9517 guint32 mtoken, i, len;
9518 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9519 MonoTableInfo *ca;
9520 MonoCustomAttrInfo *ainfo;
9521 GList *tmp, *list = NULL;
9522 const char *data;
9523 MonoCustomAttrEntry* attr;
9525 mono_error_init (error);
9527 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9529 i = mono_metadata_custom_attrs_from_index (image, idx);
9530 if (!i)
9531 return NULL;
9532 i --;
9533 while (i < ca->rows) {
9534 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9535 break;
9536 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9537 ++i;
9539 len = g_list_length (list);
9540 if (!len)
9541 return NULL;
9542 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9543 ainfo->num_attrs = len;
9544 ainfo->image = image;
9545 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9546 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9547 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9548 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9549 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9550 mtoken |= MONO_TOKEN_METHOD_DEF;
9551 break;
9552 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9553 mtoken |= MONO_TOKEN_MEMBER_REF;
9554 break;
9555 default:
9556 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9557 break;
9559 attr = &ainfo->attrs [i - 1];
9560 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9561 if (!attr->ctor) {
9562 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9563 g_list_free (list);
9564 g_free (ainfo);
9565 return NULL;
9568 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9569 /*FIXME raising an exception here doesn't make any sense*/
9570 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9571 g_list_free (list);
9572 g_free (ainfo);
9573 return NULL;
9575 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9576 attr->data_size = mono_metadata_decode_value (data, &data);
9577 attr->data = (guchar*)data;
9579 g_list_free (list);
9581 return ainfo;
9584 MonoCustomAttrInfo*
9585 mono_custom_attrs_from_method (MonoMethod *method)
9587 MonoError error;
9588 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
9589 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9590 return result;
9593 MonoCustomAttrInfo*
9594 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9596 guint32 idx;
9598 mono_error_init (error);
9601 * An instantiated method has the same cattrs as the generic method definition.
9603 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9604 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9606 if (method->is_inflated)
9607 method = ((MonoMethodInflated *) method)->declaring;
9609 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9610 return lookup_custom_attr (method->klass->image, method);
9612 if (!method->token)
9613 /* Synthetic methods */
9614 return NULL;
9616 idx = mono_method_get_index (method);
9617 idx <<= MONO_CUSTOM_ATTR_BITS;
9618 idx |= MONO_CUSTOM_ATTR_METHODDEF;
9619 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9622 MonoCustomAttrInfo*
9623 mono_custom_attrs_from_class (MonoClass *klass)
9625 MonoError error;
9626 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9627 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9628 return result;
9631 MonoCustomAttrInfo*
9632 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9634 guint32 idx;
9636 mono_error_init (error);
9638 if (klass->generic_class)
9639 klass = klass->generic_class->container_class;
9641 if (image_is_dynamic (klass->image))
9642 return lookup_custom_attr (klass->image, klass);
9644 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9645 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9646 idx <<= MONO_CUSTOM_ATTR_BITS;
9647 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9648 } else {
9649 idx = mono_metadata_token_index (klass->type_token);
9650 idx <<= MONO_CUSTOM_ATTR_BITS;
9651 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9653 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9656 MonoCustomAttrInfo*
9657 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9659 MonoError error;
9660 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9661 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9662 return result;
9665 MonoCustomAttrInfo*
9666 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9668 guint32 idx;
9670 mono_error_init (error);
9672 if (image_is_dynamic (assembly->image))
9673 return lookup_custom_attr (assembly->image, assembly);
9674 idx = 1; /* there is only one assembly */
9675 idx <<= MONO_CUSTOM_ATTR_BITS;
9676 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9677 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9680 static MonoCustomAttrInfo*
9681 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9683 guint32 idx;
9685 if (image_is_dynamic (image))
9686 return lookup_custom_attr (image, image);
9687 idx = 1; /* there is only one module */
9688 idx <<= MONO_CUSTOM_ATTR_BITS;
9689 idx |= MONO_CUSTOM_ATTR_MODULE;
9690 return mono_custom_attrs_from_index_checked (image, idx, error);
9693 MonoCustomAttrInfo*
9694 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9696 MonoError error;
9697 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9698 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9699 return result;
9702 MonoCustomAttrInfo*
9703 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9705 guint32 idx;
9707 if (image_is_dynamic (klass->image)) {
9708 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9709 return lookup_custom_attr (klass->image, property);
9711 idx = find_property_index (klass, property);
9712 idx <<= MONO_CUSTOM_ATTR_BITS;
9713 idx |= MONO_CUSTOM_ATTR_PROPERTY;
9714 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9717 MonoCustomAttrInfo*
9718 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9720 MonoError error;
9721 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9722 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9723 return result;
9726 MonoCustomAttrInfo*
9727 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9729 guint32 idx;
9731 if (image_is_dynamic (klass->image)) {
9732 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9733 return lookup_custom_attr (klass->image, event);
9735 idx = find_event_index (klass, event);
9736 idx <<= MONO_CUSTOM_ATTR_BITS;
9737 idx |= MONO_CUSTOM_ATTR_EVENT;
9738 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9741 MonoCustomAttrInfo*
9742 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9744 MonoError error;
9745 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9746 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9747 return result;
9750 MonoCustomAttrInfo*
9751 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9753 guint32 idx;
9754 mono_error_init (error);
9756 if (image_is_dynamic (klass->image)) {
9757 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9758 return lookup_custom_attr (klass->image, field);
9760 idx = find_field_index (klass, field);
9761 idx <<= MONO_CUSTOM_ATTR_BITS;
9762 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9763 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9767 * mono_custom_attrs_from_param:
9768 * @method: handle to the method that we want to retrieve custom parameter information from
9769 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9771 * The result must be released with mono_custom_attrs_free().
9773 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9775 MonoCustomAttrInfo*
9776 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9778 MonoError error;
9779 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9780 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9781 return result;
9785 * mono_custom_attrs_from_param_checked:
9786 * @method: handle to the method that we want to retrieve custom parameter information from
9787 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9788 * @error: set on error
9790 * The result must be released with mono_custom_attrs_free().
9792 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
9794 MonoCustomAttrInfo*
9795 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9797 MonoTableInfo *ca;
9798 guint32 i, idx, method_index;
9799 guint32 param_list, param_last, param_pos, found;
9800 MonoImage *image;
9801 MonoReflectionMethodAux *aux;
9803 mono_error_init (error);
9806 * An instantiated method has the same cattrs as the generic method definition.
9808 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9809 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9811 if (method->is_inflated)
9812 method = ((MonoMethodInflated *) method)->declaring;
9814 if (image_is_dynamic (method->klass->image)) {
9815 MonoCustomAttrInfo *res, *ainfo;
9816 int size;
9818 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9819 if (!aux || !aux->param_cattr)
9820 return NULL;
9822 /* Need to copy since it will be freed later */
9823 ainfo = aux->param_cattr [param];
9824 if (!ainfo)
9825 return NULL;
9826 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9827 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9828 memcpy (res, ainfo, size);
9829 return res;
9832 image = method->klass->image;
9833 method_index = mono_method_get_index (method);
9834 if (!method_index)
9835 return NULL;
9836 ca = &image->tables [MONO_TABLE_METHOD];
9838 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9839 if (method_index == ca->rows) {
9840 ca = &image->tables [MONO_TABLE_PARAM];
9841 param_last = ca->rows + 1;
9842 } else {
9843 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9844 ca = &image->tables [MONO_TABLE_PARAM];
9846 found = FALSE;
9847 for (i = param_list; i < param_last; ++i) {
9848 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9849 if (param_pos == param) {
9850 found = TRUE;
9851 break;
9854 if (!found)
9855 return NULL;
9856 idx = i;
9857 idx <<= MONO_CUSTOM_ATTR_BITS;
9858 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9859 return mono_custom_attrs_from_index_checked (image, idx, error);
9862 gboolean
9863 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9865 int i;
9866 MonoClass *klass;
9867 for (i = 0; i < ainfo->num_attrs; ++i) {
9868 klass = ainfo->attrs [i].ctor->klass;
9869 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9870 return TRUE;
9872 return FALSE;
9875 MonoObject*
9876 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9878 MonoError error;
9879 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9880 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9881 return res;
9884 MonoObject*
9885 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9887 int i, attr_index;
9888 MonoClass *klass;
9889 MonoArray *attrs;
9891 mono_error_init (error);
9893 attr_index = -1;
9894 for (i = 0; i < ainfo->num_attrs; ++i) {
9895 klass = ainfo->attrs [i].ctor->klass;
9896 if (mono_class_has_parent (klass, attr_klass)) {
9897 attr_index = i;
9898 break;
9901 if (attr_index == -1)
9902 return NULL;
9904 attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9905 if (!mono_error_ok (error))
9906 return NULL;
9907 return mono_array_get (attrs, MonoObject*, attr_index);
9911 * mono_reflection_get_custom_attrs_info:
9912 * @obj: a reflection object handle
9914 * Return the custom attribute info for attributes defined for the
9915 * reflection handle @obj. The objects.
9917 * FIXME this function leaks like a sieve for SRE objects.
9919 MonoCustomAttrInfo*
9920 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9922 MonoError error;
9923 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
9924 mono_error_assert_ok (&error);
9925 return result;
9929 * mono_reflection_get_custom_attrs_info_checked:
9930 * @obj: a reflection object handle
9931 * @error: set on error
9933 * Return the custom attribute info for attributes defined for the
9934 * reflection handle @obj. The objects.
9936 * On failure returns NULL and sets @error.
9938 * FIXME this function leaks like a sieve for SRE objects.
9940 MonoCustomAttrInfo*
9941 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
9943 MonoClass *klass;
9944 MonoCustomAttrInfo *cinfo = NULL;
9946 mono_error_init (error);
9948 klass = obj->vtable->klass;
9949 if (klass == mono_defaults.monotype_class) {
9950 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9951 klass = mono_class_from_mono_type (type);
9952 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9953 cinfo = mono_custom_attrs_from_class_checked (klass, error);
9954 return_val_if_nok (error, NULL);
9955 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9956 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9957 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
9958 return_val_if_nok (error, NULL);
9959 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9960 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9961 cinfo = mono_custom_attrs_from_module (module->image, error);
9962 return_val_if_nok (error, NULL);
9963 } else if (strcmp ("MonoProperty", klass->name) == 0) {
9964 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9965 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
9966 return_val_if_nok (error, NULL);
9967 } else if (strcmp ("MonoEvent", klass->name) == 0) {
9968 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9969 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
9970 return_val_if_nok (error, NULL);
9971 } else if (strcmp ("MonoField", klass->name) == 0) {
9972 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9973 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
9974 return_val_if_nok (error, NULL);
9975 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9976 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9977 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9978 return_val_if_nok (error, NULL);
9979 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9980 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9981 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9982 return_val_if_nok (error, NULL);
9983 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9984 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9985 MonoClass *member_class = mono_object_class (param->MemberImpl);
9986 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9987 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9988 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
9989 return_val_if_nok (error, NULL);
9990 } else if (is_sr_mono_property (member_class)) {
9991 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9992 MonoMethod *method;
9993 if (!(method = prop->property->get))
9994 method = prop->property->set;
9995 g_assert (method);
9997 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
9998 return_val_if_nok (error, NULL);
10000 #ifndef DISABLE_REFLECTION_EMIT
10001 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10002 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10003 return_val_if_nok (error, NULL);
10004 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10005 return_val_if_nok (error, NULL);
10006 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10007 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10008 MonoMethod *method = NULL;
10009 if (is_sre_ctor_builder (mono_object_class (c->cb)))
10010 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10011 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10012 method = ((MonoReflectionMethod *)c->cb)->method;
10013 else
10014 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));
10016 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10017 return_val_if_nok (error, NULL);
10019 #endif
10020 else {
10021 char *type_name = mono_type_get_full_name (member_class);
10022 mono_error_set_generic_error (error, "System", "NotSupportedException",
10023 "Custom attributes on a ParamInfo with member %s are not supported",
10024 type_name);
10025 g_free (type_name);
10026 return NULL;
10028 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10029 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10030 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10031 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10032 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10033 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10034 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10035 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10036 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10037 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10038 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10039 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10040 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10041 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10042 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10043 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10044 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10045 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10046 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10047 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10048 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10049 return_val_if_nok (error, NULL);
10050 } else { /* handle other types here... */
10051 g_error ("get custom attrs not yet supported for %s", klass->name);
10054 return cinfo;
10058 * mono_reflection_get_custom_attrs_by_type:
10059 * @obj: a reflection object handle
10061 * Return an array with all the custom attributes defined of the
10062 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10063 * of that type are returned. The objects are fully build. Return NULL if a loading error
10064 * occurs.
10066 MonoArray*
10067 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10069 MonoArray *result;
10070 MonoCustomAttrInfo *cinfo;
10072 mono_error_init (error);
10074 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10075 return_val_if_nok (error, NULL);
10076 if (cinfo) {
10077 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10078 if (!result)
10079 return NULL;
10080 if (!cinfo->cached)
10081 mono_custom_attrs_free (cinfo);
10082 } else {
10083 mono_loader_assert_no_error ();
10084 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10087 return result;
10091 * mono_reflection_get_custom_attrs:
10092 * @obj: a reflection object handle
10094 * Return an array with all the custom attributes defined of the
10095 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10096 * occurs.
10098 MonoArray*
10099 mono_reflection_get_custom_attrs (MonoObject *obj)
10101 MonoError error;
10103 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10107 * mono_reflection_get_custom_attrs_data:
10108 * @obj: a reflection obj handle
10110 * Returns an array of System.Reflection.CustomAttributeData,
10111 * which include information about attributes reflected on
10112 * types loaded using the Reflection Only methods
10114 MonoArray*
10115 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10117 MonoError error;
10118 MonoArray* result;
10119 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10120 mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10121 return result;
10125 * mono_reflection_get_custom_attrs_data_checked:
10126 * @obj: a reflection obj handle
10127 * @error: set on error
10129 * Returns an array of System.Reflection.CustomAttributeData,
10130 * which include information about attributes reflected on
10131 * types loaded using the Reflection Only methods
10133 MonoArray*
10134 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10136 MonoArray *result;
10137 MonoCustomAttrInfo *cinfo;
10139 mono_error_init (error);
10141 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10142 return_val_if_nok (error, NULL);
10143 if (cinfo) {
10144 result = mono_custom_attrs_data_construct (cinfo, error);
10145 return_val_if_nok (error, NULL);
10146 if (!cinfo->cached)
10147 mono_custom_attrs_free (cinfo);
10148 } else
10149 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10151 if (mono_loader_get_last_error ())
10152 mono_error_set_from_loader_error (error);
10154 return result;
10157 static MonoReflectionType*
10158 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10160 static MonoMethod *method_get_underlying_system_type = NULL;
10161 MonoReflectionType *rt;
10162 MonoMethod *usertype_method;
10164 mono_error_init (error);
10166 if (!method_get_underlying_system_type)
10167 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10169 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10171 rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10173 return rt;
10177 static gboolean
10178 is_corlib_type (MonoClass *klass)
10180 return klass->image == mono_defaults.corlib;
10183 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10184 static MonoClass *cached_class; \
10185 if (cached_class) \
10186 return cached_class == _class; \
10187 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10188 cached_class = _class; \
10189 return TRUE; \
10191 return FALSE; \
10192 } while (0) \
10195 #ifndef DISABLE_REFLECTION_EMIT
10196 static gboolean
10197 is_sre_array (MonoClass *klass)
10199 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10202 static gboolean
10203 is_sre_byref (MonoClass *klass)
10205 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10208 static gboolean
10209 is_sre_pointer (MonoClass *klass)
10211 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10214 static gboolean
10215 is_sre_generic_instance (MonoClass *klass)
10217 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10220 static gboolean
10221 is_sre_type_builder (MonoClass *klass)
10223 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10226 static gboolean
10227 is_sre_method_builder (MonoClass *klass)
10229 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10232 static gboolean
10233 is_sre_ctor_builder (MonoClass *klass)
10235 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10238 static gboolean
10239 is_sre_field_builder (MonoClass *klass)
10241 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10244 static gboolean
10245 is_sre_method_on_tb_inst (MonoClass *klass)
10247 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10250 static gboolean
10251 is_sre_ctor_on_tb_inst (MonoClass *klass)
10253 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10256 MonoType*
10257 mono_reflection_type_get_handle (MonoReflectionType* ref)
10259 MonoError error;
10260 MonoClass *klass;
10261 if (!ref)
10262 return NULL;
10263 if (ref->type)
10264 return ref->type;
10266 if (is_usertype (ref)) {
10267 ref = mono_reflection_type_get_underlying_system_type (ref, &error);
10268 mono_error_raise_exception (&error); /* FIXME don't raise here */
10269 if (ref == NULL || is_usertype (ref))
10270 return NULL;
10271 if (ref->type)
10272 return ref->type;
10275 klass = mono_object_class (ref);
10277 if (is_sre_array (klass)) {
10278 MonoType *res;
10279 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10280 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
10281 g_assert (base);
10282 if (sre_array->rank == 0) //single dimentional array
10283 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10284 else
10285 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10286 sre_array->type.type = res;
10287 return res;
10288 } else if (is_sre_byref (klass)) {
10289 MonoType *res;
10290 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10291 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
10292 g_assert (base);
10293 res = &mono_class_from_mono_type (base)->this_arg;
10294 sre_byref->type.type = res;
10295 return res;
10296 } else if (is_sre_pointer (klass)) {
10297 MonoType *res;
10298 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10299 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
10300 g_assert (base);
10301 res = &mono_ptr_class_get (base)->byval_arg;
10302 sre_pointer->type.type = res;
10303 return res;
10304 } else if (is_sre_generic_instance (klass)) {
10305 MonoType *res, **types;
10306 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10307 int i, count;
10309 count = mono_array_length (gclass->type_arguments);
10310 types = g_new0 (MonoType*, count);
10311 for (i = 0; i < count; ++i) {
10312 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10313 types [i] = mono_reflection_type_get_handle (t);
10314 if (!types[i]) {
10315 g_free (types);
10316 return NULL;
10320 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10321 g_free (types);
10322 g_assert (res);
10323 gclass->type.type = res;
10324 return res;
10327 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10328 return NULL;
10333 void
10334 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10336 mono_reflection_type_get_handle (type);
10339 void
10340 mono_reflection_register_with_runtime (MonoReflectionType *type)
10342 MonoType *res = mono_reflection_type_get_handle (type);
10343 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10344 MonoClass *klass;
10346 if (!res)
10347 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10349 klass = mono_class_from_mono_type (res);
10351 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10352 mono_domain_lock (domain);
10354 if (!image_is_dynamic (klass->image)) {
10355 mono_class_setup_supertypes (klass);
10356 } else {
10357 if (!domain->type_hash)
10358 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
10359 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10360 mono_g_hash_table_insert (domain->type_hash, res, type);
10362 mono_domain_unlock (domain);
10363 mono_loader_unlock ();
10367 * LOCKING: Assumes the loader lock is held.
10369 static MonoMethodSignature*
10370 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10371 MonoMethodSignature *sig;
10372 int count, i;
10374 count = parameters? mono_array_length (parameters): 0;
10376 sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10377 sig->param_count = count;
10378 sig->sentinelpos = -1; /* FIXME */
10379 for (i = 0; i < count; ++i)
10380 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10381 return sig;
10385 * LOCKING: Assumes the loader lock is held.
10387 static MonoMethodSignature*
10388 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10389 MonoMethodSignature *sig;
10391 sig = parameters_to_signature (image, ctor->parameters);
10392 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10393 sig->ret = &mono_defaults.void_class->byval_arg;
10394 return sig;
10398 * LOCKING: Assumes the loader lock is held.
10400 static MonoMethodSignature*
10401 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10402 MonoMethodSignature *sig;
10404 sig = parameters_to_signature (image, method->parameters);
10405 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10406 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10407 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10408 return sig;
10411 static MonoMethodSignature*
10412 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10413 MonoMethodSignature *sig;
10415 sig = parameters_to_signature (NULL, method->parameters);
10416 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10417 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10418 sig->generic_param_count = 0;
10419 return sig;
10422 static void
10423 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10425 MonoClass *klass = mono_object_class (prop);
10426 if (strcmp (klass->name, "PropertyBuilder") == 0) {
10427 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10428 *name = mono_string_to_utf8 (pb->name);
10429 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10430 } else {
10431 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10432 *name = g_strdup (p->property->name);
10433 if (p->property->get)
10434 *type = mono_method_signature (p->property->get)->ret;
10435 else
10436 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10440 static void
10441 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10443 MonoClass *klass = mono_object_class (field);
10444 if (strcmp (klass->name, "FieldBuilder") == 0) {
10445 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10446 *name = mono_string_to_utf8 (fb->name);
10447 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10448 } else {
10449 MonoReflectionField *f = (MonoReflectionField *)field;
10450 *name = g_strdup (mono_field_get_name (f->field));
10451 *type = f->field->type;
10455 #else /* DISABLE_REFLECTION_EMIT */
10457 void
10458 mono_reflection_register_with_runtime (MonoReflectionType *type)
10460 /* This is empty */
10463 static gboolean
10464 is_sre_type_builder (MonoClass *klass)
10466 return FALSE;
10469 static gboolean
10470 is_sre_generic_instance (MonoClass *klass)
10472 return FALSE;
10475 static void
10476 init_type_builder_generics (MonoObject *type)
10480 #endif /* !DISABLE_REFLECTION_EMIT */
10483 static gboolean
10484 is_sr_mono_field (MonoClass *klass)
10486 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10489 static gboolean
10490 is_sr_mono_property (MonoClass *klass)
10492 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10495 static gboolean
10496 is_sr_mono_method (MonoClass *klass)
10498 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10501 static gboolean
10502 is_sr_mono_cmethod (MonoClass *klass)
10504 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10507 static gboolean
10508 is_sr_mono_generic_method (MonoClass *klass)
10510 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10513 static gboolean
10514 is_sr_mono_generic_cmethod (MonoClass *klass)
10516 check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10519 gboolean
10520 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10522 return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10525 static gboolean
10526 is_usertype (MonoReflectionType *ref)
10528 MonoClass *klass = mono_object_class (ref);
10529 return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10532 static MonoReflectionType*
10533 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10535 mono_error_init (error);
10536 if (!type || type->type)
10537 return type;
10539 if (is_usertype (type)) {
10540 type = mono_reflection_type_get_underlying_system_type (type, error);
10541 return_val_if_nok (error, NULL);
10542 if (is_usertype (type)) {
10543 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10544 return NULL;
10548 return type;
10551 * Encode a value in a custom attribute stream of bytes.
10552 * The value to encode is either supplied as an object in argument val
10553 * (valuetypes are boxed), or as a pointer to the data in the
10554 * argument argval.
10555 * @type represents the type of the value
10556 * @buffer is the start of the buffer
10557 * @p the current position in the buffer
10558 * @buflen contains the size of the buffer and is used to return the new buffer size
10559 * if this needs to be realloced.
10560 * @retbuffer and @retp return the start and the position of the buffer
10562 static void
10563 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10565 MonoTypeEnum simple_type;
10567 if ((p-buffer) + 10 >= *buflen) {
10568 char *newbuf;
10569 *buflen *= 2;
10570 newbuf = (char *)g_realloc (buffer, *buflen);
10571 p = newbuf + (p-buffer);
10572 buffer = newbuf;
10574 if (!argval)
10575 argval = ((char*)arg + sizeof (MonoObject));
10576 simple_type = type->type;
10577 handle_enum:
10578 switch (simple_type) {
10579 case MONO_TYPE_BOOLEAN:
10580 case MONO_TYPE_U1:
10581 case MONO_TYPE_I1:
10582 *p++ = *argval;
10583 break;
10584 case MONO_TYPE_CHAR:
10585 case MONO_TYPE_U2:
10586 case MONO_TYPE_I2:
10587 swap_with_size (p, argval, 2, 1);
10588 p += 2;
10589 break;
10590 case MONO_TYPE_U4:
10591 case MONO_TYPE_I4:
10592 case MONO_TYPE_R4:
10593 swap_with_size (p, argval, 4, 1);
10594 p += 4;
10595 break;
10596 case MONO_TYPE_R8:
10597 swap_with_size (p, argval, 8, 1);
10598 p += 8;
10599 break;
10600 case MONO_TYPE_U8:
10601 case MONO_TYPE_I8:
10602 swap_with_size (p, argval, 8, 1);
10603 p += 8;
10604 break;
10605 case MONO_TYPE_VALUETYPE:
10606 if (type->data.klass->enumtype) {
10607 simple_type = mono_class_enum_basetype (type->data.klass)->type;
10608 goto handle_enum;
10609 } else {
10610 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10612 break;
10613 case MONO_TYPE_STRING: {
10614 char *str;
10615 guint32 slen;
10616 if (!arg) {
10617 *p++ = 0xFF;
10618 break;
10620 str = mono_string_to_utf8 ((MonoString*)arg);
10621 slen = strlen (str);
10622 if ((p-buffer) + 10 + slen >= *buflen) {
10623 char *newbuf;
10624 *buflen *= 2;
10625 *buflen += slen;
10626 newbuf = (char *)g_realloc (buffer, *buflen);
10627 p = newbuf + (p-buffer);
10628 buffer = newbuf;
10630 mono_metadata_encode_value (slen, p, &p);
10631 memcpy (p, str, slen);
10632 p += slen;
10633 g_free (str);
10634 break;
10636 case MONO_TYPE_CLASS: {
10637 char *str;
10638 guint32 slen;
10639 if (!arg) {
10640 *p++ = 0xFF;
10641 break;
10643 handle_type:
10644 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10645 slen = strlen (str);
10646 if ((p-buffer) + 10 + slen >= *buflen) {
10647 char *newbuf;
10648 *buflen *= 2;
10649 *buflen += slen;
10650 newbuf = (char *)g_realloc (buffer, *buflen);
10651 p = newbuf + (p-buffer);
10652 buffer = newbuf;
10654 mono_metadata_encode_value (slen, p, &p);
10655 memcpy (p, str, slen);
10656 p += slen;
10657 g_free (str);
10658 break;
10660 case MONO_TYPE_SZARRAY: {
10661 int len, i;
10662 MonoClass *eclass, *arg_eclass;
10664 if (!arg) {
10665 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10666 break;
10668 len = mono_array_length ((MonoArray*)arg);
10669 *p++ = len & 0xff;
10670 *p++ = (len >> 8) & 0xff;
10671 *p++ = (len >> 16) & 0xff;
10672 *p++ = (len >> 24) & 0xff;
10673 *retp = p;
10674 *retbuffer = buffer;
10675 eclass = type->data.klass;
10676 arg_eclass = mono_object_class (arg)->element_class;
10678 if (!eclass) {
10679 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10680 eclass = mono_defaults.object_class;
10682 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10683 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10684 int elsize = mono_class_array_element_size (arg_eclass);
10685 for (i = 0; i < len; ++i) {
10686 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10687 elptr += elsize;
10689 } else if (eclass->valuetype && arg_eclass->valuetype) {
10690 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10691 int elsize = mono_class_array_element_size (eclass);
10692 for (i = 0; i < len; ++i) {
10693 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10694 elptr += elsize;
10696 } else {
10697 for (i = 0; i < len; ++i) {
10698 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10701 break;
10703 case MONO_TYPE_OBJECT: {
10704 MonoClass *klass;
10705 char *str;
10706 guint32 slen;
10709 * The parameter type is 'object' but the type of the actual
10710 * argument is not. So we have to add type information to the blob
10711 * too. This is completely undocumented in the spec.
10714 if (arg == NULL) {
10715 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
10716 *p++ = 0xFF;
10717 break;
10720 klass = mono_object_class (arg);
10722 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10723 *p++ = 0x50;
10724 goto handle_type;
10725 } else if (klass->enumtype) {
10726 *p++ = 0x55;
10727 } else if (klass == mono_defaults.string_class) {
10728 simple_type = MONO_TYPE_STRING;
10729 *p++ = 0x0E;
10730 goto handle_enum;
10731 } else if (klass->rank == 1) {
10732 *p++ = 0x1D;
10733 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10734 /* See Partition II, Appendix B3 */
10735 *p++ = 0x51;
10736 else
10737 *p++ = klass->element_class->byval_arg.type;
10738 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10739 break;
10740 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10741 *p++ = simple_type = klass->byval_arg.type;
10742 goto handle_enum;
10743 } else {
10744 g_error ("unhandled type in custom attr");
10746 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10747 slen = strlen (str);
10748 if ((p-buffer) + 10 + slen >= *buflen) {
10749 char *newbuf;
10750 *buflen *= 2;
10751 *buflen += slen;
10752 newbuf = (char *)g_realloc (buffer, *buflen);
10753 p = newbuf + (p-buffer);
10754 buffer = newbuf;
10756 mono_metadata_encode_value (slen, p, &p);
10757 memcpy (p, str, slen);
10758 p += slen;
10759 g_free (str);
10760 simple_type = mono_class_enum_basetype (klass)->type;
10761 goto handle_enum;
10763 default:
10764 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10766 *retp = p;
10767 *retbuffer = buffer;
10770 static void
10771 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10773 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10774 char *str = type_get_qualified_name (type, NULL);
10775 int slen = strlen (str);
10777 *p++ = 0x55;
10779 * This seems to be optional...
10780 * *p++ = 0x80;
10782 mono_metadata_encode_value (slen, p, &p);
10783 memcpy (p, str, slen);
10784 p += slen;
10785 g_free (str);
10786 } else if (type->type == MONO_TYPE_OBJECT) {
10787 *p++ = 0x51;
10788 } else if (type->type == MONO_TYPE_CLASS) {
10789 /* it should be a type: encode_cattr_value () has the check */
10790 *p++ = 0x50;
10791 } else {
10792 mono_metadata_encode_value (type->type, p, &p);
10793 if (type->type == MONO_TYPE_SZARRAY)
10794 /* See the examples in Partition VI, Annex B */
10795 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10798 *retp = p;
10801 #ifndef DISABLE_REFLECTION_EMIT
10802 static void
10803 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10805 int len;
10806 /* Preallocate a large enough buffer */
10807 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10808 char *str = type_get_qualified_name (type, NULL);
10809 len = strlen (str);
10810 g_free (str);
10811 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10812 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10813 len = strlen (str);
10814 g_free (str);
10815 } else {
10816 len = 0;
10818 len += strlen (name);
10820 if ((p-buffer) + 20 + len >= *buflen) {
10821 char *newbuf;
10822 *buflen *= 2;
10823 *buflen += len;
10824 newbuf = (char *)g_realloc (buffer, *buflen);
10825 p = newbuf + (p-buffer);
10826 buffer = newbuf;
10829 encode_field_or_prop_type (type, p, &p);
10831 len = strlen (name);
10832 mono_metadata_encode_value (len, p, &p);
10833 memcpy (p, name, len);
10834 p += len;
10835 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10836 *retp = p;
10837 *retbuffer = buffer;
10841 * mono_reflection_get_custom_attrs_blob:
10842 * @ctor: custom attribute constructor
10843 * @ctorArgs: arguments o the constructor
10844 * @properties:
10845 * @propValues:
10846 * @fields:
10847 * @fieldValues:
10849 * Creates the blob of data that needs to be saved in the metadata and that represents
10850 * the custom attributed described by @ctor, @ctorArgs etc.
10851 * Returns: a Byte array representing the blob of data.
10853 MonoArray*
10854 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10856 MonoArray *result;
10857 MonoMethodSignature *sig;
10858 MonoObject *arg;
10859 char *buffer, *p;
10860 guint32 buflen, i;
10862 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10863 /* sig is freed later so allocate it in the heap */
10864 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10865 } else {
10866 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10869 g_assert (mono_array_length (ctorArgs) == sig->param_count);
10870 buflen = 256;
10871 p = buffer = (char *)g_malloc (buflen);
10872 /* write the prolog */
10873 *p++ = 1;
10874 *p++ = 0;
10875 for (i = 0; i < sig->param_count; ++i) {
10876 arg = mono_array_get (ctorArgs, MonoObject*, i);
10877 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10879 i = 0;
10880 if (properties)
10881 i += mono_array_length (properties);
10882 if (fields)
10883 i += mono_array_length (fields);
10884 *p++ = i & 0xff;
10885 *p++ = (i >> 8) & 0xff;
10886 if (properties) {
10887 MonoObject *prop;
10888 for (i = 0; i < mono_array_length (properties); ++i) {
10889 MonoType *ptype;
10890 char *pname;
10892 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10893 get_prop_name_and_type (prop, &pname, &ptype);
10894 *p++ = 0x54; /* PROPERTY signature */
10895 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10896 g_free (pname);
10900 if (fields) {
10901 MonoObject *field;
10902 for (i = 0; i < mono_array_length (fields); ++i) {
10903 MonoType *ftype;
10904 char *fname;
10906 field = (MonoObject *)mono_array_get (fields, gpointer, i);
10907 get_field_name_and_type (field, &fname, &ftype);
10908 *p++ = 0x53; /* FIELD signature */
10909 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10910 g_free (fname);
10914 g_assert (p - buffer <= buflen);
10915 buflen = p - buffer;
10916 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10917 p = mono_array_addr (result, char, 0);
10918 memcpy (p, buffer, buflen);
10919 g_free (buffer);
10920 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10921 g_free (sig);
10922 return result;
10926 * mono_reflection_setup_internal_class:
10927 * @tb: a TypeBuilder object
10929 * Creates a MonoClass that represents the TypeBuilder.
10930 * This is a trick that lets us simplify a lot of reflection code
10931 * (and will allow us to support Build and Run assemblies easier).
10933 void
10934 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10936 MonoError error;
10937 MonoClass *klass, *parent;
10939 RESOLVE_TYPE (tb->parent, &error);
10940 mono_error_raise_exception (&error); /* FIXME don't raise here */
10942 mono_loader_lock ();
10944 if (tb->parent) {
10945 /* check so we can compile corlib correctly */
10946 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10947 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10948 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10949 } else {
10950 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10952 } else {
10953 parent = NULL;
10956 /* the type has already being created: it means we just have to change the parent */
10957 if (tb->type.type) {
10958 klass = mono_class_from_mono_type (tb->type.type);
10959 klass->parent = NULL;
10960 /* fool mono_class_setup_parent */
10961 klass->supertypes = NULL;
10962 mono_class_setup_parent (klass, parent);
10963 mono_class_setup_mono_type (klass);
10964 mono_loader_unlock ();
10965 return;
10968 klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10970 klass->image = &tb->module->dynamic_image->image;
10972 klass->inited = 1; /* we lie to the runtime */
10973 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10974 if (!mono_error_ok (&error))
10975 goto failure;
10976 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10977 if (!mono_error_ok (&error))
10978 goto failure;
10979 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10980 klass->flags = tb->attrs;
10982 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10984 klass->element_class = klass;
10986 if (mono_class_get_ref_info (klass) == NULL) {
10988 mono_class_set_ref_info (klass, tb);
10990 /* Put into cache so mono_class_get_checked () will find it.
10991 Skip nested types as those should not be available on the global scope. */
10992 if (!tb->nesting_type)
10993 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10996 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10997 by performing a mono_class_get which does the full resolution.
10999 Working around this semantics would require us to write a lot of code for no clear advantage.
11001 mono_image_append_class_to_reflection_info_set (klass);
11002 } else {
11003 g_assert (mono_class_get_ref_info (klass) == tb);
11006 register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11008 if (parent != NULL) {
11009 mono_class_setup_parent (klass, parent);
11010 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11011 const char *old_n = klass->name;
11012 /* trick to get relative numbering right when compiling corlib */
11013 klass->name = "BuildingObject";
11014 mono_class_setup_parent (klass, mono_defaults.object_class);
11015 klass->name = old_n;
11018 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11019 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11020 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11021 klass->instance_size = sizeof (MonoObject);
11022 klass->size_inited = 1;
11023 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11026 mono_class_setup_mono_type (klass);
11028 mono_class_setup_supertypes (klass);
11031 * FIXME: handle interfaces.
11034 tb->type.type = &klass->byval_arg;
11036 if (tb->nesting_type) {
11037 g_assert (tb->nesting_type->type);
11038 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
11041 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11043 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11045 mono_loader_unlock ();
11046 return;
11048 failure:
11049 mono_loader_unlock ();
11050 mono_error_raise_exception (&error);
11054 * mono_reflection_setup_generic_class:
11055 * @tb: a TypeBuilder object
11057 * Setup the generic class before adding the first generic parameter.
11059 void
11060 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11065 * mono_reflection_create_generic_class:
11066 * @tb: a TypeBuilder object
11068 * Creates the generic class after all generic parameters have been added.
11070 void
11071 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11073 MonoClass *klass;
11074 int count, i;
11076 klass = mono_class_from_mono_type (tb->type.type);
11078 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11080 if (klass->generic_container || (count == 0))
11081 return;
11083 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11085 klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11087 klass->generic_container->owner.klass = klass;
11088 klass->generic_container->type_argc = count;
11089 klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11091 klass->is_generic = 1;
11093 for (i = 0; i < count; i++) {
11094 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11095 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
11096 klass->generic_container->type_params [i] = *param;
11097 /*Make sure we are a diferent type instance */
11098 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11099 klass->generic_container->type_params [i].info.pklass = NULL;
11100 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11102 g_assert (klass->generic_container->type_params [i].param.owner);
11105 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11109 * mono_reflection_create_internal_class:
11110 * @tb: a TypeBuilder object
11112 * Actually create the MonoClass that is associated with the TypeBuilder.
11114 void
11115 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11117 MonoClass *klass;
11119 klass = mono_class_from_mono_type (tb->type.type);
11121 mono_loader_lock ();
11122 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11123 MonoReflectionFieldBuilder *fb;
11124 MonoClass *ec;
11125 MonoType *enum_basetype;
11127 g_assert (tb->fields != NULL);
11128 g_assert (mono_array_length (tb->fields) >= 1);
11130 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11132 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
11133 mono_loader_unlock ();
11134 return;
11137 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11138 klass->element_class = mono_class_from_mono_type (enum_basetype);
11139 if (!klass->element_class)
11140 klass->element_class = mono_class_from_mono_type (enum_basetype);
11143 * get the element_class from the current corlib.
11145 ec = default_class_from_mono_type (enum_basetype);
11146 klass->instance_size = ec->instance_size;
11147 klass->size_inited = 1;
11149 * this is almost safe to do with enums and it's needed to be able
11150 * to create objects of the enum type (for use in SetConstant).
11152 /* FIXME: Does this mean enums can't have method overrides ? */
11153 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11155 mono_loader_unlock ();
11158 static MonoMarshalSpec*
11159 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11160 MonoReflectionMarshal *minfo)
11162 MonoMarshalSpec *res;
11164 res = image_g_new0 (image, MonoMarshalSpec, 1);
11165 res->native = (MonoMarshalNative)minfo->type;
11167 switch (minfo->type) {
11168 case MONO_NATIVE_LPARRAY:
11169 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11170 if (minfo->has_size) {
11171 res->data.array_data.param_num = minfo->param_num;
11172 res->data.array_data.num_elem = minfo->count;
11173 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11175 else {
11176 res->data.array_data.param_num = -1;
11177 res->data.array_data.num_elem = -1;
11178 res->data.array_data.elem_mult = -1;
11180 break;
11182 case MONO_NATIVE_BYVALTSTR:
11183 case MONO_NATIVE_BYVALARRAY:
11184 res->data.array_data.num_elem = minfo->count;
11185 break;
11187 case MONO_NATIVE_CUSTOM:
11188 if (minfo->marshaltyperef)
11189 res->data.custom_data.custom_name =
11190 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
11191 if (minfo->mcookie)
11192 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11193 break;
11195 default:
11196 break;
11199 return res;
11201 #endif /* !DISABLE_REFLECTION_EMIT */
11203 MonoReflectionMarshalAsAttribute*
11204 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11205 MonoMarshalSpec *spec, MonoError *error)
11207 MonoReflectionType *rt;
11208 MonoReflectionMarshalAsAttribute *minfo;
11209 MonoType *mtype;
11211 mono_error_init (error);
11213 minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11214 if (!minfo)
11215 return NULL;
11216 minfo->utype = spec->native;
11218 switch (minfo->utype) {
11219 case MONO_NATIVE_LPARRAY:
11220 minfo->array_subtype = spec->data.array_data.elem_type;
11221 minfo->size_const = spec->data.array_data.num_elem;
11222 if (spec->data.array_data.param_num != -1)
11223 minfo->size_param_index = spec->data.array_data.param_num;
11224 break;
11226 case MONO_NATIVE_BYVALTSTR:
11227 case MONO_NATIVE_BYVALARRAY:
11228 minfo->size_const = spec->data.array_data.num_elem;
11229 break;
11231 case MONO_NATIVE_CUSTOM:
11232 if (spec->data.custom_data.custom_name) {
11233 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11234 if (mtype) {
11235 rt = mono_type_get_object_checked (domain, mtype, error);
11236 if (!rt)
11237 return NULL;
11239 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11242 MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11244 if (spec->data.custom_data.cookie)
11245 MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11246 break;
11248 default:
11249 break;
11252 return minfo;
11255 #ifndef DISABLE_REFLECTION_EMIT
11256 static MonoMethod*
11257 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11258 ReflectionMethodBuilder *rmb,
11259 MonoMethodSignature *sig)
11261 MonoError error;
11262 MonoMethod *m;
11263 MonoMethodWrapper *wrapperm;
11264 MonoMarshalSpec **specs;
11265 MonoReflectionMethodAux *method_aux;
11266 MonoImage *image;
11267 gboolean dynamic;
11268 int i;
11270 mono_error_init (&error);
11272 * Methods created using a MethodBuilder should have their memory allocated
11273 * inside the image mempool, while dynamic methods should have their memory
11274 * malloc'd.
11276 dynamic = rmb->refs != NULL;
11277 image = dynamic ? NULL : klass->image;
11279 if (!dynamic)
11280 g_assert (!klass->generic_class);
11282 mono_loader_lock ();
11284 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11285 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11286 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11287 else
11288 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11290 wrapperm = (MonoMethodWrapper*)m;
11292 m->dynamic = dynamic;
11293 m->slot = -1;
11294 m->flags = rmb->attrs;
11295 m->iflags = rmb->iattrs;
11296 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11297 m->klass = klass;
11298 m->signature = sig;
11299 m->sre_method = TRUE;
11300 m->skip_visibility = rmb->skip_visibility;
11301 if (rmb->table_idx)
11302 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11304 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11305 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11306 m->string_ctor = 1;
11308 m->signature->pinvoke = 1;
11309 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11310 m->signature->pinvoke = 1;
11312 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11314 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11315 g_assert (mono_error_ok (&error));
11316 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11317 g_assert (mono_error_ok (&error));
11319 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11321 if (image_is_dynamic (klass->image))
11322 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11324 mono_loader_unlock ();
11326 return m;
11327 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11328 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11329 MonoMethodHeader *header;
11330 guint32 code_size;
11331 gint32 max_stack, i;
11332 gint32 num_locals = 0;
11333 gint32 num_clauses = 0;
11334 guint8 *code;
11336 if (rmb->ilgen) {
11337 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11338 code_size = rmb->ilgen->code_len;
11339 max_stack = rmb->ilgen->max_stack;
11340 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11341 if (rmb->ilgen->ex_handlers)
11342 num_clauses = method_count_clauses (rmb->ilgen);
11343 } else {
11344 if (rmb->code) {
11345 code = mono_array_addr (rmb->code, guint8, 0);
11346 code_size = mono_array_length (rmb->code);
11347 /* we probably need to run a verifier on the code... */
11348 max_stack = 8;
11350 else {
11351 code = NULL;
11352 code_size = 0;
11353 max_stack = 8;
11357 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11358 header->code_size = code_size;
11359 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11360 memcpy ((char*)header->code, code, code_size);
11361 header->max_stack = max_stack;
11362 header->init_locals = rmb->init_locals;
11363 header->num_locals = num_locals;
11365 for (i = 0; i < num_locals; ++i) {
11366 MonoReflectionLocalBuilder *lb =
11367 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11369 header->locals [i] = image_g_new0 (image, MonoType, 1);
11370 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11373 header->num_clauses = num_clauses;
11374 if (num_clauses) {
11375 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11376 rmb->ilgen, num_clauses);
11379 wrapperm->header = header;
11382 if (rmb->generic_params) {
11383 int count = mono_array_length (rmb->generic_params);
11384 MonoGenericContainer *container = rmb->generic_container;
11386 g_assert (container);
11388 container->type_argc = count;
11389 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11390 container->owner.method = m;
11391 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11393 m->is_generic = TRUE;
11394 mono_method_set_generic_container (m, container);
11396 for (i = 0; i < count; i++) {
11397 MonoReflectionGenericParam *gp =
11398 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11399 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11400 container->type_params [i] = *param;
11404 * The method signature might have pointers to generic parameters that belong to other methods.
11405 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11406 * generic parameters.
11408 for (i = 0; i < m->signature->param_count; ++i) {
11409 MonoType *t = m->signature->params [i];
11410 if (t->type == MONO_TYPE_MVAR) {
11411 MonoGenericParam *gparam = t->data.generic_param;
11412 if (gparam->num < count) {
11413 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11414 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11420 if (klass->generic_container) {
11421 container->parent = klass->generic_container;
11422 container->context.class_inst = klass->generic_container->context.class_inst;
11424 container->context.method_inst = mono_get_shared_generic_inst (container);
11427 if (rmb->refs) {
11428 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11429 int i;
11430 void **data;
11432 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11434 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11435 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11436 for (i = 0; i < rmb->nrefs; ++i)
11437 data [i + 1] = rmb->refs [i];
11440 method_aux = NULL;
11442 /* Parameter info */
11443 if (rmb->pinfo) {
11444 if (!method_aux)
11445 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11446 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11447 for (i = 0; i <= m->signature->param_count; ++i) {
11448 MonoReflectionParamBuilder *pb;
11449 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11450 if ((i > 0) && (pb->attrs)) {
11451 /* Make a copy since it might point to a shared type structure */
11452 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11453 m->signature->params [i - 1]->attrs = pb->attrs;
11456 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11457 MonoDynamicImage *assembly;
11458 guint32 idx, len;
11459 MonoTypeEnum def_type;
11460 char *p;
11461 const char *p2;
11463 if (!method_aux->param_defaults) {
11464 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11465 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11467 assembly = (MonoDynamicImage*)klass->image;
11468 idx = encode_constant (assembly, pb->def_value, &def_type);
11469 /* Copy the data from the blob since it might get realloc-ed */
11470 p = assembly->blob.data + idx;
11471 len = mono_metadata_decode_blob_size (p, &p2);
11472 len += p2 - p;
11473 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11474 method_aux->param_default_types [i] = def_type;
11475 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11478 if (pb->name) {
11479 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11480 g_assert (mono_error_ok (&error));
11482 if (pb->cattrs) {
11483 if (!method_aux->param_cattr)
11484 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11485 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11491 /* Parameter marshalling */
11492 specs = NULL;
11493 if (rmb->pinfo)
11494 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11495 MonoReflectionParamBuilder *pb;
11496 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11497 if (pb->marshal_info) {
11498 if (specs == NULL)
11499 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11500 specs [pb->position] =
11501 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11505 if (specs != NULL) {
11506 if (!method_aux)
11507 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11508 method_aux->param_marshall = specs;
11511 if (image_is_dynamic (klass->image) && method_aux)
11512 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11514 mono_loader_unlock ();
11516 return m;
11519 static MonoMethod*
11520 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11522 ReflectionMethodBuilder rmb;
11523 MonoMethodSignature *sig;
11525 mono_loader_lock ();
11526 sig = ctor_builder_to_signature (klass->image, mb);
11527 mono_loader_unlock ();
11529 if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11530 return NULL;
11532 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11533 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11535 /* If we are in a generic class, we might be called multiple times from inflate_method */
11536 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11537 /* ilgen is no longer needed */
11538 mb->ilgen = NULL;
11541 return mb->mhandle;
11544 static MonoMethod*
11545 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11547 ReflectionMethodBuilder rmb;
11548 MonoMethodSignature *sig;
11550 mono_error_init (error);
11552 mono_loader_lock ();
11553 sig = method_builder_to_signature (klass->image, mb);
11554 mono_loader_unlock ();
11556 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11557 return NULL;
11559 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11560 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11562 /* If we are in a generic class, we might be called multiple times from inflate_method */
11563 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11564 /* ilgen is no longer needed */
11565 mb->ilgen = NULL;
11567 return mb->mhandle;
11570 static MonoClassField*
11571 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11573 MonoClassField *field;
11574 MonoType *custom;
11575 MonoError error;
11577 field = g_new0 (MonoClassField, 1);
11579 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11580 g_assert (mono_error_ok (&error));
11581 if (fb->attrs || fb->modreq || fb->modopt) {
11582 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11583 field->type->attrs = fb->attrs;
11585 g_assert (image_is_dynamic (klass->image));
11586 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11587 g_free (field->type);
11588 field->type = mono_metadata_type_dup (klass->image, custom);
11589 g_free (custom);
11590 } else {
11591 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11593 if (fb->offset != -1)
11594 field->offset = fb->offset;
11595 field->parent = klass;
11596 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11598 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11600 return field;
11602 #endif
11604 MonoType*
11605 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11607 MonoClass *klass;
11608 MonoReflectionTypeBuilder *tb = NULL;
11609 gboolean is_dynamic = FALSE;
11610 MonoClass *geninst;
11612 mono_loader_lock ();
11614 if (is_sre_type_builder (mono_object_class (type))) {
11615 tb = (MonoReflectionTypeBuilder *) type;
11617 is_dynamic = TRUE;
11618 } else if (is_sre_generic_instance (mono_object_class (type))) {
11619 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11620 MonoReflectionType *gtd = rgi->generic_type;
11622 if (is_sre_type_builder (mono_object_class (gtd))) {
11623 tb = (MonoReflectionTypeBuilder *)gtd;
11624 is_dynamic = TRUE;
11628 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11629 if (tb && tb->generic_container)
11630 mono_reflection_create_generic_class (tb);
11632 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11633 if (!klass->generic_container) {
11634 mono_loader_unlock ();
11635 return NULL;
11638 if (klass->wastypebuilder) {
11639 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11641 is_dynamic = TRUE;
11644 mono_loader_unlock ();
11646 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11648 return &geninst->byval_arg;
11651 MonoClass*
11652 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11654 MonoGenericClass *gclass;
11655 MonoGenericInst *inst;
11657 g_assert (klass->generic_container);
11659 inst = mono_metadata_get_generic_inst (type_argc, types);
11660 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11662 return mono_generic_class_get_class (gclass);
11665 MonoReflectionMethod*
11666 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11668 MonoError error;
11669 MonoClass *klass;
11670 MonoMethod *method, *inflated;
11671 MonoMethodInflated *imethod;
11672 MonoGenericContext tmp_context;
11673 MonoGenericInst *ginst;
11674 MonoType **type_argv;
11675 int count, i;
11677 /*FIXME but this no longer should happen*/
11678 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11679 #ifndef DISABLE_REFLECTION_EMIT
11680 MonoReflectionMethodBuilder *mb = NULL;
11681 MonoReflectionTypeBuilder *tb;
11682 MonoClass *klass;
11684 mb = (MonoReflectionMethodBuilder *) rmethod;
11685 tb = (MonoReflectionTypeBuilder *) mb->type;
11686 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11688 method = methodbuilder_to_mono_method (klass, mb, &error);
11689 if (!method)
11690 mono_error_raise_exception (&error); /* FIXME don't raise here */
11691 #else
11692 g_assert_not_reached ();
11693 method = NULL;
11694 #endif
11695 } else {
11696 method = rmethod->method;
11699 klass = method->klass;
11701 if (method->is_inflated)
11702 method = ((MonoMethodInflated *) method)->declaring;
11704 count = mono_method_signature (method)->generic_param_count;
11705 if (count != mono_array_length (types))
11706 return NULL;
11708 type_argv = g_new0 (MonoType *, count);
11709 for (i = 0; i < count; i++) {
11710 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11711 type_argv [i] = mono_reflection_type_get_handle (garg);
11713 ginst = mono_metadata_get_generic_inst (count, type_argv);
11714 g_free (type_argv);
11716 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11717 tmp_context.method_inst = ginst;
11719 inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11720 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11721 imethod = (MonoMethodInflated *) inflated;
11723 /*FIXME but I think this is no longer necessary*/
11724 if (image_is_dynamic (method->klass->image)) {
11725 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11727 * This table maps metadata structures representing inflated methods/fields
11728 * to the reflection objects representing their generic definitions.
11730 mono_image_lock ((MonoImage*)image);
11731 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11732 mono_image_unlock ((MonoImage*)image);
11735 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11736 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11738 MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11739 mono_error_raise_exception (&error); /* FIXME don't raise here */
11740 return ret;
11743 #ifndef DISABLE_REFLECTION_EMIT
11745 static MonoMethod *
11746 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11748 MonoMethodInflated *imethod;
11749 MonoGenericContext *context;
11750 int i;
11753 * With generic code sharing the klass might not be inflated.
11754 * This can happen because classes inflated with their own
11755 * type arguments are "normalized" to the uninflated class.
11757 if (!klass->generic_class)
11758 return method;
11760 context = mono_class_get_context (klass);
11762 if (klass->method.count && klass->methods) {
11763 /* Find the already created inflated method */
11764 for (i = 0; i < klass->method.count; ++i) {
11765 g_assert (klass->methods [i]->is_inflated);
11766 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11767 break;
11769 g_assert (i < klass->method.count);
11770 imethod = (MonoMethodInflated*)klass->methods [i];
11771 } else {
11772 MonoError error;
11773 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11774 mono_error_assert_ok (&error);
11777 if (method->is_generic && image_is_dynamic (method->klass->image)) {
11778 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11780 mono_image_lock ((MonoImage*)image);
11781 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11782 mono_image_unlock ((MonoImage*)image);
11784 return (MonoMethod *) imethod;
11787 static MonoMethod *
11788 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
11790 MonoMethod *method;
11791 MonoClass *gklass;
11793 mono_error_init (error);
11795 MonoClass *type_class = mono_object_class (type);
11797 if (is_sre_generic_instance (type_class)) {
11798 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11799 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11800 } else if (is_sre_type_builder (type_class)) {
11801 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11802 } else if (type->type) {
11803 gklass = mono_class_from_mono_type (type->type);
11804 gklass = mono_class_get_generic_type_definition (gklass);
11805 } else {
11806 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11809 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11810 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11811 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11812 else {
11813 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
11814 if (!method)
11815 return NULL;
11817 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
11818 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
11819 if (!method)
11820 return NULL;
11821 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11822 method = ((MonoReflectionMethod *) obj)->method;
11823 else {
11824 method = NULL; /* prevent compiler warning */
11825 g_error ("can't handle type %s", obj->vtable->klass->name);
11828 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11831 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11832 void
11833 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11835 MonoGenericClass *gclass;
11836 MonoDynamicGenericClass *dgclass;
11837 MonoClass *klass, *gklass;
11838 MonoType *gtype;
11839 int i;
11841 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11842 klass = mono_class_from_mono_type (gtype);
11843 g_assert (gtype->type == MONO_TYPE_GENERICINST);
11844 gclass = gtype->data.generic_class;
11846 if (!gclass->is_dynamic)
11847 return;
11849 dgclass = (MonoDynamicGenericClass *) gclass;
11851 if (dgclass->initialized)
11852 return;
11854 gklass = gclass->container_class;
11855 mono_class_init (gklass);
11857 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11859 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11860 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11861 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11863 for (i = 0; i < dgclass->count_fields; i++) {
11864 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11865 MonoClassField *field, *inflated_field = NULL;
11867 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11868 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11869 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11870 field = ((MonoReflectionField *) obj)->field;
11871 else {
11872 field = NULL; /* prevent compiler warning */
11873 g_assert_not_reached ();
11876 dgclass->fields [i] = *field;
11877 dgclass->fields [i].parent = klass;
11878 dgclass->fields [i].type = mono_class_inflate_generic_type (
11879 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11880 dgclass->field_generic_types [i] = field->type;
11881 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11882 dgclass->field_objects [i] = obj;
11884 if (inflated_field) {
11885 g_free (inflated_field);
11886 } else {
11887 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11891 dgclass->initialized = TRUE;
11894 void
11895 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11897 MonoDynamicGenericClass *dgclass;
11898 int i;
11900 g_assert (gclass->is_dynamic);
11902 dgclass = (MonoDynamicGenericClass *)gclass;
11904 for (i = 0; i < dgclass->count_fields; ++i) {
11905 MonoClassField *field = dgclass->fields + i;
11906 mono_metadata_free_type (field->type);
11907 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11911 static void
11912 fix_partial_generic_class (MonoClass *klass)
11914 MonoClass *gklass = klass->generic_class->container_class;
11915 MonoDynamicGenericClass *dgclass;
11916 int i;
11918 if (klass->wastypebuilder)
11919 return;
11921 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
11922 if (klass->parent != gklass->parent) {
11923 MonoError error;
11924 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11925 if (mono_error_ok (&error)) {
11926 MonoClass *parent = mono_class_from_mono_type (parent_type);
11927 mono_metadata_free_type (parent_type);
11928 if (parent != klass->parent) {
11929 /*fool mono_class_setup_parent*/
11930 klass->supertypes = NULL;
11931 mono_class_setup_parent (klass, parent);
11933 } else {
11934 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11935 mono_error_cleanup (&error);
11936 if (gklass->wastypebuilder)
11937 klass->wastypebuilder = TRUE;
11938 return;
11942 if (!dgclass->initialized)
11943 return;
11945 if (klass->method.count != gklass->method.count) {
11946 klass->method.count = gklass->method.count;
11947 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11949 for (i = 0; i < klass->method.count; i++) {
11950 MonoError error;
11951 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11952 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11953 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11957 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11958 klass->interface_count = gklass->interface_count;
11959 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11960 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11962 for (i = 0; i < gklass->interface_count; ++i) {
11963 MonoError error;
11964 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11965 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11966 mono_metadata_free_type (iface_type);
11968 ensure_runtime_vtable (klass->interfaces [i], &error);
11969 mono_error_raise_exception (&error); /* FIXME don't raise here */
11971 klass->interfaces_inited = 1;
11974 if (klass->field.count != gklass->field.count) {
11975 klass->field.count = gklass->field.count;
11976 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11978 for (i = 0; i < klass->field.count; i++) {
11979 klass->fields [i] = gklass->fields [i];
11980 klass->fields [i].parent = klass;
11981 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11985 /*We can only finish with this klass once it's parent has as well*/
11986 if (gklass->wastypebuilder)
11987 klass->wastypebuilder = TRUE;
11988 return;
11992 * ensure_generic_class_runtime_vtable:
11993 * @klass a generic class
11994 * @error set on error
11996 * Ensures that the generic container of @klass has a vtable and
11997 * returns TRUE on success. On error returns FALSE and sets @error.
11999 static gboolean
12000 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12002 MonoClass *gklass = klass->generic_class->container_class;
12004 mono_error_init (error);
12006 if (!ensure_runtime_vtable (gklass, error))
12007 return FALSE;
12009 fix_partial_generic_class (klass);
12011 return TRUE;
12015 * ensure_runtime_vtable:
12016 * @klass the class
12017 * @error set on error
12019 * Ensures that @klass has a vtable and returns TRUE on success. On
12020 * error returns FALSE and sets @error.
12022 static gboolean
12023 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12025 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12026 int i, num, j;
12028 mono_error_init (error);
12030 if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12031 return TRUE;
12032 if (klass->parent)
12033 if (!ensure_runtime_vtable (klass->parent, error))
12034 return FALSE;
12036 if (tb) {
12037 num = tb->ctors? mono_array_length (tb->ctors): 0;
12038 num += tb->num_methods;
12039 klass->method.count = num;
12040 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12041 num = tb->ctors? mono_array_length (tb->ctors): 0;
12042 for (i = 0; i < num; ++i) {
12043 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12044 if (!ctor)
12045 return FALSE;
12046 klass->methods [i] = ctor;
12048 num = tb->num_methods;
12049 j = i;
12050 for (i = 0; i < num; ++i) {
12051 MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12052 if (!meth)
12053 return FALSE;
12054 klass->methods [j++] = meth;
12057 if (tb->interfaces) {
12058 klass->interface_count = mono_array_length (tb->interfaces);
12059 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12060 for (i = 0; i < klass->interface_count; ++i) {
12061 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
12062 klass->interfaces [i] = mono_class_from_mono_type (iface);
12063 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12064 return FALSE;
12066 klass->interfaces_inited = 1;
12068 } else if (klass->generic_class){
12069 if (!ensure_generic_class_runtime_vtable (klass, error))
12070 return FALSE;
12073 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12074 int slot_num = 0;
12075 for (i = 0; i < klass->method.count; ++i) {
12076 MonoMethod *im = klass->methods [i];
12077 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12078 im->slot = slot_num++;
12081 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12082 mono_class_setup_interface_offsets (klass);
12083 mono_class_setup_interface_id (klass);
12087 * The generic vtable is needed even if image->run is not set since some
12088 * runtime code like ves_icall_Type_GetMethodsByName depends on
12089 * method->slot being defined.
12093 * tb->methods could not be freed since it is used for determining
12094 * overrides during dynamic vtable construction.
12097 return TRUE;
12100 static MonoMethod*
12101 mono_reflection_method_get_handle (MonoObject *method)
12103 MonoError error;
12104 MonoClass *klass = mono_object_class (method);
12105 if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12106 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12107 return sr_method->method;
12109 if (is_sre_method_builder (klass)) {
12110 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12111 return mb->mhandle;
12113 if (is_sre_method_on_tb_inst (klass)) {
12114 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12115 MonoMethod *result;
12116 /*FIXME move this to a proper method and unify with resolve_object*/
12117 if (m->method_args) {
12118 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12119 mono_error_raise_exception (&error); /* FIXME don't raise here */
12120 } else {
12121 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
12122 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12123 MonoMethod *mono_method;
12125 if (is_sre_method_builder (mono_object_class (m->mb)))
12126 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12127 else if (is_sr_mono_method (mono_object_class (m->mb)))
12128 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12129 else
12130 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)));
12132 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12134 return result;
12137 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12138 return NULL;
12141 void
12142 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12144 MonoReflectionTypeBuilder *tb;
12145 int i, j, onum;
12146 MonoReflectionMethod *m;
12148 *overrides = NULL;
12149 *num_overrides = 0;
12151 g_assert (image_is_dynamic (klass->image));
12153 if (!mono_class_get_ref_info (klass))
12154 return;
12156 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12158 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12160 onum = 0;
12161 if (tb->methods) {
12162 for (i = 0; i < tb->num_methods; ++i) {
12163 MonoReflectionMethodBuilder *mb =
12164 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12165 if (mb->override_methods)
12166 onum += mono_array_length (mb->override_methods);
12170 if (onum) {
12171 *overrides = g_new0 (MonoMethod*, onum * 2);
12173 onum = 0;
12174 for (i = 0; i < tb->num_methods; ++i) {
12175 MonoReflectionMethodBuilder *mb =
12176 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12177 if (mb->override_methods) {
12178 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12179 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12181 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12182 (*overrides) [onum * 2 + 1] = mb->mhandle;
12184 g_assert (mb->mhandle);
12186 onum ++;
12192 *num_overrides = onum;
12195 static void
12196 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12198 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12199 MonoReflectionFieldBuilder *fb;
12200 MonoClassField *field;
12201 MonoImage *image = klass->image;
12202 const char *p, *p2;
12203 int i;
12204 guint32 len, idx, real_size = 0;
12206 klass->field.count = tb->num_fields;
12207 klass->field.first = 0;
12209 mono_error_init (error);
12211 if (tb->class_size) {
12212 if ((tb->packing_size & 0xffffff00) != 0) {
12213 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12214 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12215 return;
12217 klass->packing_size = tb->packing_size;
12218 real_size = klass->instance_size + tb->class_size;
12221 if (!klass->field.count) {
12222 klass->instance_size = MAX (klass->instance_size, real_size);
12223 return;
12226 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12227 mono_class_alloc_ext (klass);
12228 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12230 This is, guess what, a hack.
12231 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12232 On the static path no field class is resolved, only types are built. This is the right thing to do
12233 but we suck.
12234 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12236 klass->size_inited = 1;
12238 for (i = 0; i < klass->field.count; ++i) {
12239 MonoArray *rva_data;
12240 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12241 field = &klass->fields [i];
12242 field->name = mono_string_to_utf8_image (image, fb->name, error);
12243 if (!mono_error_ok (error))
12244 return;
12245 if (fb->attrs) {
12246 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
12247 field->type->attrs = fb->attrs;
12248 } else {
12249 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
12252 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12253 char *base = mono_array_addr (rva_data, char, 0);
12254 size_t size = mono_array_length (rva_data);
12255 char *data = (char *)mono_image_alloc (klass->image, size);
12256 memcpy (data, base, size);
12257 klass->ext->field_def_values [i].data = data;
12259 if (fb->offset != -1)
12260 field->offset = fb->offset;
12261 field->parent = klass;
12262 fb->handle = field;
12263 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12265 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12266 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12268 if (fb->def_value) {
12269 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12270 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12271 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12272 /* Copy the data from the blob since it might get realloc-ed */
12273 p = assembly->blob.data + idx;
12274 len = mono_metadata_decode_blob_size (p, &p2);
12275 len += p2 - p;
12276 klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12277 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12281 klass->instance_size = MAX (klass->instance_size, real_size);
12282 mono_class_layout_fields (klass);
12285 static void
12286 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12288 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12289 MonoReflectionPropertyBuilder *pb;
12290 MonoImage *image = klass->image;
12291 MonoProperty *properties;
12292 int i;
12294 mono_error_init (error);
12296 if (!klass->ext)
12297 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12299 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12300 klass->ext->property.first = 0;
12302 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12303 klass->ext->properties = properties;
12304 for (i = 0; i < klass->ext->property.count; ++i) {
12305 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12306 properties [i].parent = klass;
12307 properties [i].attrs = pb->attrs;
12308 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12309 if (!mono_error_ok (error))
12310 return;
12311 if (pb->get_method)
12312 properties [i].get = pb->get_method->mhandle;
12313 if (pb->set_method)
12314 properties [i].set = pb->set_method->mhandle;
12316 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12317 if (pb->def_value) {
12318 guint32 len, idx;
12319 const char *p, *p2;
12320 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12321 if (!klass->ext->prop_def_values)
12322 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12323 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12324 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12325 /* Copy the data from the blob since it might get realloc-ed */
12326 p = assembly->blob.data + idx;
12327 len = mono_metadata_decode_blob_size (p, &p2);
12328 len += p2 - p;
12329 klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12330 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12335 MonoReflectionEvent *
12336 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12338 MonoError error;
12339 MonoEvent *event = g_new0 (MonoEvent, 1);
12340 MonoClass *klass;
12342 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12344 event->parent = klass;
12345 event->attrs = eb->attrs;
12346 event->name = mono_string_to_utf8 (eb->name);
12347 if (eb->add_method)
12348 event->add = eb->add_method->mhandle;
12349 if (eb->remove_method)
12350 event->remove = eb->remove_method->mhandle;
12351 if (eb->raise_method)
12352 event->raise = eb->raise_method->mhandle;
12354 #ifndef MONO_SMALL_CONFIG
12355 if (eb->other_methods) {
12356 int j;
12357 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12358 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12359 MonoReflectionMethodBuilder *mb =
12360 mono_array_get (eb->other_methods,
12361 MonoReflectionMethodBuilder*, j);
12362 event->other [j] = mb->mhandle;
12365 #endif
12367 MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12368 mono_error_raise_exception (&error); /* FIXME don't raise here */
12369 return ev_obj;
12372 static void
12373 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12375 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12376 MonoReflectionEventBuilder *eb;
12377 MonoImage *image = klass->image;
12378 MonoEvent *events;
12379 int i;
12381 mono_error_init (error);
12383 if (!klass->ext)
12384 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12386 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12387 klass->ext->event.first = 0;
12389 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12390 klass->ext->events = events;
12391 for (i = 0; i < klass->ext->event.count; ++i) {
12392 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12393 events [i].parent = klass;
12394 events [i].attrs = eb->attrs;
12395 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12396 if (!mono_error_ok (error))
12397 return;
12398 if (eb->add_method)
12399 events [i].add = eb->add_method->mhandle;
12400 if (eb->remove_method)
12401 events [i].remove = eb->remove_method->mhandle;
12402 if (eb->raise_method)
12403 events [i].raise = eb->raise_method->mhandle;
12405 #ifndef MONO_SMALL_CONFIG
12406 if (eb->other_methods) {
12407 int j;
12408 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12409 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12410 MonoReflectionMethodBuilder *mb =
12411 mono_array_get (eb->other_methods,
12412 MonoReflectionMethodBuilder*, j);
12413 events [i].other [j] = mb->mhandle;
12416 #endif
12417 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12421 static gboolean
12422 remove_instantiations_of_and_ensure_contents (gpointer key,
12423 gpointer value,
12424 gpointer user_data)
12426 MonoType *type = (MonoType*)key;
12427 MonoClass *klass = (MonoClass*)user_data;
12429 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12430 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12431 return TRUE;
12432 } else
12433 return FALSE;
12436 static void
12437 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12439 mono_error_init (error);
12440 int i;
12442 if (!arr)
12443 return;
12445 for (i = 0; i < mono_array_length (arr); ++i) {
12446 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12447 if (!mono_error_ok (error))
12448 break;
12452 MonoReflectionType*
12453 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12455 MonoError error;
12456 MonoClass *klass;
12457 MonoDomain* domain;
12458 MonoReflectionType* res;
12459 int i, j;
12461 domain = mono_object_domain (tb);
12462 klass = mono_class_from_mono_type (tb->type.type);
12465 * Check for user defined Type subclasses.
12467 RESOLVE_TYPE (tb->parent, &error);
12468 mono_error_raise_exception (&error); /* FIXME don't raise here */
12469 check_array_for_usertypes (tb->interfaces, &error);
12470 mono_error_raise_exception (&error); /*FIXME don't raise here */
12471 if (tb->fields) {
12472 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12473 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12474 if (fb) {
12475 RESOLVE_TYPE (fb->type, &error);
12476 mono_error_raise_exception (&error); /* FIXME don't raise here */
12477 check_array_for_usertypes (fb->modreq, &error);
12478 mono_error_raise_exception (&error); /*FIXME don't raise here */
12479 check_array_for_usertypes (fb->modopt, &error);
12480 mono_error_raise_exception (&error); /*FIXME don't raise here */
12481 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12482 RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12483 mono_error_raise_exception (&error); /* FIXME don't raise here */
12488 if (tb->methods) {
12489 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12490 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12491 if (mb) {
12492 RESOLVE_TYPE (mb->rtype, &error);
12493 mono_error_raise_exception (&error); /* FIXME don't raise here */
12494 check_array_for_usertypes (mb->return_modreq, &error);
12495 mono_error_raise_exception (&error); /*FIXME don't raise here */
12496 check_array_for_usertypes (mb->return_modopt, &error);
12497 mono_error_raise_exception (&error); /*FIXME don't raise here */
12498 check_array_for_usertypes (mb->parameters, &error);
12499 mono_error_raise_exception (&error); /*FIXME don't raise here */
12500 if (mb->param_modreq)
12501 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12502 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12503 mono_error_raise_exception (&error); /*FIXME don't raise here */
12505 if (mb->param_modopt)
12506 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12507 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12508 mono_error_raise_exception (&error); /*FIXME don't raise here */
12513 if (tb->ctors) {
12514 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12515 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12516 if (mb) {
12517 check_array_for_usertypes (mb->parameters, &error);
12518 mono_error_raise_exception (&error); /*FIXME don't raise here */
12519 if (mb->param_modreq)
12520 for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12521 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12522 mono_error_raise_exception (&error); /*FIXME don't raise here */
12524 if (mb->param_modopt)
12525 for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12526 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12527 mono_error_raise_exception (&error); /*FIXME don't raise here */
12533 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12536 * we need to lock the domain because the lock will be taken inside
12537 * So, we need to keep the locking order correct.
12539 mono_loader_lock ();
12540 mono_domain_lock (domain);
12541 if (klass->wastypebuilder) {
12542 mono_domain_unlock (domain);
12543 mono_loader_unlock ();
12545 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12546 mono_error_raise_exception (&error); /* FIXME don't raise here */
12548 return res;
12551 * Fields to set in klass:
12552 * the various flags: delegate/unicode/contextbound etc.
12554 klass->flags = tb->attrs;
12555 klass->has_cctor = 1;
12556 klass->has_finalize = 1;
12557 klass->has_finalize_inited = 1;
12559 mono_class_setup_parent (klass, klass->parent);
12560 /* fool mono_class_setup_supertypes */
12561 klass->supertypes = NULL;
12562 mono_class_setup_supertypes (klass);
12563 mono_class_setup_mono_type (klass);
12565 #if 0
12566 if (!((MonoDynamicImage*)klass->image)->run) {
12567 if (klass->generic_container) {
12568 /* FIXME: The code below can't handle generic classes */
12569 klass->wastypebuilder = TRUE;
12570 mono_loader_unlock ();
12571 mono_domain_unlock (domain);
12573 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12574 mono_error_raise_exception (&error); /* FIXME don't raise here */
12576 return res;
12579 #endif
12581 /* enums are done right away */
12582 if (!klass->enumtype)
12583 if (!ensure_runtime_vtable (klass, &error))
12584 goto failure;
12586 if (tb->subtypes) {
12587 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12588 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12589 mono_class_alloc_ext (klass);
12590 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
12594 klass->nested_classes_inited = TRUE;
12596 /* fields and object layout */
12597 if (klass->parent) {
12598 if (!klass->parent->size_inited)
12599 mono_class_init (klass->parent);
12600 klass->instance_size = klass->parent->instance_size;
12601 klass->sizes.class_size = 0;
12602 klass->min_align = klass->parent->min_align;
12603 /* if the type has no fields we won't call the field_setup
12604 * routine which sets up klass->has_references.
12606 klass->has_references |= klass->parent->has_references;
12607 } else {
12608 klass->instance_size = sizeof (MonoObject);
12609 klass->min_align = 1;
12612 /* FIXME: handle packing_size and instance_size */
12613 typebuilder_setup_fields (klass, &error);
12614 if (!mono_error_ok (&error))
12615 goto failure;
12616 typebuilder_setup_properties (klass, &error);
12617 if (!mono_error_ok (&error))
12618 goto failure;
12620 typebuilder_setup_events (klass, &error);
12621 if (!mono_error_ok (&error))
12622 goto failure;
12624 klass->wastypebuilder = TRUE;
12627 * If we are a generic TypeBuilder, there might be instantiations in the type cache
12628 * which have type System.Reflection.MonoGenericClass, but after the type is created,
12629 * we want to return normal System.MonoType objects, so clear these out from the cache.
12631 * Together with this we must ensure the contents of all instances to match the created type.
12633 if (domain->type_hash && klass->generic_container)
12634 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12636 mono_domain_unlock (domain);
12637 mono_loader_unlock ();
12639 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12640 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12641 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12644 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12645 mono_error_raise_exception (&error); /* FIXME don't raise here */
12647 g_assert (res != (MonoReflectionType*)tb);
12649 return res;
12651 failure:
12652 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12653 klass->wastypebuilder = TRUE;
12654 mono_domain_unlock (domain);
12655 mono_loader_unlock ();
12656 mono_error_raise_exception (&error);
12657 return NULL;
12660 void
12661 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12663 MonoGenericParamFull *param;
12664 MonoImage *image;
12665 MonoClass *pklass;
12666 MonoError error;
12668 image = &gparam->tbuilder->module->dynamic_image->image;
12670 param = mono_image_new0 (image, MonoGenericParamFull, 1);
12672 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12673 g_assert (mono_error_ok (&error));
12674 param->param.num = gparam->index;
12676 if (gparam->mbuilder) {
12677 if (!gparam->mbuilder->generic_container) {
12678 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12679 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12680 gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12681 gparam->mbuilder->generic_container->is_method = TRUE;
12683 * Cannot set owner.method, since the MonoMethod is not created yet.
12684 * Set the image field instead, so type_in_image () works.
12686 gparam->mbuilder->generic_container->is_anonymous = TRUE;
12687 gparam->mbuilder->generic_container->owner.image = klass->image;
12689 param->param.owner = gparam->mbuilder->generic_container;
12690 } else if (gparam->tbuilder) {
12691 if (!gparam->tbuilder->generic_container) {
12692 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12693 gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12694 gparam->tbuilder->generic_container->owner.klass = klass;
12696 param->param.owner = gparam->tbuilder->generic_container;
12699 pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12701 gparam->type.type = &pklass->byval_arg;
12703 mono_class_set_ref_info (pklass, gparam);
12704 mono_image_append_class_to_reflection_info_set (pklass);
12707 MonoArray *
12708 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12710 MonoError error;
12711 MonoReflectionModuleBuilder *module = sig->module;
12712 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12713 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12714 guint32 buflen, i;
12715 MonoArray *result;
12716 SigBuffer buf;
12718 check_array_for_usertypes (sig->arguments, &error);
12719 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12721 sigbuffer_init (&buf, 32);
12723 sigbuffer_add_value (&buf, 0x07);
12724 sigbuffer_add_value (&buf, na);
12725 if (assembly != NULL){
12726 for (i = 0; i < na; ++i) {
12727 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12728 encode_reflection_type (assembly, type, &buf);
12732 buflen = buf.p - buf.buf;
12733 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12734 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12735 sigbuffer_free (&buf);
12737 return result;
12740 MonoArray *
12741 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12743 MonoError error;
12744 MonoDynamicImage *assembly = sig->module->dynamic_image;
12745 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12746 guint32 buflen, i;
12747 MonoArray *result;
12748 SigBuffer buf;
12750 check_array_for_usertypes (sig->arguments, &error);
12751 mono_error_raise_exception (&error); /* FIXME: don't raise here */
12753 sigbuffer_init (&buf, 32);
12755 sigbuffer_add_value (&buf, 0x06);
12756 for (i = 0; i < na; ++i) {
12757 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12758 encode_reflection_type (assembly, type, &buf);
12761 buflen = buf.p - buf.buf;
12762 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12763 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12764 sigbuffer_free (&buf);
12766 return result;
12769 typedef struct {
12770 MonoMethod *handle;
12771 MonoDomain *domain;
12772 } DynamicMethodReleaseData;
12775 * The runtime automatically clean up those after finalization.
12777 static MonoReferenceQueue *dynamic_method_queue;
12779 static void
12780 free_dynamic_method (void *dynamic_method)
12782 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12783 MonoDomain *domain = data->domain;
12784 MonoMethod *method = data->handle;
12785 guint32 dis_link;
12787 mono_domain_lock (domain);
12788 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12789 g_hash_table_remove (domain->method_to_dyn_method, method);
12790 mono_domain_unlock (domain);
12791 g_assert (dis_link);
12792 mono_gchandle_free (dis_link);
12794 mono_runtime_free_method (domain, method);
12795 g_free (data);
12798 void
12799 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12801 MonoReferenceQueue *queue;
12802 MonoMethod *handle;
12803 DynamicMethodReleaseData *release_data;
12804 ReflectionMethodBuilder rmb;
12805 MonoMethodSignature *sig;
12806 MonoClass *klass;
12807 MonoDomain *domain;
12808 GSList *l;
12809 int i;
12811 if (mono_runtime_is_shutting_down ())
12812 mono_raise_exception (mono_get_exception_invalid_operation (""));
12814 if (!(queue = dynamic_method_queue)) {
12815 mono_loader_lock ();
12816 if (!(queue = dynamic_method_queue))
12817 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12818 mono_loader_unlock ();
12821 sig = dynamic_method_to_signature (mb);
12823 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12826 * Resolve references.
12829 * Every second entry in the refs array is reserved for storing handle_class,
12830 * which is needed by the ldtoken implementation in the JIT.
12832 rmb.nrefs = mb->nrefs;
12833 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12834 for (i = 0; i < mb->nrefs; i += 2) {
12835 MonoClass *handle_class;
12836 gpointer ref;
12837 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12839 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12840 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12842 * The referenced DynamicMethod should already be created by the managed
12843 * code, except in the case of circular references. In that case, we store
12844 * method in the refs array, and fix it up later when the referenced
12845 * DynamicMethod is created.
12847 if (method->mhandle) {
12848 ref = method->mhandle;
12849 } else {
12850 /* FIXME: GC object stored in unmanaged memory */
12851 ref = method;
12853 /* FIXME: GC object stored in unmanaged memory */
12854 method->referenced_by = g_slist_append (method->referenced_by, mb);
12856 handle_class = mono_defaults.methodhandle_class;
12857 } else {
12858 MonoException *ex = NULL;
12859 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12860 if (!ref)
12861 ex = mono_get_exception_type_load (NULL, NULL);
12862 else if (mono_security_core_clr_enabled ())
12863 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12865 if (ex) {
12866 g_free (rmb.refs);
12867 mono_raise_exception (ex);
12868 return;
12872 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12873 rmb.refs [i + 1] = handle_class;
12876 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12878 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12879 release_data = g_new (DynamicMethodReleaseData, 1);
12880 release_data->handle = handle;
12881 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12882 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12883 g_free (release_data);
12885 /* Fix up refs entries pointing at us */
12886 for (l = mb->referenced_by; l; l = l->next) {
12887 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12888 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12889 gpointer *data;
12891 g_assert (method->mhandle);
12893 data = (gpointer*)wrapper->method_data;
12894 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12895 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12896 data [i + 1] = mb->mhandle;
12899 g_slist_free (mb->referenced_by);
12901 g_free (rmb.refs);
12903 /* ilgen is no longer needed */
12904 mb->ilgen = NULL;
12906 domain = mono_domain_get ();
12907 mono_domain_lock (domain);
12908 if (!domain->method_to_dyn_method)
12909 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12910 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12911 mono_domain_unlock (domain);
12914 #endif /* DISABLE_REFLECTION_EMIT */
12918 * mono_reflection_is_valid_dynamic_token:
12920 * Returns TRUE if token is valid.
12923 gboolean
12924 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12926 return lookup_dyn_token (image, token) != NULL;
12929 MonoMethodSignature *
12930 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12932 MonoMethodSignature *sig;
12933 g_assert (image_is_dynamic (image));
12935 mono_error_init (error);
12937 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12938 if (sig)
12939 return sig;
12941 return mono_method_signature_checked (method, error);
12944 #ifndef DISABLE_REFLECTION_EMIT
12947 * mono_reflection_lookup_dynamic_token:
12949 * Finish the Builder object pointed to by TOKEN and return the corresponding
12950 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
12951 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12952 * mapping table.
12954 * LOCKING: Take the loader lock
12956 gpointer
12957 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12959 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12960 MonoObject *obj;
12961 MonoClass *klass;
12963 obj = lookup_dyn_token (assembly, token);
12964 if (!obj) {
12965 if (valid_token)
12966 g_error ("Could not find required dynamic token 0x%08x", token);
12967 else
12968 return NULL;
12971 if (!handle_class)
12972 handle_class = &klass;
12973 return resolve_object (image, obj, handle_class, context);
12977 * ensure_complete_type:
12979 * Ensure that KLASS is completed if it is a dynamic type, or references
12980 * dynamic types.
12982 static void
12983 ensure_complete_type (MonoClass *klass)
12985 MonoError error;
12987 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12988 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12990 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
12991 mono_error_raise_exception (&error); /* FIXME don't raise here */
12993 // Asserting here could break a lot of code
12994 //g_assert (klass->wastypebuilder);
12997 if (klass->generic_class) {
12998 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12999 int i;
13001 for (i = 0; i < inst->type_argc; ++i) {
13002 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13007 static gpointer
13008 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13010 MonoError error;
13011 gpointer result = NULL;
13013 if (strcmp (obj->vtable->klass->name, "String") == 0) {
13014 result = mono_string_intern_checked ((MonoString*)obj, &error);
13015 mono_error_raise_exception (&error); /* FIXME don't raise here */
13016 *handle_class = mono_defaults.string_class;
13017 g_assert (result);
13018 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13019 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13020 MonoClass *mc = mono_class_from_mono_type (type);
13021 if (!mono_class_init (mc))
13022 mono_raise_exception (mono_class_get_exception_for_failure (mc));
13024 if (context) {
13025 MonoType *inflated = mono_class_inflate_generic_type (type, context);
13026 result = mono_class_from_mono_type (inflated);
13027 mono_metadata_free_type (inflated);
13028 } else {
13029 result = mono_class_from_mono_type (type);
13031 *handle_class = mono_defaults.typehandle_class;
13032 g_assert (result);
13033 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13034 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13035 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13036 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13037 result = ((MonoReflectionMethod*)obj)->method;
13038 if (context) {
13039 MonoError error;
13040 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13041 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13043 *handle_class = mono_defaults.methodhandle_class;
13044 g_assert (result);
13045 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13046 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13047 result = mb->mhandle;
13048 if (!result) {
13049 /* Type is not yet created */
13050 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13052 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13053 mono_error_raise_exception (&error); /* FIXME don't raise here */
13056 * Hopefully this has been filled in by calling CreateType() on the
13057 * TypeBuilder.
13060 * TODO: This won't work if the application finishes another
13061 * TypeBuilder instance instead of this one.
13063 result = mb->mhandle;
13065 if (context) {
13066 MonoError error;
13067 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13068 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13070 *handle_class = mono_defaults.methodhandle_class;
13071 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13072 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13074 result = cb->mhandle;
13075 if (!result) {
13076 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13078 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13079 mono_error_raise_exception (&error); /* FIXME don't raise here */
13080 result = cb->mhandle;
13082 if (context) {
13083 MonoError error;
13084 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13085 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13087 *handle_class = mono_defaults.methodhandle_class;
13088 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13089 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13091 ensure_complete_type (field->parent);
13092 if (context) {
13093 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
13094 MonoClass *klass = mono_class_from_mono_type (inflated);
13095 MonoClassField *inflated_field;
13096 gpointer iter = NULL;
13097 mono_metadata_free_type (inflated);
13098 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13099 if (!strcmp (field->name, inflated_field->name))
13100 break;
13102 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13103 result = inflated_field;
13104 } else {
13105 result = field;
13107 *handle_class = mono_defaults.fieldhandle_class;
13108 g_assert (result);
13109 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13110 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13111 result = fb->handle;
13113 if (!result) {
13114 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13116 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13117 mono_error_raise_exception (&error); /* FIXME don't raise here */
13118 result = fb->handle;
13121 if (fb->handle && fb->handle->parent->generic_container) {
13122 MonoClass *klass = fb->handle->parent;
13123 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
13124 MonoClass *inflated = mono_class_from_mono_type (type);
13126 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13127 g_assert (result);
13128 mono_metadata_free_type (type);
13130 *handle_class = mono_defaults.fieldhandle_class;
13131 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13132 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13133 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
13134 MonoClass *klass;
13136 klass = type->data.klass;
13137 if (klass->wastypebuilder) {
13138 /* Already created */
13139 result = klass;
13141 else {
13142 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13143 mono_error_raise_exception (&error); /* FIXME don't raise here */
13144 result = type->data.klass;
13145 g_assert (result);
13147 *handle_class = mono_defaults.typehandle_class;
13148 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13149 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13150 MonoMethodSignature *sig;
13151 int nargs, i;
13153 if (helper->arguments)
13154 nargs = mono_array_length (helper->arguments);
13155 else
13156 nargs = 0;
13158 sig = mono_metadata_signature_alloc (image, nargs);
13159 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13160 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13162 if (helper->unmanaged_call_conv) { /* unmanaged */
13163 sig->call_convention = helper->unmanaged_call_conv - 1;
13164 sig->pinvoke = TRUE;
13165 } else if (helper->call_conv & 0x02) {
13166 sig->call_convention = MONO_CALL_VARARG;
13167 } else {
13168 sig->call_convention = MONO_CALL_DEFAULT;
13171 sig->param_count = nargs;
13172 /* TODO: Copy type ? */
13173 sig->ret = helper->return_type->type;
13174 for (i = 0; i < nargs; ++i)
13175 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
13177 result = sig;
13178 *handle_class = NULL;
13179 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13180 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13181 /* Already created by the managed code */
13182 g_assert (method->mhandle);
13183 result = method->mhandle;
13184 *handle_class = mono_defaults.methodhandle_class;
13185 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13186 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13187 type = mono_class_inflate_generic_type (type, context);
13188 result = mono_class_from_mono_type (type);
13189 *handle_class = mono_defaults.typehandle_class;
13190 g_assert (result);
13191 mono_metadata_free_type (type);
13192 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13193 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13194 type = mono_class_inflate_generic_type (type, context);
13195 result = mono_class_from_mono_type (type);
13196 *handle_class = mono_defaults.typehandle_class;
13197 g_assert (result);
13198 mono_metadata_free_type (type);
13199 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13200 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13201 MonoClass *inflated;
13202 MonoType *type;
13203 MonoClassField *field;
13205 if (is_sre_field_builder (mono_object_class (f->fb)))
13206 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13207 else if (is_sr_mono_field (mono_object_class (f->fb)))
13208 field = ((MonoReflectionField*)f->fb)->field;
13209 else
13210 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)));
13212 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
13213 inflated = mono_class_from_mono_type (type);
13215 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13216 ensure_complete_type (field->parent);
13217 g_assert (result);
13218 mono_metadata_free_type (type);
13219 *handle_class = mono_defaults.fieldhandle_class;
13220 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13221 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13222 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
13223 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13224 MonoMethod *method;
13226 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13227 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13228 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13229 method = ((MonoReflectionMethod *)c->cb)->method;
13230 else
13231 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)));
13233 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13234 *handle_class = mono_defaults.methodhandle_class;
13235 mono_metadata_free_type (type);
13236 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13237 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13238 if (m->method_args) {
13239 result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13240 mono_error_raise_exception (&error); /* FIXME don't raise here */
13241 if (context) {
13242 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13243 mono_error_assert_ok (&error);
13245 } else {
13246 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
13247 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13248 MonoMethod *method;
13250 if (is_sre_method_builder (mono_object_class (m->mb)))
13251 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13252 else if (is_sr_mono_method (mono_object_class (m->mb)))
13253 method = ((MonoReflectionMethod *)m->mb)->method;
13254 else
13255 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)));
13257 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13258 mono_metadata_free_type (type);
13260 *handle_class = mono_defaults.methodhandle_class;
13261 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13262 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13263 MonoType *mtype;
13264 MonoClass *klass;
13265 MonoMethod *method;
13266 gpointer iter;
13267 char *name;
13269 mtype = mono_reflection_type_get_handle (m->parent);
13270 klass = mono_class_from_mono_type (mtype);
13272 /* Find the method */
13274 name = mono_string_to_utf8 (m->name);
13275 iter = NULL;
13276 while ((method = mono_class_get_methods (klass, &iter))) {
13277 if (!strcmp (method->name, name))
13278 break;
13280 g_free (name);
13282 // FIXME:
13283 g_assert (method);
13284 // FIXME: Check parameters/return value etc. match
13286 result = method;
13287 *handle_class = mono_defaults.methodhandle_class;
13288 } else if (is_sre_array (mono_object_get_class(obj)) ||
13289 is_sre_byref (mono_object_get_class(obj)) ||
13290 is_sre_pointer (mono_object_get_class(obj))) {
13291 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13292 MonoType *type = mono_reflection_type_get_handle (ref_type);
13294 if (context) {
13295 MonoType *inflated = mono_class_inflate_generic_type (type, context);
13296 result = mono_class_from_mono_type (inflated);
13297 mono_metadata_free_type (inflated);
13298 } else {
13299 result = mono_class_from_mono_type (type);
13301 *handle_class = mono_defaults.typehandle_class;
13302 } else {
13303 g_print ("%s\n", obj->vtable->klass->name);
13304 g_assert_not_reached ();
13306 return result;
13309 #else /* DISABLE_REFLECTION_EMIT */
13311 MonoArray*
13312 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
13314 g_assert_not_reached ();
13315 return NULL;
13318 void
13319 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13321 g_assert_not_reached ();
13324 void
13325 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13327 g_assert_not_reached ();
13330 void
13331 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13333 g_assert_not_reached ();
13336 void
13337 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13339 g_assert_not_reached ();
13342 void
13343 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13345 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13348 void
13349 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13351 g_assert_not_reached ();
13354 void
13355 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13357 g_assert_not_reached ();
13360 MonoReflectionModule *
13361 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13363 g_assert_not_reached ();
13364 return NULL;
13367 guint32
13368 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13370 g_assert_not_reached ();
13371 return 0;
13374 guint32
13375 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13377 g_assert_not_reached ();
13378 return 0;
13381 guint32
13382 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
13383 gboolean create_open_instance, gboolean register_token, MonoError *error)
13385 g_assert_not_reached ();
13386 return 0;
13389 void
13390 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13394 void
13395 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13397 g_assert_not_reached ();
13400 void
13401 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13403 *overrides = NULL;
13404 *num_overrides = 0;
13407 MonoReflectionEvent *
13408 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13410 g_assert_not_reached ();
13411 return NULL;
13414 MonoReflectionType*
13415 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13417 g_assert_not_reached ();
13418 return NULL;
13421 void
13422 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13424 g_assert_not_reached ();
13427 MonoArray *
13428 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13430 g_assert_not_reached ();
13431 return NULL;
13434 MonoArray *
13435 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13437 g_assert_not_reached ();
13438 return NULL;
13441 void
13442 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13446 gpointer
13447 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13449 return NULL;
13452 MonoType*
13453 mono_reflection_type_get_handle (MonoReflectionType* ref)
13455 if (!ref)
13456 return NULL;
13457 return ref->type;
13460 void
13461 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13463 g_assert_not_reached ();
13466 #endif /* DISABLE_REFLECTION_EMIT */
13468 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13469 const static guint32 declsec_flags_map[] = {
13470 0x00000000, /* empty */
13471 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
13472 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
13473 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
13474 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
13475 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
13476 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
13477 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
13478 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
13479 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
13480 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
13481 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
13482 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
13483 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
13484 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
13485 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
13486 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
13487 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
13488 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
13492 * Returns flags that includes all available security action associated to the handle.
13493 * @token: metadata token (either for a class or a method)
13494 * @image: image where resides the metadata.
13496 static guint32
13497 mono_declsec_get_flags (MonoImage *image, guint32 token)
13499 int index = mono_metadata_declsec_from_index (image, token);
13500 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13501 guint32 result = 0;
13502 guint32 action;
13503 int i;
13505 /* HasSecurity can be present for other, not specially encoded, attributes,
13506 e.g. SuppressUnmanagedCodeSecurityAttribute */
13507 if (index < 0)
13508 return 0;
13510 for (i = index; i < t->rows; i++) {
13511 guint32 cols [MONO_DECL_SECURITY_SIZE];
13513 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13514 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13515 break;
13517 action = cols [MONO_DECL_SECURITY_ACTION];
13518 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13519 result |= declsec_flags_map [action];
13520 } else {
13521 g_assert_not_reached ();
13524 return result;
13528 * Get the security actions (in the form of flags) associated with the specified method.
13530 * @method: The method for which we want the declarative security flags.
13531 * Return the declarative security flags for the method (only).
13533 * Note: To keep MonoMethod size down we do not cache the declarative security flags
13534 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
13536 guint32
13537 mono_declsec_flags_from_method (MonoMethod *method)
13539 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13540 /* FIXME: No cache (for the moment) */
13541 guint32 idx = mono_method_get_index (method);
13542 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13543 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13544 return mono_declsec_get_flags (method->klass->image, idx);
13546 return 0;
13550 * Get the security actions (in the form of flags) associated with the specified class.
13552 * @klass: The class for which we want the declarative security flags.
13553 * Return the declarative security flags for the class.
13555 * Note: We cache the flags inside the MonoClass structure as this will get
13556 * called very often (at least for each method).
13558 guint32
13559 mono_declsec_flags_from_class (MonoClass *klass)
13561 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13562 if (!klass->ext || !klass->ext->declsec_flags) {
13563 guint32 idx;
13565 idx = mono_metadata_token_index (klass->type_token);
13566 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13567 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13568 mono_loader_lock ();
13569 mono_class_alloc_ext (klass);
13570 mono_loader_unlock ();
13571 /* we cache the flags on classes */
13572 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13574 return klass->ext->declsec_flags;
13576 return 0;
13580 * Get the security actions (in the form of flags) associated with the specified assembly.
13582 * @assembly: The assembly for which we want the declarative security flags.
13583 * Return the declarative security flags for the assembly.
13585 guint32
13586 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13588 guint32 idx = 1; /* there is only one assembly */
13589 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13590 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13591 return mono_declsec_get_flags (assembly->image, idx);
13596 * Fill actions for the specific index (which may either be an encoded class token or
13597 * an encoded method token) from the metadata image.
13598 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13600 static MonoBoolean
13601 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13602 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13604 MonoBoolean result = FALSE;
13605 MonoTableInfo *t;
13606 guint32 cols [MONO_DECL_SECURITY_SIZE];
13607 int index = mono_metadata_declsec_from_index (image, token);
13608 int i;
13610 t = &image->tables [MONO_TABLE_DECLSECURITY];
13611 for (i = index; i < t->rows; i++) {
13612 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13614 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13615 return result;
13617 /* if present only replace (class) permissions with method permissions */
13618 /* if empty accept either class or method permissions */
13619 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13620 if (!actions->demand.blob) {
13621 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13622 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13623 actions->demand.blob = (char*) (blob + 2);
13624 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13625 result = TRUE;
13627 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13628 if (!actions->noncasdemand.blob) {
13629 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13630 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13631 actions->noncasdemand.blob = (char*) (blob + 2);
13632 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13633 result = TRUE;
13635 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13636 if (!actions->demandchoice.blob) {
13637 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13638 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13639 actions->demandchoice.blob = (char*) (blob + 2);
13640 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13641 result = TRUE;
13646 return result;
13649 static MonoBoolean
13650 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
13651 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13653 guint32 idx = mono_metadata_token_index (klass->type_token);
13654 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13655 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13656 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13659 static MonoBoolean
13660 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
13661 guint32 id_std, guint32 id_noncas, guint32 id_choice)
13663 guint32 idx = mono_method_get_index (method);
13664 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13665 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13666 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13670 * Collect all actions (that requires to generate code in mini) assigned for
13671 * the specified method.
13672 * Note: Don't use the content of actions if the function return FALSE.
13674 MonoBoolean
13675 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13677 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
13678 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13679 MonoBoolean result = FALSE;
13680 guint32 flags;
13682 /* quick exit if no declarative security is present in the metadata */
13683 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13684 return FALSE;
13686 /* we want the original as the wrapper is "free" of the security informations */
13687 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13688 method = mono_marshal_method_from_wrapper (method);
13689 if (!method)
13690 return FALSE;
13693 /* First we look for method-level attributes */
13694 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13695 mono_class_init (method->klass);
13696 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13698 result = mono_declsec_get_method_demands_params (method, demands,
13699 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13702 /* Here we use (or create) the class declarative cache to look for demands */
13703 flags = mono_declsec_flags_from_class (method->klass);
13704 if (flags & mask) {
13705 if (!result) {
13706 mono_class_init (method->klass);
13707 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13709 result |= mono_declsec_get_class_demands_params (method->klass, demands,
13710 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13713 /* The boolean return value is used as a shortcut in case nothing needs to
13714 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13715 return result;
13720 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13722 * Note: Don't use the content of actions if the function return FALSE.
13724 MonoBoolean
13725 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13727 MonoBoolean result = FALSE;
13728 guint32 flags;
13730 /* quick exit if no declarative security is present in the metadata */
13731 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13732 return FALSE;
13734 /* we want the original as the wrapper is "free" of the security informations */
13735 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13736 method = mono_marshal_method_from_wrapper (method);
13737 if (!method)
13738 return FALSE;
13741 /* results are independant - zeroize both */
13742 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13743 memset (klass, 0, sizeof (MonoDeclSecurityActions));
13745 /* First we look for method-level attributes */
13746 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13747 mono_class_init (method->klass);
13749 result = mono_declsec_get_method_demands_params (method, cmethod,
13750 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13753 /* Here we use (or create) the class declarative cache to look for demands */
13754 flags = mono_declsec_flags_from_class (method->klass);
13755 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13756 mono_class_init (method->klass);
13758 result |= mono_declsec_get_class_demands_params (method->klass, klass,
13759 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13762 return result;
13766 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13768 * @klass The inherited class - this is the class that provides the security check (attributes)
13769 * @demans
13770 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13772 * Note: Don't use the content of actions if the function return FALSE.
13774 MonoBoolean
13775 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13777 MonoBoolean result = FALSE;
13778 guint32 flags;
13780 /* quick exit if no declarative security is present in the metadata */
13781 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13782 return FALSE;
13784 /* Here we use (or create) the class declarative cache to look for demands */
13785 flags = mono_declsec_flags_from_class (klass);
13786 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13787 mono_class_init (klass);
13788 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13790 result |= mono_declsec_get_class_demands_params (klass, demands,
13791 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13794 return result;
13798 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13800 * Note: Don't use the content of actions if the function return FALSE.
13802 MonoBoolean
13803 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13805 /* quick exit if no declarative security is present in the metadata */
13806 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13807 return FALSE;
13809 /* we want the original as the wrapper is "free" of the security informations */
13810 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13811 method = mono_marshal_method_from_wrapper (method);
13812 if (!method)
13813 return FALSE;
13816 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13817 mono_class_init (method->klass);
13818 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13820 return mono_declsec_get_method_demands_params (method, demands,
13821 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13823 return FALSE;
13827 static MonoBoolean
13828 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13830 guint32 cols [MONO_DECL_SECURITY_SIZE];
13831 MonoTableInfo *t;
13832 int i;
13834 int index = mono_metadata_declsec_from_index (image, token);
13835 if (index == -1)
13836 return FALSE;
13838 t = &image->tables [MONO_TABLE_DECLSECURITY];
13839 for (i = index; i < t->rows; i++) {
13840 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13842 /* shortcut - index are ordered */
13843 if (token != cols [MONO_DECL_SECURITY_PARENT])
13844 return FALSE;
13846 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13847 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13848 entry->blob = (char*) (metadata + 2);
13849 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13850 return TRUE;
13854 return FALSE;
13857 MonoBoolean
13858 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13860 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13861 guint32 idx = mono_method_get_index (method);
13862 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13863 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13864 return get_declsec_action (method->klass->image, idx, action, entry);
13866 return FALSE;
13869 MonoBoolean
13870 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13872 /* use cache */
13873 guint32 flags = mono_declsec_flags_from_class (klass);
13874 if (declsec_flags_map [action] & flags) {
13875 guint32 idx = mono_metadata_token_index (klass->type_token);
13876 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13877 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13878 return get_declsec_action (klass->image, idx, action, entry);
13880 return FALSE;
13883 MonoBoolean
13884 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13886 guint32 idx = 1; /* there is only one assembly */
13887 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13888 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13890 return get_declsec_action (assembly->image, idx, action, entry);
13893 gboolean
13894 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13896 MonoError error;
13897 MonoObject *res, *exc;
13898 void *params [1];
13899 static MonoMethod *method = NULL;
13901 if (method == NULL) {
13902 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
13903 g_assert (method);
13907 * The result of mono_type_get_object_checked () might be a System.MonoType but we
13908 * need a TypeBuilder so use mono_class_get_ref_info (klass).
13910 g_assert (mono_class_get_ref_info (klass));
13911 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13913 params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13914 mono_error_raise_exception (&error); /* FIXME don't raise here */
13916 res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
13918 if (exc || !mono_error_ok (&error)) {
13919 mono_error_cleanup (&error);
13920 return FALSE;
13921 } else
13922 return *(MonoBoolean*)mono_object_unbox (res);
13926 * mono_reflection_type_get_type:
13927 * @reftype: the System.Type object
13929 * Returns the MonoType* associated with the C# System.Type object @reftype.
13931 MonoType*
13932 mono_reflection_type_get_type (MonoReflectionType *reftype)
13934 g_assert (reftype);
13936 return mono_reflection_type_get_handle (reftype);
13940 * mono_reflection_assembly_get_assembly:
13941 * @refassembly: the System.Reflection.Assembly object
13943 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13945 MonoAssembly*
13946 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13948 g_assert (refassembly);
13950 return refassembly->assembly;