2 * reflection.c: Routines for creating an image at runtime.
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
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>
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
);
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
64 MonoReflectionILGen
*ilgen
;
65 MonoReflectionType
*rtype
;
66 MonoArray
*parameters
;
67 MonoArray
*generic_params
;
68 MonoGenericContainer
*generic_container
;
74 guint32
*table_idx
; /* note: it's a pointer */
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
;
89 int charset
, extra_flags
, native_cc
;
90 MonoString
*dll
, *dllentry
;
91 } ReflectionMethodBuilder
;
95 MonoReflectionGenericParam
*gparam
;
96 } GenericParamTableEntry
;
98 const unsigned char table_sizes
[MONO_TABLE_NUM
] = {
108 MONO_INTERFACEIMPL_SIZE
,
109 MONO_MEMBERREF_SIZE
, /* 0x0A */
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
,
120 MONO_PROPERTY_MAP_SIZE
,
123 MONO_METHOD_SEMA_SIZE
,
124 MONO_METHODIMPL_SIZE
,
125 MONO_MODULEREF_SIZE
, /* 0x1A */
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
,
140 MONO_NESTED_CLASS_SIZE
,
142 MONO_GENERICPARAM_SIZE
, /* 0x2A */
143 MONO_METHODSPEC_SIZE
,
144 MONO_GENPARCONSTRAINT_SIZE
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32
mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
);
150 static guint32
mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_open_instance
, MonoError
*error
);
151 static guint32
mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*cb
, MonoError
*error
);
152 static guint32
mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
, MonoError
*error
);
153 static gboolean
ensure_runtime_vtable (MonoClass
*klass
, MonoError
*error
);
154 static gpointer
resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
, MonoError
*error
);
155 static guint32
mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
, MonoError
*error
);
156 static guint32
encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
);
157 static gpointer
register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
);
158 static gboolean
reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
, MonoError
*error
);
159 static gboolean
reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
, MonoError
*error
);
160 static guint32
create_generic_typespec (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
, MonoError
*error
);
163 static guint32
mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
);
164 static guint32
mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
);
165 static void mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
);
166 static guint32
encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
, MonoError
*error
);
167 static guint32
encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, guint32
*ret_type
);
168 static char* type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
);
169 static void encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
);
170 static void get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
);
171 static MonoReflectionType
*mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
, MonoError
*error
);
172 static MonoType
* mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
, MonoError
*error
);
173 static MonoReflectionType
* mono_reflection_type_resolve_user_types (MonoReflectionType
*type
, MonoError
*error
);
174 static gboolean
is_sre_array (MonoClass
*klass
);
175 static gboolean
is_sre_byref (MonoClass
*klass
);
176 static gboolean
is_sre_pointer (MonoClass
*klass
);
177 static gboolean
is_sre_type_builder (MonoClass
*klass
);
178 static gboolean
is_sre_method_builder (MonoClass
*klass
);
179 static gboolean
is_sre_ctor_builder (MonoClass
*klass
);
180 static gboolean
is_sre_field_builder (MonoClass
*klass
);
181 static gboolean
is_sr_mono_method (MonoClass
*klass
);
182 static gboolean
is_sr_mono_cmethod (MonoClass
*klass
);
183 static gboolean
is_sr_mono_generic_method (MonoClass
*klass
);
184 static gboolean
is_sr_mono_generic_cmethod (MonoClass
*klass
);
185 static gboolean
is_sr_mono_field (MonoClass
*klass
);
186 static gboolean
is_sr_mono_property (MonoClass
*klass
);
187 static gboolean
is_sre_method_on_tb_inst (MonoClass
*klass
);
188 static gboolean
is_sre_ctor_on_tb_inst (MonoClass
*klass
);
190 static gboolean
type_is_reference (MonoType
*type
);
192 static guint32
mono_image_get_methodspec_token (MonoDynamicImage
*assembly
, MonoMethod
*method
);
193 static guint32
mono_image_get_inflated_method_token (MonoDynamicImage
*assembly
, MonoMethod
*m
);
194 static MonoMethod
* inflate_method (MonoReflectionType
*type
, MonoObject
*obj
, MonoError
*error
);
196 static guint32
create_typespec (MonoDynamicImage
*assembly
, MonoType
*type
);
197 static void init_type_builder_generics (MonoObject
*type
);
199 #define RESOLVE_TYPE(type, error) do { \
200 type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
202 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do { \
203 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
204 __type = mono_reflection_type_resolve_user_types (__type, error); \
205 if (mono_error_ok (error)) \
206 mono_array_set (arr, MonoReflectionType*, index, __type); \
209 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
211 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
212 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
214 #if SIZEOF_VOID_P == 4
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
217 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
220 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
221 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
223 /* Class lazy loading functions */
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly
, System
.Reflection
, MonoAssembly
)
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_module
, System
.Reflection
, MonoModule
)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method
, System
.Reflection
, MonoGenericMethod
);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod
, System
.Reflection
, MonoGenericCMethod
);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_method
, System
.Reflection
, MonoMethod
);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod
, System
.Reflection
, MonoCMethod
);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_field
, System
.Reflection
, MonoField
);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_event
, System
.Reflection
, MonoEvent
);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_property
, System
.Reflection
, MonoProperty
);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info
, System
.Reflection
, MonoParameterInfo
);
234 static GENERATE_GET_CLASS_WITH_CACHE (missing
, System
.Reflection
, Missing
);
235 static GENERATE_GET_CLASS_WITH_CACHE (method_body
, System
.Reflection
, MethodBody
);
236 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info
, System
.Reflection
, LocalVariableInfo
);
237 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause
, System
.Reflection
, ExceptionHandlingClause
);
238 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument
, System
.Reflection
, CustomAttributeTypedArgument
);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument
, System
.Reflection
, CustomAttributeNamedArgument
);
240 static GENERATE_GET_CLASS_WITH_CACHE (type_builder
, System
.Reflection
.Emit
, TypeBuilder
);
241 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute
, System
.Runtime
.InteropServices
, MarshalAsAttribute
);
242 static GENERATE_GET_CLASS_WITH_CACHE (dbnull
, System
, DBNull
);
244 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
245 static GPtrArray
*dynamic_images
;
246 static mono_mutex_t dynamic_images_mutex
;
249 dynamic_images_lock (void)
251 mono_os_mutex_lock (&dynamic_images_mutex
);
255 dynamic_images_unlock (void)
257 mono_os_mutex_unlock (&dynamic_images_mutex
);
261 * mono_find_dynamic_image_owner:
263 * Find the dynamic image, if any, which a given pointer is located in the memory of.
266 mono_find_dynamic_image_owner (void *ptr
)
268 MonoImage
*owner
= NULL
;
271 dynamic_images_lock ();
275 for (i
= 0; !owner
&& i
< dynamic_images
->len
; ++i
) {
276 MonoImage
*image
= (MonoImage
*)g_ptr_array_index (dynamic_images
, i
);
277 if (mono_mempool_contains_addr (image
->mempool
, ptr
))
282 dynamic_images_unlock ();
288 mono_reflection_init (void)
290 mono_os_mutex_init (&dynamic_images_mutex
);
294 dynamic_image_lock (MonoDynamicImage
*image
)
296 MONO_PREPARE_BLOCKING
;
297 mono_image_lock ((MonoImage
*)image
);
298 MONO_FINISH_BLOCKING
;
302 dynamic_image_unlock (MonoDynamicImage
*image
)
304 mono_image_unlock ((MonoImage
*)image
);
308 register_dyn_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
310 MONO_REQ_GC_UNSAFE_MODE
;
312 dynamic_image_lock (assembly
);
313 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), obj
);
314 dynamic_image_unlock (assembly
);
318 lookup_dyn_token (MonoDynamicImage
*assembly
, guint32 token
)
320 MONO_REQ_GC_UNSAFE_MODE
;
324 dynamic_image_lock (assembly
);
325 obj
= (MonoObject
*)mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
326 dynamic_image_unlock (assembly
);
332 sigbuffer_init (SigBuffer
*buf
, int size
)
334 MONO_REQ_GC_NEUTRAL_MODE
;
336 buf
->buf
= (char *)g_malloc (size
);
338 buf
->end
= buf
->buf
+ size
;
342 sigbuffer_make_room (SigBuffer
*buf
, int size
)
344 MONO_REQ_GC_NEUTRAL_MODE
;
346 if (buf
->end
- buf
->p
< size
) {
347 int new_size
= buf
->end
- buf
->buf
+ size
+ 32;
348 char *p
= (char *)g_realloc (buf
->buf
, new_size
);
349 size
= buf
->p
- buf
->buf
;
352 buf
->end
= buf
->buf
+ new_size
;
357 sigbuffer_add_value (SigBuffer
*buf
, guint32 val
)
359 MONO_REQ_GC_NEUTRAL_MODE
;
361 sigbuffer_make_room (buf
, 6);
362 mono_metadata_encode_value (val
, buf
->p
, &buf
->p
);
366 sigbuffer_add_byte (SigBuffer
*buf
, guint8 val
)
368 MONO_REQ_GC_NEUTRAL_MODE
;
370 sigbuffer_make_room (buf
, 1);
376 sigbuffer_add_mem (SigBuffer
*buf
, char *p
, guint32 size
)
378 MONO_REQ_GC_NEUTRAL_MODE
;
380 sigbuffer_make_room (buf
, size
);
381 memcpy (buf
->p
, p
, size
);
386 sigbuffer_free (SigBuffer
*buf
)
388 MONO_REQ_GC_NEUTRAL_MODE
;
393 #ifndef DISABLE_REFLECTION_EMIT
397 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
401 image_g_malloc (MonoImage
*image
, guint size
)
403 MONO_REQ_GC_NEUTRAL_MODE
;
406 return mono_image_alloc (image
, size
);
408 return g_malloc (size
);
410 #endif /* !DISABLE_REFLECTION_EMIT */
415 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
419 image_g_malloc0 (MonoImage
*image
, guint size
)
421 MONO_REQ_GC_NEUTRAL_MODE
;
424 return mono_image_alloc0 (image
, size
);
426 return g_malloc0 (size
);
431 * @image: a MonoImage
434 * If @image is NULL, free @ptr, otherwise do nothing.
437 image_g_free (MonoImage
*image
, gpointer ptr
)
443 #ifndef DISABLE_REFLECTION_EMIT
445 image_strdup (MonoImage
*image
, const char *s
)
447 MONO_REQ_GC_NEUTRAL_MODE
;
450 return mono_image_strdup (image
, s
);
456 #define image_g_new(image,struct_type, n_structs) \
457 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
459 #define image_g_new0(image,struct_type, n_structs) \
460 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
464 alloc_table (MonoDynamicTable
*table
, guint nrows
)
466 MONO_REQ_GC_NEUTRAL_MODE
;
469 g_assert (table
->columns
);
470 if (nrows
+ 1 >= table
->alloc_rows
) {
471 while (nrows
+ 1 >= table
->alloc_rows
) {
472 if (table
->alloc_rows
== 0)
473 table
->alloc_rows
= 16;
475 table
->alloc_rows
*= 2;
478 table
->values
= (guint32
*)g_renew (guint32
, table
->values
, (table
->alloc_rows
) * table
->columns
);
483 make_room_in_stream (MonoDynamicStream
*stream
, int size
)
485 MONO_REQ_GC_NEUTRAL_MODE
;
487 if (size
<= stream
->alloc_size
)
490 while (stream
->alloc_size
<= size
) {
491 if (stream
->alloc_size
< 4096)
492 stream
->alloc_size
= 4096;
494 stream
->alloc_size
*= 2;
497 stream
->data
= (char *)g_realloc (stream
->data
, stream
->alloc_size
);
501 string_heap_insert (MonoDynamicStream
*sh
, const char *str
)
503 MONO_REQ_GC_NEUTRAL_MODE
;
507 gpointer oldkey
, oldval
;
509 if (g_hash_table_lookup_extended (sh
->hash
, str
, &oldkey
, &oldval
))
510 return GPOINTER_TO_UINT (oldval
);
512 len
= strlen (str
) + 1;
515 make_room_in_stream (sh
, idx
+ len
);
518 * We strdup the string even if we already copy them in sh->data
519 * so that the string pointers in the hash remain valid even if
520 * we need to realloc sh->data. We may want to avoid that later.
522 g_hash_table_insert (sh
->hash
, g_strdup (str
), GUINT_TO_POINTER (idx
));
523 memcpy (sh
->data
+ idx
, str
, len
);
529 string_heap_insert_mstring (MonoDynamicStream
*sh
, MonoString
*str
)
531 MONO_REQ_GC_UNSAFE_MODE
;
533 char *name
= mono_string_to_utf8 (str
);
535 idx
= string_heap_insert (sh
, name
);
540 #ifndef DISABLE_REFLECTION_EMIT
542 string_heap_init (MonoDynamicStream
*sh
)
544 MONO_REQ_GC_NEUTRAL_MODE
;
547 sh
->alloc_size
= 4096;
548 sh
->data
= (char *)g_malloc (4096);
549 sh
->hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
550 string_heap_insert (sh
, "");
555 mono_image_add_stream_data (MonoDynamicStream
*stream
, const char *data
, guint32 len
)
557 MONO_REQ_GC_NEUTRAL_MODE
;
561 make_room_in_stream (stream
, stream
->index
+ len
);
562 memcpy (stream
->data
+ stream
->index
, data
, len
);
564 stream
->index
+= len
;
566 * align index? Not without adding an additional param that controls it since
567 * we may store a blob value in pieces.
573 mono_image_add_stream_zero (MonoDynamicStream
*stream
, guint32 len
)
575 MONO_REQ_GC_NEUTRAL_MODE
;
579 make_room_in_stream (stream
, stream
->index
+ len
);
580 memset (stream
->data
+ stream
->index
, 0, len
);
582 stream
->index
+= len
;
587 stream_data_align (MonoDynamicStream
*stream
)
589 MONO_REQ_GC_NEUTRAL_MODE
;
592 guint32 count
= stream
->index
% 4;
594 /* we assume the stream data will be aligned */
596 mono_image_add_stream_data (stream
, buf
, 4 - count
);
599 #ifndef DISABLE_REFLECTION_EMIT
601 mono_blob_entry_hash (const char* str
)
603 MONO_REQ_GC_NEUTRAL_MODE
;
607 len
= mono_metadata_decode_blob_size (str
, &str
);
611 for (str
+= 1; str
< end
; str
++)
612 h
= (h
<< 5) - h
+ *str
;
620 mono_blob_entry_equal (const char *str1
, const char *str2
) {
621 MONO_REQ_GC_NEUTRAL_MODE
;
626 len
= mono_metadata_decode_blob_size (str1
, &end1
);
627 len2
= mono_metadata_decode_blob_size (str2
, &end2
);
630 return memcmp (end1
, end2
, len
) == 0;
634 add_to_blob_cached (MonoDynamicImage
*assembly
, char *b1
, int s1
, char *b2
, int s2
)
636 MONO_REQ_GC_NEUTRAL_MODE
;
640 gpointer oldkey
, oldval
;
642 copy
= (char *)g_malloc (s1
+s2
);
643 memcpy (copy
, b1
, s1
);
644 memcpy (copy
+ s1
, b2
, s2
);
645 if (g_hash_table_lookup_extended (assembly
->blob_cache
, copy
, &oldkey
, &oldval
)) {
647 idx
= GPOINTER_TO_UINT (oldval
);
649 idx
= mono_image_add_stream_data (&assembly
->blob
, b1
, s1
);
650 mono_image_add_stream_data (&assembly
->blob
, b2
, s2
);
651 g_hash_table_insert (assembly
->blob_cache
, copy
, GUINT_TO_POINTER (idx
));
657 sigbuffer_add_to_blob_cached (MonoDynamicImage
*assembly
, SigBuffer
*buf
)
659 MONO_REQ_GC_NEUTRAL_MODE
;
663 guint32 size
= buf
->p
- buf
->buf
;
665 g_assert (size
<= (buf
->end
- buf
->buf
));
666 mono_metadata_encode_value (size
, b
, &b
);
667 return add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, buf
->buf
, size
);
671 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
672 * dest may be misaligned.
675 swap_with_size (char *dest
, const char* val
, int len
, int nelem
) {
676 MONO_REQ_GC_NEUTRAL_MODE
;
677 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
680 for (elem
= 0; elem
< nelem
; ++elem
) {
706 g_assert_not_reached ();
712 memcpy (dest
, val
, len
* nelem
);
717 add_mono_string_to_blob_cached (MonoDynamicImage
*assembly
, MonoString
*str
)
719 MONO_REQ_GC_UNSAFE_MODE
;
723 guint32 idx
= 0, len
;
725 len
= str
->length
* 2;
726 mono_metadata_encode_value (len
, b
, &b
);
727 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
729 char *swapped
= g_malloc (2 * mono_string_length (str
));
730 const char *p
= (const char*)mono_string_chars (str
);
732 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
733 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
737 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
742 #ifndef DISABLE_REFLECTION_EMIT
744 default_class_from_mono_type (MonoType
*type
)
746 MONO_REQ_GC_NEUTRAL_MODE
;
748 switch (type
->type
) {
749 case MONO_TYPE_OBJECT
:
750 return mono_defaults
.object_class
;
752 return mono_defaults
.void_class
;
753 case MONO_TYPE_BOOLEAN
:
754 return mono_defaults
.boolean_class
;
756 return mono_defaults
.char_class
;
758 return mono_defaults
.sbyte_class
;
760 return mono_defaults
.byte_class
;
762 return mono_defaults
.int16_class
;
764 return mono_defaults
.uint16_class
;
766 return mono_defaults
.int32_class
;
768 return mono_defaults
.uint32_class
;
770 return mono_defaults
.int_class
;
772 return mono_defaults
.uint_class
;
774 return mono_defaults
.int64_class
;
776 return mono_defaults
.uint64_class
;
778 return mono_defaults
.single_class
;
780 return mono_defaults
.double_class
;
781 case MONO_TYPE_STRING
:
782 return mono_defaults
.string_class
;
784 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type
->type
);
785 g_assert_not_reached ();
793 * mono_class_get_ref_info:
795 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
798 mono_class_get_ref_info (MonoClass
*klass
)
800 MONO_REQ_GC_UNSAFE_MODE
;
802 if (klass
->ref_info_handle
== 0)
805 return mono_gchandle_get_target (klass
->ref_info_handle
);
809 mono_class_set_ref_info (MonoClass
*klass
, gpointer obj
)
811 MONO_REQ_GC_UNSAFE_MODE
;
813 klass
->ref_info_handle
= mono_gchandle_new ((MonoObject
*)obj
, FALSE
);
814 g_assert (klass
->ref_info_handle
!= 0);
818 mono_class_free_ref_info (MonoClass
*klass
)
820 MONO_REQ_GC_NEUTRAL_MODE
;
822 if (klass
->ref_info_handle
) {
823 mono_gchandle_free (klass
->ref_info_handle
);
824 klass
->ref_info_handle
= 0;
829 encode_generic_class (MonoDynamicImage
*assembly
, MonoGenericClass
*gclass
, SigBuffer
*buf
)
831 MONO_REQ_GC_NEUTRAL_MODE
;
834 MonoGenericInst
*class_inst
;
839 class_inst
= gclass
->context
.class_inst
;
841 sigbuffer_add_value (buf
, MONO_TYPE_GENERICINST
);
842 klass
= gclass
->container_class
;
843 sigbuffer_add_value (buf
, klass
->byval_arg
.type
);
844 sigbuffer_add_value (buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
846 sigbuffer_add_value (buf
, class_inst
->type_argc
);
847 for (i
= 0; i
< class_inst
->type_argc
; ++i
)
848 encode_type (assembly
, class_inst
->type_argv
[i
], buf
);
853 encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
)
855 MONO_REQ_GC_NEUTRAL_MODE
;
858 g_assert_not_reached ();
863 sigbuffer_add_value (buf
, MONO_TYPE_BYREF
);
867 case MONO_TYPE_BOOLEAN
:
881 case MONO_TYPE_STRING
:
882 case MONO_TYPE_OBJECT
:
883 case MONO_TYPE_TYPEDBYREF
:
884 sigbuffer_add_value (buf
, type
->type
);
887 sigbuffer_add_value (buf
, type
->type
);
888 encode_type (assembly
, type
->data
.type
, buf
);
890 case MONO_TYPE_SZARRAY
:
891 sigbuffer_add_value (buf
, type
->type
);
892 encode_type (assembly
, &type
->data
.klass
->byval_arg
, buf
);
894 case MONO_TYPE_VALUETYPE
:
895 case MONO_TYPE_CLASS
: {
896 MonoClass
*k
= mono_class_from_mono_type (type
);
898 if (k
->generic_container
) {
899 MonoGenericClass
*gclass
= mono_metadata_lookup_generic_class (k
, k
->generic_container
->context
.class_inst
, TRUE
);
900 encode_generic_class (assembly
, gclass
, buf
);
903 * Make sure we use the correct type.
905 sigbuffer_add_value (buf
, k
->byval_arg
.type
);
907 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
908 * otherwise two typerefs could point to the same type, leading to
909 * verification errors.
911 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, &k
->byval_arg
));
915 case MONO_TYPE_ARRAY
:
916 sigbuffer_add_value (buf
, type
->type
);
917 encode_type (assembly
, &type
->data
.array
->eklass
->byval_arg
, buf
);
918 sigbuffer_add_value (buf
, type
->data
.array
->rank
);
919 sigbuffer_add_value (buf
, 0); /* FIXME: set to 0 for now */
920 sigbuffer_add_value (buf
, 0);
922 case MONO_TYPE_GENERICINST
:
923 encode_generic_class (assembly
, type
->data
.generic_class
, buf
);
927 sigbuffer_add_value (buf
, type
->type
);
928 sigbuffer_add_value (buf
, mono_type_get_generic_param_num (type
));
931 g_error ("need to encode type %x", type
->type
);
936 encode_reflection_type (MonoDynamicImage
*assembly
, MonoReflectionType
*type
, SigBuffer
*buf
, MonoError
*error
)
938 MONO_REQ_GC_UNSAFE_MODE
;
940 mono_error_init (error
);
943 sigbuffer_add_value (buf
, MONO_TYPE_VOID
);
947 MonoType
*t
= mono_reflection_type_get_handle (type
, error
);
948 return_if_nok (error
);
949 encode_type (assembly
, t
, buf
);
953 encode_custom_modifiers (MonoDynamicImage
*assembly
, MonoArray
*modreq
, MonoArray
*modopt
, SigBuffer
*buf
, MonoError
*error
)
955 MONO_REQ_GC_UNSAFE_MODE
;
959 mono_error_init (error
);
962 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
963 MonoType
*mod
= mono_type_array_get_and_resolve (modreq
, i
, error
);
964 return_if_nok (error
);
965 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_REQD
);
966 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
));
970 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
971 MonoType
*mod
= mono_type_array_get_and_resolve (modopt
, i
, error
);
972 return_if_nok (error
);
973 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_OPT
);
974 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
));
979 #ifndef DISABLE_REFLECTION_EMIT
981 method_encode_signature (MonoDynamicImage
*assembly
, MonoMethodSignature
*sig
)
983 MONO_REQ_GC_UNSAFE_MODE
;
987 guint32 nparams
= sig
->param_count
;
993 sigbuffer_init (&buf
, 32);
995 * FIXME: vararg, explicit_this, differenc call_conv values...
997 idx
= sig
->call_convention
;
999 idx
|= 0x20; /* hasthis */
1000 if (sig
->generic_param_count
)
1001 idx
|= 0x10; /* generic */
1002 sigbuffer_add_byte (&buf
, idx
);
1003 if (sig
->generic_param_count
)
1004 sigbuffer_add_value (&buf
, sig
->generic_param_count
);
1005 sigbuffer_add_value (&buf
, nparams
);
1006 encode_type (assembly
, sig
->ret
, &buf
);
1007 for (i
= 0; i
< nparams
; ++i
) {
1008 if (i
== sig
->sentinelpos
)
1009 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
1010 encode_type (assembly
, sig
->params
[i
], &buf
);
1012 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1013 sigbuffer_free (&buf
);
1019 method_builder_encode_signature (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
, MonoError
*error
)
1021 MONO_REQ_GC_UNSAFE_MODE
;
1023 mono_error_init (error
);
1026 * FIXME: reuse code from method_encode_signature().
1030 guint32 nparams
= mb
->parameters
? mono_array_length (mb
->parameters
): 0;
1031 guint32 ngparams
= mb
->generic_params
? mono_array_length (mb
->generic_params
): 0;
1032 guint32 notypes
= mb
->opt_types
? mono_array_length (mb
->opt_types
): 0;
1035 sigbuffer_init (&buf
, 32);
1036 /* LAMESPEC: all the call conv spec is foobared */
1037 idx
= mb
->call_conv
& 0x60; /* has-this, explicit-this */
1038 if (mb
->call_conv
& 2)
1039 idx
|= 0x5; /* vararg */
1040 if (!(mb
->attrs
& METHOD_ATTRIBUTE_STATIC
))
1041 idx
|= 0x20; /* hasthis */
1043 idx
|= 0x10; /* generic */
1044 sigbuffer_add_byte (&buf
, idx
);
1046 sigbuffer_add_value (&buf
, ngparams
);
1047 sigbuffer_add_value (&buf
, nparams
+ notypes
);
1048 encode_custom_modifiers (assembly
, mb
->return_modreq
, mb
->return_modopt
, &buf
, error
);
1051 encode_reflection_type (assembly
, mb
->rtype
, &buf
, error
);
1054 for (i
= 0; i
< nparams
; ++i
) {
1055 MonoArray
*modreq
= NULL
;
1056 MonoArray
*modopt
= NULL
;
1057 MonoReflectionType
*pt
;
1059 if (mb
->param_modreq
&& (i
< mono_array_length (mb
->param_modreq
)))
1060 modreq
= mono_array_get (mb
->param_modreq
, MonoArray
*, i
);
1061 if (mb
->param_modopt
&& (i
< mono_array_length (mb
->param_modopt
)))
1062 modopt
= mono_array_get (mb
->param_modopt
, MonoArray
*, i
);
1063 encode_custom_modifiers (assembly
, modreq
, modopt
, &buf
, error
);
1066 pt
= mono_array_get (mb
->parameters
, MonoReflectionType
*, i
);
1067 encode_reflection_type (assembly
, pt
, &buf
, error
);
1072 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
1073 for (i
= 0; i
< notypes
; ++i
) {
1074 MonoReflectionType
*pt
;
1076 pt
= mono_array_get (mb
->opt_types
, MonoReflectionType
*, i
);
1077 encode_reflection_type (assembly
, pt
, &buf
, error
);
1082 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1084 sigbuffer_free (&buf
);
1089 encode_locals (MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
, MonoError
*error
)
1091 MONO_REQ_GC_UNSAFE_MODE
;
1093 mono_error_init (error
);
1095 MonoDynamicTable
*table
;
1097 guint32 idx
, sig_idx
;
1098 guint nl
= mono_array_length (ilgen
->locals
);
1102 sigbuffer_init (&buf
, 32);
1103 sigbuffer_add_value (&buf
, 0x07);
1104 sigbuffer_add_value (&buf
, nl
);
1105 for (i
= 0; i
< nl
; ++i
) {
1106 MonoReflectionLocalBuilder
*lb
= mono_array_get (ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
1109 sigbuffer_add_value (&buf
, MONO_TYPE_PINNED
);
1111 encode_reflection_type (assembly
, (MonoReflectionType
*)lb
->type
, &buf
, error
);
1112 if (!is_ok (error
)) {
1113 sigbuffer_free (&buf
);
1117 sig_idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1118 sigbuffer_free (&buf
);
1120 if (assembly
->standalonesig_cache
== NULL
)
1121 assembly
->standalonesig_cache
= g_hash_table_new (NULL
, NULL
);
1122 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
)));
1126 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
1127 idx
= table
->next_idx
++;
1129 alloc_table (table
, table
->rows
);
1130 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
1132 values
[MONO_STAND_ALONE_SIGNATURE
] = sig_idx
;
1134 g_hash_table_insert (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
), GUINT_TO_POINTER (idx
));
1140 method_count_clauses (MonoReflectionILGen
*ilgen
)
1142 MONO_REQ_GC_UNSAFE_MODE
;
1144 guint32 num_clauses
= 0;
1147 MonoILExceptionInfo
*ex_info
;
1148 for (i
= 0; i
< mono_array_length (ilgen
->ex_handlers
); ++i
) {
1149 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
1150 if (ex_info
->handlers
)
1151 num_clauses
+= mono_array_length (ex_info
->handlers
);
1159 #ifndef DISABLE_REFLECTION_EMIT
1160 static MonoExceptionClause
*
1161 method_encode_clauses (MonoImage
*image
, MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
, guint32 num_clauses
, MonoError
*error
)
1163 MONO_REQ_GC_UNSAFE_MODE
;
1165 mono_error_init (error
);
1167 MonoExceptionClause
*clauses
;
1168 MonoExceptionClause
*clause
;
1169 MonoILExceptionInfo
*ex_info
;
1170 MonoILExceptionBlock
*ex_block
;
1171 guint32 finally_start
;
1172 int i
, j
, clause_index
;;
1174 clauses
= image_g_new0 (image
, MonoExceptionClause
, num_clauses
);
1177 for (i
= mono_array_length (ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
1178 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
1179 finally_start
= ex_info
->start
+ ex_info
->len
;
1180 if (!ex_info
->handlers
)
1182 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
1183 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
1184 clause
= &(clauses
[clause_index
]);
1186 clause
->flags
= ex_block
->type
;
1187 clause
->try_offset
= ex_info
->start
;
1189 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
1190 clause
->try_len
= finally_start
- ex_info
->start
;
1192 clause
->try_len
= ex_info
->len
;
1193 clause
->handler_offset
= ex_block
->start
;
1194 clause
->handler_len
= ex_block
->len
;
1195 if (ex_block
->extype
) {
1196 MonoType
*extype
= mono_reflection_type_get_handle ((MonoReflectionType
*)ex_block
->extype
, error
);
1198 if (!is_ok (error
)) {
1199 image_g_free (image
, clauses
);
1202 clause
->data
.catch_class
= mono_class_from_mono_type (extype
);
1204 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
1205 clause
->data
.filter_offset
= ex_block
->filter_offset
;
1207 clause
->data
.filter_offset
= 0;
1209 finally_start
= ex_block
->start
+ ex_block
->len
;
1217 #endif /* !DISABLE_REFLECTION_EMIT */
1220 * method_encode_code:
1222 * @assembly the assembly
1223 * @mb the managed MethodBuilder
1224 * @error set on error
1226 * Note that the return value is not sensible if @error is set.
1229 method_encode_code (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
, MonoError
*error
)
1231 MONO_REQ_GC_UNSAFE_MODE
;
1236 gint32 max_stack
, i
;
1237 gint32 num_locals
= 0;
1238 gint32 num_exception
= 0;
1241 char fat_header
[12];
1243 guint16 short_value
;
1244 guint32 local_sig
= 0;
1245 guint32 header_size
= 12;
1248 mono_error_init (error
);
1250 if ((mb
->attrs
& (METHOD_ATTRIBUTE_PINVOKE_IMPL
| METHOD_ATTRIBUTE_ABSTRACT
)) ||
1251 (mb
->iattrs
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
)))
1255 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1257 code
= mb
->ilgen
->code
;
1258 code_size
= mb
->ilgen
->code_len
;
1259 max_stack
= mb
->ilgen
->max_stack
;
1260 num_locals
= mb
->ilgen
->locals
? mono_array_length (mb
->ilgen
->locals
) : 0;
1261 if (mb
->ilgen
->ex_handlers
)
1262 num_exception
= method_count_clauses (mb
->ilgen
);
1266 char *name
= mono_string_to_utf8 (mb
->name
);
1267 char *str
= g_strdup_printf ("Method %s does not have any IL associated", name
);
1268 mono_error_set_argument (error
, NULL
, "a method does not have any IL associated");
1274 code_size
= mono_array_length (code
);
1275 max_stack
= 8; /* we probably need to run a verifier on the code... */
1278 stream_data_align (&assembly
->code
);
1280 /* check for exceptions, maxstack, locals */
1281 maybe_small
= (max_stack
<= 8) && (!num_locals
) && (!num_exception
);
1283 if (code_size
< 64 && !(code_size
& 1)) {
1284 flags
= (code_size
<< 2) | 0x2;
1285 } else if (code_size
< 32 && (code_size
& 1)) {
1286 flags
= (code_size
<< 2) | 0x6; /* LAMESPEC: see metadata.c */
1290 idx
= mono_image_add_stream_data (&assembly
->code
, &flags
, 1);
1291 /* add to the fixup todo list */
1292 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
1293 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 1));
1294 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
1295 return assembly
->text_rva
+ idx
;
1299 local_sig
= MONO_TOKEN_SIGNATURE
| encode_locals (assembly
, mb
->ilgen
, error
);
1300 return_val_if_nok (error
, 0);
1303 * FIXME: need to set also the header size in fat_flags.
1304 * (and more sects and init locals flags)
1308 fat_flags
|= METHOD_HEADER_MORE_SECTS
;
1309 if (mb
->init_locals
)
1310 fat_flags
|= METHOD_HEADER_INIT_LOCALS
;
1311 fat_header
[0] = fat_flags
;
1312 fat_header
[1] = (header_size
/ 4 ) << 4;
1313 short_value
= GUINT16_TO_LE (max_stack
);
1314 memcpy (fat_header
+ 2, &short_value
, 2);
1315 int_value
= GUINT32_TO_LE (code_size
);
1316 memcpy (fat_header
+ 4, &int_value
, 4);
1317 int_value
= GUINT32_TO_LE (local_sig
);
1318 memcpy (fat_header
+ 8, &int_value
, 4);
1319 idx
= mono_image_add_stream_data (&assembly
->code
, fat_header
, 12);
1320 /* add to the fixup todo list */
1321 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
1322 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 12));
1324 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
1325 if (num_exception
) {
1326 unsigned char sheader
[4];
1327 MonoILExceptionInfo
* ex_info
;
1328 MonoILExceptionBlock
* ex_block
;
1331 stream_data_align (&assembly
->code
);
1332 /* always use fat format for now */
1333 sheader
[0] = METHOD_HEADER_SECTION_FAT_FORMAT
| METHOD_HEADER_SECTION_EHTABLE
;
1334 num_exception
*= 6 * sizeof (guint32
);
1335 num_exception
+= 4; /* include the size of the header */
1336 sheader
[1] = num_exception
& 0xff;
1337 sheader
[2] = (num_exception
>> 8) & 0xff;
1338 sheader
[3] = (num_exception
>> 16) & 0xff;
1339 mono_image_add_stream_data (&assembly
->code
, (char*)sheader
, 4);
1340 /* fat header, so we are already aligned */
1342 for (i
= mono_array_length (mb
->ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
1343 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (mb
->ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
1344 if (ex_info
->handlers
) {
1345 int finally_start
= ex_info
->start
+ ex_info
->len
;
1346 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
1348 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
1350 val
= GUINT32_TO_LE (ex_block
->type
);
1351 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1353 val
= GUINT32_TO_LE (ex_info
->start
);
1354 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1355 /* need fault, too, probably */
1356 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
1357 val
= GUINT32_TO_LE (finally_start
- ex_info
->start
);
1359 val
= GUINT32_TO_LE (ex_info
->len
);
1360 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1361 /* handler offset */
1362 val
= GUINT32_TO_LE (ex_block
->start
);
1363 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1365 val
= GUINT32_TO_LE (ex_block
->len
);
1366 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1367 finally_start
= ex_block
->start
+ ex_block
->len
;
1368 if (ex_block
->extype
) {
1369 MonoType
*extype
= mono_reflection_type_get_handle ((MonoReflectionType
*)ex_block
->extype
, error
);
1370 return_val_if_nok (error
, 0);
1372 val
= mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly
, extype
));
1374 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
1375 val
= ex_block
->filter_offset
;
1379 val
= GUINT32_TO_LE (val
);
1380 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1381 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1382 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1385 g_error ("No clauses for ex info block %d", i
);
1389 return assembly
->text_rva
+ idx
;
1393 find_index_in_table (MonoDynamicImage
*assembly
, int table_idx
, int col
, guint32 token
)
1395 MONO_REQ_GC_NEUTRAL_MODE
;
1398 MonoDynamicTable
*table
;
1401 table
= &assembly
->tables
[table_idx
];
1403 g_assert (col
< table
->columns
);
1405 values
= table
->values
+ table
->columns
;
1406 for (i
= 1; i
<= table
->rows
; ++i
) {
1407 if (values
[col
] == token
)
1409 values
+= table
->columns
;
1415 * LOCKING: Acquires the loader lock.
1417 static MonoCustomAttrInfo
*
1418 lookup_custom_attr (MonoImage
*image
, gpointer member
)
1420 MONO_REQ_GC_NEUTRAL_MODE
;
1422 MonoCustomAttrInfo
* res
;
1424 res
= (MonoCustomAttrInfo
*)mono_image_property_lookup (image
, member
, MONO_PROP_DYNAMIC_CATTR
);
1429 res
= (MonoCustomAttrInfo
*)g_memdup (res
, MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * res
->num_attrs
);
1435 custom_attr_visible (MonoImage
*image
, MonoReflectionCustomAttr
*cattr
)
1437 MONO_REQ_GC_UNSAFE_MODE
;
1439 /* FIXME: Need to do more checks */
1440 if (cattr
->ctor
->method
&& (cattr
->ctor
->method
->klass
->image
!= image
)) {
1441 int visibility
= cattr
->ctor
->method
->klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
1443 if ((visibility
!= TYPE_ATTRIBUTE_PUBLIC
) && (visibility
!= TYPE_ATTRIBUTE_NESTED_PUBLIC
))
1450 static MonoCustomAttrInfo
*
1451 mono_custom_attrs_from_builders (MonoImage
*alloc_img
, MonoImage
*image
, MonoArray
*cattrs
)
1453 MONO_REQ_GC_UNSAFE_MODE
;
1455 int i
, index
, count
, not_visible
;
1456 MonoCustomAttrInfo
*ainfo
;
1457 MonoReflectionCustomAttr
*cattr
;
1461 /* FIXME: check in assembly the Run flag is set */
1463 count
= mono_array_length (cattrs
);
1465 /* Skip nonpublic attributes since MS.NET seems to do the same */
1466 /* FIXME: This needs to be done more globally */
1468 for (i
= 0; i
< count
; ++i
) {
1469 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1470 if (!custom_attr_visible (image
, cattr
))
1473 count
-= not_visible
;
1475 ainfo
= (MonoCustomAttrInfo
*)image_g_malloc0 (alloc_img
, MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * count
);
1477 ainfo
->image
= image
;
1478 ainfo
->num_attrs
= count
;
1479 ainfo
->cached
= alloc_img
!= NULL
;
1481 for (i
= 0; i
< count
; ++i
) {
1482 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1483 if (custom_attr_visible (image
, cattr
)) {
1484 unsigned char *saved
= (unsigned char *)mono_image_alloc (image
, mono_array_length (cattr
->data
));
1485 memcpy (saved
, mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1486 ainfo
->attrs
[index
].ctor
= cattr
->ctor
->method
;
1487 ainfo
->attrs
[index
].data
= saved
;
1488 ainfo
->attrs
[index
].data_size
= mono_array_length (cattr
->data
);
1496 #ifndef DISABLE_REFLECTION_EMIT
1498 * LOCKING: Acquires the loader lock.
1501 mono_save_custom_attrs (MonoImage
*image
, void *obj
, MonoArray
*cattrs
)
1503 MONO_REQ_GC_UNSAFE_MODE
;
1505 MonoCustomAttrInfo
*ainfo
, *tmp
;
1507 if (!cattrs
|| !mono_array_length (cattrs
))
1510 ainfo
= mono_custom_attrs_from_builders (image
, image
, cattrs
);
1512 mono_loader_lock ();
1513 tmp
= (MonoCustomAttrInfo
*)mono_image_property_lookup (image
, obj
, MONO_PROP_DYNAMIC_CATTR
);
1515 mono_custom_attrs_free (tmp
);
1516 mono_image_property_insert (image
, obj
, MONO_PROP_DYNAMIC_CATTR
, ainfo
);
1517 mono_loader_unlock ();
1523 mono_custom_attrs_free (MonoCustomAttrInfo
*ainfo
)
1525 MONO_REQ_GC_NEUTRAL_MODE
;
1527 if (ainfo
&& !ainfo
->cached
)
1532 * idx is the table index of the object
1533 * type is one of MONO_CUSTOM_ATTR_*
1536 mono_image_add_cattrs (MonoDynamicImage
*assembly
, guint32 idx
, guint32 type
, MonoArray
*cattrs
, MonoError
*error
)
1538 MONO_REQ_GC_UNSAFE_MODE
;
1540 MonoDynamicTable
*table
;
1541 MonoReflectionCustomAttr
*cattr
;
1543 guint32 count
, i
, token
;
1545 char *p
= blob_size
;
1547 mono_error_init (error
);
1549 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1552 count
= mono_array_length (cattrs
);
1553 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
1554 table
->rows
+= count
;
1555 alloc_table (table
, table
->rows
);
1556 values
= table
->values
+ table
->next_idx
* MONO_CUSTOM_ATTR_SIZE
;
1557 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1559 for (i
= 0; i
< count
; ++i
) {
1560 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1561 values
[MONO_CUSTOM_ATTR_PARENT
] = idx
;
1562 token
= mono_image_create_token (assembly
, (MonoObject
*)cattr
->ctor
, FALSE
, FALSE
, error
);
1563 if (!mono_error_ok (error
)) goto fail
;
1564 type
= mono_metadata_token_index (token
);
1565 type
<<= MONO_CUSTOM_ATTR_TYPE_BITS
;
1566 switch (mono_metadata_token_table (token
)) {
1567 case MONO_TABLE_METHOD
:
1568 type
|= MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
1570 * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1571 * method, not the one returned by mono_image_create_token ().
1573 mono_g_hash_table_insert (assembly
->remapped_tokens
, GUINT_TO_POINTER (token
), cattr
->ctor
);
1575 case MONO_TABLE_MEMBERREF
:
1576 type
|= MONO_CUSTOM_ATTR_TYPE_MEMBERREF
;
1579 g_warning ("got wrong token in custom attr");
1582 values
[MONO_CUSTOM_ATTR_TYPE
] = type
;
1584 mono_metadata_encode_value (mono_array_length (cattr
->data
), p
, &p
);
1585 values
[MONO_CUSTOM_ATTR_VALUE
] = add_to_blob_cached (assembly
, blob_size
, p
- blob_size
,
1586 mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1587 values
+= MONO_CUSTOM_ATTR_SIZE
;
1598 mono_image_add_decl_security (MonoDynamicImage
*assembly
, guint32 parent_token
, MonoArray
*permissions
)
1600 MONO_REQ_GC_UNSAFE_MODE
;
1602 MonoDynamicTable
*table
;
1604 guint32 count
, i
, idx
;
1605 MonoReflectionPermissionSet
*perm
;
1610 count
= mono_array_length (permissions
);
1611 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
1612 table
->rows
+= count
;
1613 alloc_table (table
, table
->rows
);
1615 for (i
= 0; i
< mono_array_length (permissions
); ++i
) {
1616 perm
= (MonoReflectionPermissionSet
*)mono_array_addr (permissions
, MonoReflectionPermissionSet
, i
);
1618 values
= table
->values
+ table
->next_idx
* MONO_DECL_SECURITY_SIZE
;
1620 idx
= mono_metadata_token_index (parent_token
);
1621 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
1622 switch (mono_metadata_token_table (parent_token
)) {
1623 case MONO_TABLE_TYPEDEF
:
1624 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
1626 case MONO_TABLE_METHOD
:
1627 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
1629 case MONO_TABLE_ASSEMBLY
:
1630 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
1633 g_assert_not_reached ();
1636 values
[MONO_DECL_SECURITY_ACTION
] = perm
->action
;
1637 values
[MONO_DECL_SECURITY_PARENT
] = idx
;
1638 values
[MONO_DECL_SECURITY_PERMISSIONSET
] = add_mono_string_to_blob_cached (assembly
, perm
->pset
);
1645 * Fill in the MethodDef and ParamDef tables for a method.
1646 * This is used for both normal methods and constructors.
1649 mono_image_basic_method (ReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
, MonoError
*error
)
1651 MONO_REQ_GC_UNSAFE_MODE
;
1653 MonoDynamicTable
*table
;
1657 mono_error_init (error
);
1659 /* room in this table is already allocated */
1660 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
1661 *mb
->table_idx
= table
->next_idx
++;
1662 g_hash_table_insert (assembly
->method_to_table_idx
, mb
->mhandle
, GUINT_TO_POINTER ((*mb
->table_idx
)));
1663 values
= table
->values
+ *mb
->table_idx
* MONO_METHOD_SIZE
;
1664 values
[MONO_METHOD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1665 values
[MONO_METHOD_FLAGS
] = mb
->attrs
;
1666 values
[MONO_METHOD_IMPLFLAGS
] = mb
->iattrs
;
1667 values
[MONO_METHOD_SIGNATURE
] = method_builder_encode_signature (assembly
, mb
, error
);
1668 return_val_if_nok (error
, FALSE
);
1669 values
[MONO_METHOD_RVA
] = method_encode_code (assembly
, mb
, error
);
1670 return_val_if_nok (error
, FALSE
);
1672 table
= &assembly
->tables
[MONO_TABLE_PARAM
];
1673 values
[MONO_METHOD_PARAMLIST
] = table
->next_idx
;
1675 mono_image_add_decl_security (assembly
,
1676 mono_metadata_make_token (MONO_TABLE_METHOD
, *mb
->table_idx
), mb
->permissions
);
1679 MonoDynamicTable
*mtable
;
1682 mtable
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
1683 mvalues
= mtable
->values
+ mtable
->next_idx
* MONO_FIELD_MARSHAL_SIZE
;
1686 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1687 if (mono_array_get (mb
->pinfo
, gpointer
, i
))
1690 table
->rows
+= count
;
1691 alloc_table (table
, table
->rows
);
1692 values
= table
->values
+ table
->next_idx
* MONO_PARAM_SIZE
;
1693 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1694 MonoReflectionParamBuilder
*pb
;
1695 if ((pb
= mono_array_get (mb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
1696 values
[MONO_PARAM_FLAGS
] = pb
->attrs
;
1697 values
[MONO_PARAM_SEQUENCE
] = i
;
1698 if (pb
->name
!= NULL
) {
1699 values
[MONO_PARAM_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
1701 values
[MONO_PARAM_NAME
] = 0;
1703 values
+= MONO_PARAM_SIZE
;
1704 if (pb
->marshal_info
) {
1706 alloc_table (mtable
, mtable
->rows
);
1707 mvalues
= mtable
->values
+ mtable
->rows
* MONO_FIELD_MARSHAL_SIZE
;
1708 mvalues
[MONO_FIELD_MARSHAL_PARENT
] = (table
->next_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_PARAMDEF
;
1709 mvalues
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, pb
->marshal_info
, error
);
1710 return_val_if_nok (error
, FALSE
);
1712 pb
->table_idx
= table
->next_idx
++;
1713 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
1714 guint32 field_type
= 0;
1715 mtable
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
1717 alloc_table (mtable
, mtable
->rows
);
1718 mvalues
= mtable
->values
+ mtable
->rows
* MONO_CONSTANT_SIZE
;
1719 mvalues
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_PARAM
| (pb
->table_idx
<< MONO_HASCONSTANT_BITS
);
1720 mvalues
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, pb
->def_value
, &field_type
);
1721 mvalues
[MONO_CONSTANT_TYPE
] = field_type
;
1722 mvalues
[MONO_CONSTANT_PADDING
] = 0;
1731 #ifndef DISABLE_REFLECTION_EMIT
1733 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
, MonoError
*error
)
1735 MONO_REQ_GC_UNSAFE_MODE
;
1737 mono_error_init (error
);
1738 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1740 rmb
->ilgen
= mb
->ilgen
;
1741 rmb
->rtype
= mono_reflection_type_resolve_user_types ((MonoReflectionType
*)mb
->rtype
, error
);
1742 return_val_if_nok (error
, FALSE
);
1743 rmb
->parameters
= mb
->parameters
;
1744 rmb
->generic_params
= mb
->generic_params
;
1745 rmb
->generic_container
= mb
->generic_container
;
1746 rmb
->opt_types
= NULL
;
1747 rmb
->pinfo
= mb
->pinfo
;
1748 rmb
->attrs
= mb
->attrs
;
1749 rmb
->iattrs
= mb
->iattrs
;
1750 rmb
->call_conv
= mb
->call_conv
;
1751 rmb
->code
= mb
->code
;
1752 rmb
->type
= mb
->type
;
1753 rmb
->name
= mb
->name
;
1754 rmb
->table_idx
= &mb
->table_idx
;
1755 rmb
->init_locals
= mb
->init_locals
;
1756 rmb
->skip_visibility
= FALSE
;
1757 rmb
->return_modreq
= mb
->return_modreq
;
1758 rmb
->return_modopt
= mb
->return_modopt
;
1759 rmb
->param_modreq
= mb
->param_modreq
;
1760 rmb
->param_modopt
= mb
->param_modopt
;
1761 rmb
->permissions
= mb
->permissions
;
1762 rmb
->mhandle
= mb
->mhandle
;
1767 rmb
->charset
= mb
->charset
;
1768 rmb
->extra_flags
= mb
->extra_flags
;
1769 rmb
->native_cc
= mb
->native_cc
;
1770 rmb
->dllentry
= mb
->dllentry
;
1778 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
, MonoError
*error
)
1780 MONO_REQ_GC_UNSAFE_MODE
;
1782 const char *name
= mb
->attrs
& METHOD_ATTRIBUTE_STATIC
? ".cctor": ".ctor";
1784 mono_error_init (error
);
1786 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1788 rmb
->ilgen
= mb
->ilgen
;
1789 rmb
->rtype
= mono_type_get_object_checked (mono_domain_get (), &mono_defaults
.void_class
->byval_arg
, error
);
1790 return_val_if_nok (error
, FALSE
);
1791 rmb
->parameters
= mb
->parameters
;
1792 rmb
->generic_params
= NULL
;
1793 rmb
->generic_container
= NULL
;
1794 rmb
->opt_types
= NULL
;
1795 rmb
->pinfo
= mb
->pinfo
;
1796 rmb
->attrs
= mb
->attrs
;
1797 rmb
->iattrs
= mb
->iattrs
;
1798 rmb
->call_conv
= mb
->call_conv
;
1800 rmb
->type
= mb
->type
;
1801 rmb
->name
= mono_string_new (mono_domain_get (), name
);
1802 rmb
->table_idx
= &mb
->table_idx
;
1803 rmb
->init_locals
= mb
->init_locals
;
1804 rmb
->skip_visibility
= FALSE
;
1805 rmb
->return_modreq
= NULL
;
1806 rmb
->return_modopt
= NULL
;
1807 rmb
->param_modreq
= mb
->param_modreq
;
1808 rmb
->param_modopt
= mb
->param_modopt
;
1809 rmb
->permissions
= mb
->permissions
;
1810 rmb
->mhandle
= mb
->mhandle
;
1818 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder
*rmb
, MonoReflectionDynamicMethod
*mb
)
1820 MONO_REQ_GC_UNSAFE_MODE
;
1822 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1824 rmb
->ilgen
= mb
->ilgen
;
1825 rmb
->rtype
= mb
->rtype
;
1826 rmb
->parameters
= mb
->parameters
;
1827 rmb
->generic_params
= NULL
;
1828 rmb
->generic_container
= NULL
;
1829 rmb
->opt_types
= NULL
;
1831 rmb
->attrs
= mb
->attrs
;
1833 rmb
->call_conv
= mb
->call_conv
;
1835 rmb
->type
= (MonoObject
*) mb
->owner
;
1836 rmb
->name
= mb
->name
;
1837 rmb
->table_idx
= NULL
;
1838 rmb
->init_locals
= mb
->init_locals
;
1839 rmb
->skip_visibility
= mb
->skip_visibility
;
1840 rmb
->return_modreq
= NULL
;
1841 rmb
->return_modopt
= NULL
;
1842 rmb
->param_modreq
= NULL
;
1843 rmb
->param_modopt
= NULL
;
1844 rmb
->permissions
= NULL
;
1845 rmb
->mhandle
= mb
->mhandle
;
1852 mono_image_add_methodimpl (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, MonoError
*error
)
1854 MONO_REQ_GC_UNSAFE_MODE
;
1856 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
1857 MonoDynamicTable
*table
;
1860 MonoReflectionMethod
*m
;
1863 mono_error_init (error
);
1865 if (!mb
->override_methods
)
1868 for (i
= 0; i
< mono_array_length (mb
->override_methods
); ++i
) {
1869 m
= mono_array_get (mb
->override_methods
, MonoReflectionMethod
*, i
);
1871 table
= &assembly
->tables
[MONO_TABLE_METHODIMPL
];
1873 alloc_table (table
, table
->rows
);
1874 values
= table
->values
+ table
->rows
* MONO_METHODIMPL_SIZE
;
1875 values
[MONO_METHODIMPL_CLASS
] = tb
->table_idx
;
1876 values
[MONO_METHODIMPL_BODY
] = MONO_METHODDEFORREF_METHODDEF
| (mb
->table_idx
<< MONO_METHODDEFORREF_BITS
);
1878 tok
= mono_image_create_token (assembly
, (MonoObject
*)m
, FALSE
, FALSE
, error
);
1879 return_val_if_nok (error
, FALSE
);
1881 switch (mono_metadata_token_table (tok
)) {
1882 case MONO_TABLE_MEMBERREF
:
1883 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
1885 case MONO_TABLE_METHOD
:
1886 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
1889 g_assert_not_reached ();
1891 values
[MONO_METHODIMPL_DECLARATION
] = tok
;
1897 #ifndef DISABLE_REFLECTION_EMIT
1899 mono_image_get_method_info (MonoReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
, MonoError
*error
)
1901 MONO_REQ_GC_UNSAFE_MODE
;
1903 MonoDynamicTable
*table
;
1905 ReflectionMethodBuilder rmb
;
1908 mono_error_init (error
);
1910 if (!reflection_methodbuilder_from_method_builder (&rmb
, mb
, error
) ||
1911 !mono_image_basic_method (&rmb
, assembly
, error
))
1914 mb
->table_idx
= *rmb
.table_idx
;
1916 if (mb
->dll
) { /* It's a P/Invoke method */
1918 /* map CharSet values to on-disk values */
1919 int ncharset
= (mb
->charset
? (mb
->charset
- 1) * 2 : 0);
1920 int extra_flags
= mb
->extra_flags
;
1921 table
= &assembly
->tables
[MONO_TABLE_IMPLMAP
];
1923 alloc_table (table
, table
->rows
);
1924 values
= table
->values
+ table
->rows
* MONO_IMPLMAP_SIZE
;
1926 values
[MONO_IMPLMAP_FLAGS
] = (mb
->native_cc
<< 8) | ncharset
| extra_flags
;
1927 values
[MONO_IMPLMAP_MEMBER
] = (mb
->table_idx
<< 1) | 1; /* memberforwarded: method */
1929 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->dllentry
);
1931 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1932 moduleref
= string_heap_insert_mstring (&assembly
->sheap
, mb
->dll
);
1933 if (!(values
[MONO_IMPLMAP_SCOPE
] = find_index_in_table (assembly
, MONO_TABLE_MODULEREF
, MONO_MODULEREF_NAME
, moduleref
))) {
1934 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
1936 alloc_table (table
, table
->rows
);
1937 table
->values
[table
->rows
* MONO_MODULEREF_SIZE
+ MONO_MODULEREF_NAME
] = moduleref
;
1938 values
[MONO_IMPLMAP_SCOPE
] = table
->rows
;
1942 if (mb
->generic_params
) {
1943 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
1944 table
->rows
+= mono_array_length (mb
->generic_params
);
1945 alloc_table (table
, table
->rows
);
1946 for (i
= 0; i
< mono_array_length (mb
->generic_params
); ++i
) {
1947 guint32 owner
= MONO_TYPEORMETHOD_METHOD
| (mb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
1949 mono_image_get_generic_param_info (
1950 (MonoReflectionGenericParam
*)mono_array_get (mb
->generic_params
, gpointer
, i
), owner
, assembly
);
1958 mono_image_get_ctor_info (MonoDomain
*domain
, MonoReflectionCtorBuilder
*mb
, MonoDynamicImage
*assembly
, MonoError
*error
)
1960 MONO_REQ_GC_UNSAFE_MODE
;
1962 ReflectionMethodBuilder rmb
;
1964 if (!reflection_methodbuilder_from_ctor_builder (&rmb
, mb
, error
))
1967 if (!mono_image_basic_method (&rmb
, assembly
, error
))
1970 mb
->table_idx
= *rmb
.table_idx
;
1977 type_get_fully_qualified_name (MonoType
*type
)
1979 MONO_REQ_GC_NEUTRAL_MODE
;
1981 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1985 type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
)
1987 MONO_REQ_GC_UNSAFE_MODE
;
1992 klass
= mono_class_from_mono_type (type
);
1994 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
1995 ta
= klass
->image
->assembly
;
1996 if (assembly_is_dynamic (ta
) || (ta
== ass
)) {
1997 if (klass
->generic_class
|| klass
->generic_container
)
1998 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1999 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_FULL_NAME
);
2001 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
2004 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
2007 #ifndef DISABLE_REFLECTION_EMIT
2008 /*field_image is the image to which the eventual custom mods have been encoded against*/
2010 fieldref_encode_signature (MonoDynamicImage
*assembly
, MonoImage
*field_image
, MonoType
*type
)
2012 MONO_REQ_GC_NEUTRAL_MODE
;
2015 guint32 idx
, i
, token
;
2017 if (!assembly
->save
)
2020 sigbuffer_init (&buf
, 32);
2022 sigbuffer_add_value (&buf
, 0x06);
2023 /* encode custom attributes before the type */
2024 if (type
->num_mods
) {
2025 for (i
= 0; i
< type
->num_mods
; ++i
) {
2028 MonoClass
*klass
= mono_class_get_checked (field_image
, type
->modifiers
[i
].token
, &error
);
2029 g_assert (mono_error_ok (&error
)); /* FIXME don't swallow the error */
2031 token
= mono_image_typedef_or_ref (assembly
, &klass
->byval_arg
);
2033 token
= type
->modifiers
[i
].token
;
2036 if (type
->modifiers
[i
].required
)
2037 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_REQD
);
2039 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_OPT
);
2041 sigbuffer_add_value (&buf
, token
);
2044 encode_type (assembly
, type
, &buf
);
2045 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2046 sigbuffer_free (&buf
);
2052 field_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
, MonoError
*error
)
2054 MONO_REQ_GC_UNSAFE_MODE
;
2056 mono_error_init (error
);
2060 guint32 typespec
= 0;
2064 init_type_builder_generics (fb
->type
);
2066 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
, error
);
2067 return_val_if_nok (error
, 0);
2068 klass
= mono_class_from_mono_type (type
);
2070 sigbuffer_init (&buf
, 32);
2072 sigbuffer_add_value (&buf
, 0x06);
2073 encode_custom_modifiers (assembly
, fb
->modreq
, fb
->modopt
, &buf
, error
);
2076 /* encode custom attributes before the type */
2078 if (klass
->generic_container
)
2079 typespec
= create_typespec (assembly
, type
);
2082 MonoGenericClass
*gclass
;
2083 gclass
= mono_metadata_lookup_generic_class (klass
, klass
->generic_container
->context
.class_inst
, TRUE
);
2084 encode_generic_class (assembly
, gclass
, &buf
);
2086 encode_type (assembly
, type
, &buf
);
2088 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2089 sigbuffer_free (&buf
);
2092 sigbuffer_free (&buf
);
2097 encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, MonoTypeEnum
*ret_type
)
2099 MONO_REQ_GC_UNSAFE_MODE
;
2101 char blob_size
[64];
2102 char *b
= blob_size
;
2105 guint32 idx
= 0, len
= 0, dummy
= 0;
2107 buf
= (char *)g_malloc (64);
2109 *ret_type
= MONO_TYPE_CLASS
;
2111 box_val
= (char*)&dummy
;
2113 box_val
= ((char*)val
) + sizeof (MonoObject
);
2114 *ret_type
= val
->vtable
->klass
->byval_arg
.type
;
2117 switch (*ret_type
) {
2118 case MONO_TYPE_BOOLEAN
:
2123 case MONO_TYPE_CHAR
:
2140 case MONO_TYPE_VALUETYPE
: {
2141 MonoClass
*klass
= val
->vtable
->klass
;
2143 if (klass
->enumtype
) {
2144 *ret_type
= mono_class_enum_basetype (klass
)->type
;
2146 } else if (mono_is_corlib_image (klass
->image
) && strcmp (klass
->name_space
, "System") == 0 && strcmp (klass
->name
, "DateTime") == 0) {
2149 g_error ("we can't encode valuetypes, we should have never reached this line");
2152 case MONO_TYPE_CLASS
:
2154 case MONO_TYPE_STRING
: {
2155 MonoString
*str
= (MonoString
*)val
;
2156 /* there is no signature */
2157 len
= str
->length
* 2;
2158 mono_metadata_encode_value (len
, b
, &b
);
2159 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2161 char *swapped
= g_malloc (2 * mono_string_length (str
));
2162 const char *p
= (const char*)mono_string_chars (str
);
2164 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
2165 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
2169 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
2175 case MONO_TYPE_GENERICINST
:
2176 *ret_type
= val
->vtable
->klass
->generic_class
->container_class
->byval_arg
.type
;
2179 g_error ("we don't encode constant type 0x%02x yet", *ret_type
);
2182 /* there is no signature */
2183 mono_metadata_encode_value (len
, b
, &b
);
2184 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2185 idx
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
2186 swap_with_size (blob_size
, box_val
, len
, 1);
2187 mono_image_add_stream_data (&assembly
->blob
, blob_size
, len
);
2189 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, box_val
, len
);
2197 encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
, MonoError
*error
)
2199 MONO_REQ_GC_UNSAFE_MODE
;
2201 mono_error_init (error
);
2207 sigbuffer_init (&buf
, 32);
2209 sigbuffer_add_value (&buf
, minfo
->type
);
2211 switch (minfo
->type
) {
2212 case MONO_NATIVE_BYVALTSTR
:
2213 case MONO_NATIVE_BYVALARRAY
:
2214 sigbuffer_add_value (&buf
, minfo
->count
);
2216 case MONO_NATIVE_LPARRAY
:
2217 if (minfo
->eltype
|| minfo
->has_size
) {
2218 sigbuffer_add_value (&buf
, minfo
->eltype
);
2219 if (minfo
->has_size
) {
2220 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? minfo
->param_num
: 0);
2221 sigbuffer_add_value (&buf
, minfo
->count
!= -1? minfo
->count
: 0);
2223 /* LAMESPEC: ElemMult is undocumented */
2224 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? 1: 0);
2228 case MONO_NATIVE_SAFEARRAY
:
2230 sigbuffer_add_value (&buf
, minfo
->eltype
);
2232 case MONO_NATIVE_CUSTOM
:
2234 str
= mono_string_to_utf8 (minfo
->guid
);
2236 sigbuffer_add_value (&buf
, len
);
2237 sigbuffer_add_mem (&buf
, str
, len
);
2240 sigbuffer_add_value (&buf
, 0);
2242 /* native type name */
2243 sigbuffer_add_value (&buf
, 0);
2244 /* custom marshaler type name */
2245 if (minfo
->marshaltype
|| minfo
->marshaltyperef
) {
2246 if (minfo
->marshaltyperef
) {
2247 MonoType
*marshaltype
= mono_reflection_type_get_handle ((MonoReflectionType
*)minfo
->marshaltyperef
, error
);
2248 if (!is_ok (error
)) {
2249 sigbuffer_free (&buf
);
2252 str
= type_get_fully_qualified_name (marshaltype
);
2254 str
= mono_string_to_utf8 (minfo
->marshaltype
);
2256 sigbuffer_add_value (&buf
, len
);
2257 sigbuffer_add_mem (&buf
, str
, len
);
2260 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
2261 sigbuffer_add_value (&buf
, 0);
2263 if (minfo
->mcookie
) {
2264 str
= mono_string_to_utf8 (minfo
->mcookie
);
2266 sigbuffer_add_value (&buf
, len
);
2267 sigbuffer_add_mem (&buf
, str
, len
);
2270 sigbuffer_add_value (&buf
, 0);
2276 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2277 sigbuffer_free (&buf
);
2282 mono_image_get_field_info (MonoReflectionFieldBuilder
*fb
, MonoDynamicImage
*assembly
, MonoError
*error
)
2284 MONO_REQ_GC_UNSAFE_MODE
;
2286 mono_error_init (error
);
2288 MonoDynamicTable
*table
;
2291 /* maybe this fixup should be done in the C# code */
2292 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
)
2293 fb
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
2294 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
2295 fb
->table_idx
= table
->next_idx
++;
2296 g_hash_table_insert (assembly
->field_to_table_idx
, fb
->handle
, GUINT_TO_POINTER (fb
->table_idx
));
2297 values
= table
->values
+ fb
->table_idx
* MONO_FIELD_SIZE
;
2298 values
[MONO_FIELD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, fb
->name
);
2299 values
[MONO_FIELD_FLAGS
] = fb
->attrs
;
2300 values
[MONO_FIELD_SIGNATURE
] = field_encode_signature (assembly
, fb
, error
);
2301 return_if_nok (error
);
2304 if (fb
->offset
!= -1) {
2305 table
= &assembly
->tables
[MONO_TABLE_FIELDLAYOUT
];
2307 alloc_table (table
, table
->rows
);
2308 values
= table
->values
+ table
->rows
* MONO_FIELD_LAYOUT_SIZE
;
2309 values
[MONO_FIELD_LAYOUT_FIELD
] = fb
->table_idx
;
2310 values
[MONO_FIELD_LAYOUT_OFFSET
] = fb
->offset
;
2312 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
) {
2313 MonoTypeEnum field_type
= (MonoTypeEnum
)0;
2314 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
2316 alloc_table (table
, table
->rows
);
2317 values
= table
->values
+ table
->rows
* MONO_CONSTANT_SIZE
;
2318 values
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_FIEDDEF
| (fb
->table_idx
<< MONO_HASCONSTANT_BITS
);
2319 values
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, fb
->def_value
, &field_type
);
2320 values
[MONO_CONSTANT_TYPE
] = field_type
;
2321 values
[MONO_CONSTANT_PADDING
] = 0;
2323 if (fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
2325 table
= &assembly
->tables
[MONO_TABLE_FIELDRVA
];
2327 alloc_table (table
, table
->rows
);
2328 values
= table
->values
+ table
->rows
* MONO_FIELD_RVA_SIZE
;
2329 values
[MONO_FIELD_RVA_FIELD
] = fb
->table_idx
;
2331 * We store it in the code section because it's simpler for now.
2334 if (mono_array_length (fb
->rva_data
) >= 10)
2335 stream_data_align (&assembly
->code
);
2336 rva_idx
= mono_image_add_stream_data (&assembly
->code
, mono_array_addr (fb
->rva_data
, char, 0), mono_array_length (fb
->rva_data
));
2338 rva_idx
= mono_image_add_stream_zero (&assembly
->code
, mono_class_value_size (fb
->handle
->parent
, NULL
));
2339 values
[MONO_FIELD_RVA_RVA
] = rva_idx
+ assembly
->text_rva
;
2341 if (fb
->marshal_info
) {
2342 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
2344 alloc_table (table
, table
->rows
);
2345 values
= table
->values
+ table
->rows
* MONO_FIELD_MARSHAL_SIZE
;
2346 values
[MONO_FIELD_MARSHAL_PARENT
] = (fb
->table_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_FIELDSREF
;
2347 values
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, fb
->marshal_info
, error
);
2348 return_if_nok (error
);
2353 property_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionPropertyBuilder
*fb
, MonoError
*error
)
2355 MONO_REQ_GC_UNSAFE_MODE
;
2357 mono_error_init (error
);
2360 guint32 nparams
= 0;
2361 MonoReflectionMethodBuilder
*mb
= fb
->get_method
;
2362 MonoReflectionMethodBuilder
*smb
= fb
->set_method
;
2365 if (mb
&& mb
->parameters
)
2366 nparams
= mono_array_length (mb
->parameters
);
2367 if (!mb
&& smb
&& smb
->parameters
)
2368 nparams
= mono_array_length (smb
->parameters
) - 1;
2369 sigbuffer_init (&buf
, 32);
2370 if (fb
->call_conv
& 0x20)
2371 sigbuffer_add_byte (&buf
, 0x28);
2373 sigbuffer_add_byte (&buf
, 0x08);
2374 sigbuffer_add_value (&buf
, nparams
);
2376 encode_reflection_type (assembly
, (MonoReflectionType
*)mb
->rtype
, &buf
, error
);
2379 for (i
= 0; i
< nparams
; ++i
) {
2380 MonoReflectionType
*pt
= mono_array_get (mb
->parameters
, MonoReflectionType
*, i
);
2381 encode_reflection_type (assembly
, pt
, &buf
, error
);
2385 } else if (smb
&& smb
->parameters
) {
2386 /* the property type is the last param */
2387 encode_reflection_type (assembly
, mono_array_get (smb
->parameters
, MonoReflectionType
*, nparams
), &buf
, error
);
2391 for (i
= 0; i
< nparams
; ++i
) {
2392 MonoReflectionType
*pt
= mono_array_get (smb
->parameters
, MonoReflectionType
*, i
);
2393 encode_reflection_type (assembly
, pt
, &buf
, error
);
2398 encode_reflection_type (assembly
, (MonoReflectionType
*)fb
->type
, &buf
, error
);
2403 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2404 sigbuffer_free (&buf
);
2407 sigbuffer_free (&buf
);
2412 mono_image_get_property_info (MonoReflectionPropertyBuilder
*pb
, MonoDynamicImage
*assembly
, MonoError
*error
)
2414 MONO_REQ_GC_UNSAFE_MODE
;
2416 mono_error_init (error
);
2418 MonoDynamicTable
*table
;
2420 guint num_methods
= 0;
2424 * we need to set things in the following tables:
2425 * PROPERTYMAP (info already filled in _get_type_info ())
2426 * PROPERTY (rows already preallocated in _get_type_info ())
2427 * METHOD (method info already done with the generic method code)
2431 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
2432 pb
->table_idx
= table
->next_idx
++;
2433 values
= table
->values
+ pb
->table_idx
* MONO_PROPERTY_SIZE
;
2434 values
[MONO_PROPERTY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
2435 values
[MONO_PROPERTY_FLAGS
] = pb
->attrs
;
2436 values
[MONO_PROPERTY_TYPE
] = property_encode_signature (assembly
, pb
, error
);
2437 return_if_nok (error
);
2440 /* FIXME: we still don't handle 'other' methods */
2441 if (pb
->get_method
) num_methods
++;
2442 if (pb
->set_method
) num_methods
++;
2444 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
2445 table
->rows
+= num_methods
;
2446 alloc_table (table
, table
->rows
);
2448 if (pb
->get_method
) {
2449 semaidx
= table
->next_idx
++;
2450 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2451 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_GETTER
;
2452 values
[MONO_METHOD_SEMA_METHOD
] = pb
->get_method
->table_idx
;
2453 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
2455 if (pb
->set_method
) {
2456 semaidx
= table
->next_idx
++;
2457 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2458 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_SETTER
;
2459 values
[MONO_METHOD_SEMA_METHOD
] = pb
->set_method
->table_idx
;
2460 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
2462 if (pb
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
) {
2463 MonoTypeEnum field_type
= (MonoTypeEnum
)0;
2464 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
2466 alloc_table (table
, table
->rows
);
2467 values
= table
->values
+ table
->rows
* MONO_CONSTANT_SIZE
;
2468 values
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_PROPERTY
| (pb
->table_idx
<< MONO_HASCONSTANT_BITS
);
2469 values
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, pb
->def_value
, &field_type
);
2470 values
[MONO_CONSTANT_TYPE
] = field_type
;
2471 values
[MONO_CONSTANT_PADDING
] = 0;
2476 mono_image_get_event_info (MonoReflectionEventBuilder
*eb
, MonoDynamicImage
*assembly
, MonoError
*error
)
2478 MONO_REQ_GC_UNSAFE_MODE
;
2480 MonoDynamicTable
*table
;
2482 guint num_methods
= 0;
2486 * we need to set things in the following tables:
2487 * EVENTMAP (info already filled in _get_type_info ())
2488 * EVENT (rows already preallocated in _get_type_info ())
2489 * METHOD (method info already done with the generic method code)
2492 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
2493 eb
->table_idx
= table
->next_idx
++;
2494 values
= table
->values
+ eb
->table_idx
* MONO_EVENT_SIZE
;
2495 values
[MONO_EVENT_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, eb
->name
);
2496 values
[MONO_EVENT_FLAGS
] = eb
->attrs
;
2497 MonoType
*ebtype
= mono_reflection_type_get_handle (eb
->type
, error
);
2498 return_if_nok (error
);
2499 values
[MONO_EVENT_TYPE
] = mono_image_typedef_or_ref (assembly
, ebtype
);
2502 * FIXME: we still don't handle 'other' methods
2504 if (eb
->add_method
) num_methods
++;
2505 if (eb
->remove_method
) num_methods
++;
2506 if (eb
->raise_method
) num_methods
++;
2508 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
2509 table
->rows
+= num_methods
;
2510 alloc_table (table
, table
->rows
);
2512 if (eb
->add_method
) {
2513 semaidx
= table
->next_idx
++;
2514 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2515 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_ADD_ON
;
2516 values
[MONO_METHOD_SEMA_METHOD
] = eb
->add_method
->table_idx
;
2517 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2519 if (eb
->remove_method
) {
2520 semaidx
= table
->next_idx
++;
2521 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2522 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_REMOVE_ON
;
2523 values
[MONO_METHOD_SEMA_METHOD
] = eb
->remove_method
->table_idx
;
2524 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2526 if (eb
->raise_method
) {
2527 semaidx
= table
->next_idx
++;
2528 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2529 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_FIRE
;
2530 values
[MONO_METHOD_SEMA_METHOD
] = eb
->raise_method
->table_idx
;
2531 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2536 encode_constraints (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
, MonoError
*error
)
2538 MONO_REQ_GC_UNSAFE_MODE
;
2540 mono_error_init (error
);
2542 MonoDynamicTable
*table
;
2543 guint32 num_constraints
, i
;
2547 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
2548 num_constraints
= gparam
->iface_constraints
?
2549 mono_array_length (gparam
->iface_constraints
) : 0;
2550 table
->rows
+= num_constraints
;
2551 if (gparam
->base_type
)
2553 alloc_table (table
, table
->rows
);
2555 if (gparam
->base_type
) {
2556 table_idx
= table
->next_idx
++;
2557 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2559 MonoType
*gpbasetype
= mono_reflection_type_get_handle (gparam
->base_type
, error
);
2560 return_if_nok (error
);
2561 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2562 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (assembly
, gpbasetype
);
2565 for (i
= 0; i
< num_constraints
; i
++) {
2566 MonoReflectionType
*constraint
= (MonoReflectionType
*)mono_array_get (
2567 gparam
->iface_constraints
, gpointer
, i
);
2569 table_idx
= table
->next_idx
++;
2570 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2572 MonoType
*constraint_type
= mono_reflection_type_get_handle (constraint
, error
);
2573 return_if_nok (error
);
2575 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2576 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (assembly
, constraint_type
);
2581 mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
)
2583 MONO_REQ_GC_UNSAFE_MODE
;
2585 GenericParamTableEntry
*entry
;
2588 * The GenericParam table must be sorted according to the `owner' field.
2589 * We need to do this sorting prior to writing the GenericParamConstraint
2590 * table, since we have to use the final GenericParam table indices there
2591 * and they must also be sorted.
2594 entry
= g_new0 (GenericParamTableEntry
, 1);
2595 entry
->owner
= owner
;
2596 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2597 MONO_GC_REGISTER_ROOT_IF_MOVING (entry
->gparam
, MONO_ROOT_SOURCE_REFLECTION
, "reflection generic parameter");
2598 entry
->gparam
= gparam
;
2600 g_ptr_array_add (assembly
->gen_params
, entry
);
2604 write_generic_param_entry (MonoDynamicImage
*assembly
, GenericParamTableEntry
*entry
, MonoError
*error
)
2606 MONO_REQ_GC_UNSAFE_MODE
;
2608 MonoDynamicTable
*table
;
2609 MonoGenericParam
*param
;
2613 mono_error_init (error
);
2615 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
2616 table_idx
= table
->next_idx
++;
2617 values
= table
->values
+ table_idx
* MONO_GENERICPARAM_SIZE
;
2619 MonoType
*gparam_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)entry
->gparam
, error
);
2620 return_val_if_nok (error
, FALSE
);
2622 param
= gparam_type
->data
.generic_param
;
2624 values
[MONO_GENERICPARAM_OWNER
] = entry
->owner
;
2625 values
[MONO_GENERICPARAM_FLAGS
] = entry
->gparam
->attrs
;
2626 values
[MONO_GENERICPARAM_NUMBER
] = mono_generic_param_num (param
);
2627 values
[MONO_GENERICPARAM_NAME
] = string_heap_insert (&assembly
->sheap
, mono_generic_param_info (param
)->name
);
2629 if (!mono_image_add_cattrs (assembly
, table_idx
, MONO_CUSTOM_ATTR_GENERICPAR
, entry
->gparam
->cattrs
, error
))
2632 encode_constraints (entry
->gparam
, table_idx
, assembly
, error
);
2633 return_val_if_nok (error
, FALSE
);
2639 resolution_scope_from_image (MonoDynamicImage
*assembly
, MonoImage
*image
)
2641 MONO_REQ_GC_UNSAFE_MODE
;
2643 MonoDynamicTable
*table
;
2646 guint32 cols
[MONO_ASSEMBLY_SIZE
];
2650 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, image
))))
2653 if (assembly_is_dynamic (image
->assembly
) && (image
->assembly
== assembly
->image
.assembly
)) {
2654 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
2655 token
= table
->next_idx
++;
2657 alloc_table (table
, table
->rows
);
2658 values
= table
->values
+ token
* MONO_MODULEREF_SIZE
;
2659 values
[MONO_MODULEREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->module_name
);
2661 token
<<= MONO_RESOLUTION_SCOPE_BITS
;
2662 token
|= MONO_RESOLUTION_SCOPE_MODULEREF
;
2663 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2668 if (assembly_is_dynamic (image
->assembly
))
2670 memset (cols
, 0, sizeof (cols
));
2672 /* image->assembly->image is the manifest module */
2673 image
= image
->assembly
->image
;
2674 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_ASSEMBLY
], 0, cols
, MONO_ASSEMBLY_SIZE
);
2677 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLYREF
];
2678 token
= table
->next_idx
++;
2680 alloc_table (table
, table
->rows
);
2681 values
= table
->values
+ token
* MONO_ASSEMBLYREF_SIZE
;
2682 values
[MONO_ASSEMBLYREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->assembly_name
);
2683 values
[MONO_ASSEMBLYREF_MAJOR_VERSION
] = cols
[MONO_ASSEMBLY_MAJOR_VERSION
];
2684 values
[MONO_ASSEMBLYREF_MINOR_VERSION
] = cols
[MONO_ASSEMBLY_MINOR_VERSION
];
2685 values
[MONO_ASSEMBLYREF_BUILD_NUMBER
] = cols
[MONO_ASSEMBLY_BUILD_NUMBER
];
2686 values
[MONO_ASSEMBLYREF_REV_NUMBER
] = cols
[MONO_ASSEMBLY_REV_NUMBER
];
2687 values
[MONO_ASSEMBLYREF_FLAGS
] = 0;
2688 values
[MONO_ASSEMBLYREF_CULTURE
] = 0;
2689 values
[MONO_ASSEMBLYREF_HASH_VALUE
] = 0;
2691 if (strcmp ("", image
->assembly
->aname
.culture
)) {
2692 values
[MONO_ASSEMBLYREF_CULTURE
] = string_heap_insert (&assembly
->sheap
,
2693 image
->assembly
->aname
.culture
);
2696 if ((pubkey
= mono_image_get_public_key (image
, &publen
))) {
2697 guchar pubtoken
[9];
2699 mono_digest_get_public_token (pubtoken
+ 1, (guchar
*)pubkey
, publen
);
2700 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = mono_image_add_stream_data (&assembly
->blob
, (char*)pubtoken
, 9);
2702 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = 0;
2704 token
<<= MONO_RESOLUTION_SCOPE_BITS
;
2705 token
|= MONO_RESOLUTION_SCOPE_ASSEMBLYREF
;
2706 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2711 create_typespec (MonoDynamicImage
*assembly
, MonoType
*type
)
2713 MONO_REQ_GC_NEUTRAL_MODE
;
2715 MonoDynamicTable
*table
;
2720 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, type
))))
2723 sigbuffer_init (&buf
, 32);
2724 switch (type
->type
) {
2725 case MONO_TYPE_FNPTR
:
2727 case MONO_TYPE_SZARRAY
:
2728 case MONO_TYPE_ARRAY
:
2730 case MONO_TYPE_MVAR
:
2731 case MONO_TYPE_GENERICINST
:
2732 encode_type (assembly
, type
, &buf
);
2734 case MONO_TYPE_CLASS
:
2735 case MONO_TYPE_VALUETYPE
: {
2736 MonoClass
*k
= mono_class_from_mono_type (type
);
2737 if (!k
|| !k
->generic_container
) {
2738 sigbuffer_free (&buf
);
2741 encode_type (assembly
, type
, &buf
);
2745 sigbuffer_free (&buf
);
2749 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
2750 if (assembly
->save
) {
2751 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2752 alloc_table (table
, table
->rows
+ 1);
2753 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
2754 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
2756 sigbuffer_free (&buf
);
2758 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
2759 g_hash_table_insert (assembly
->typespec
, type
, GUINT_TO_POINTER(token
));
2765 mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
)
2767 MONO_REQ_GC_UNSAFE_MODE
;
2769 MonoDynamicTable
*table
;
2771 guint32 token
, scope
, enclosing
;
2774 /* if the type requires a typespec, we must try that first*/
2775 if (try_typespec
&& (token
= create_typespec (assembly
, type
)))
2777 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typeref
, type
));
2780 klass
= mono_class_from_mono_type (type
);
2782 klass
= mono_class_from_mono_type (type
);
2785 * If it's in the same module and not a generic type parameter:
2787 if ((klass
->image
== &assembly
->image
) && (type
->type
!= MONO_TYPE_VAR
) &&
2788 (type
->type
!= MONO_TYPE_MVAR
)) {
2789 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mono_class_get_ref_info (klass
);
2790 token
= MONO_TYPEDEFORREF_TYPEDEF
| (tb
->table_idx
<< MONO_TYPEDEFORREF_BITS
);
2791 register_dyn_token (assembly
, token
, (MonoObject
*)mono_class_get_ref_info (klass
));
2795 if (klass
->nested_in
) {
2796 enclosing
= mono_image_typedef_or_ref_full (assembly
, &klass
->nested_in
->byval_arg
, FALSE
);
2797 /* get the typeref idx of the enclosing type */
2798 enclosing
>>= MONO_TYPEDEFORREF_BITS
;
2799 scope
= (enclosing
<< MONO_RESOLUTION_SCOPE_BITS
) | MONO_RESOLUTION_SCOPE_TYPEREF
;
2801 scope
= resolution_scope_from_image (assembly
, klass
->image
);
2803 table
= &assembly
->tables
[MONO_TABLE_TYPEREF
];
2804 if (assembly
->save
) {
2805 alloc_table (table
, table
->rows
+ 1);
2806 values
= table
->values
+ table
->next_idx
* MONO_TYPEREF_SIZE
;
2807 values
[MONO_TYPEREF_SCOPE
] = scope
;
2808 values
[MONO_TYPEREF_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
2809 values
[MONO_TYPEREF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
2811 token
= MONO_TYPEDEFORREF_TYPEREF
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
); /* typeref */
2812 g_hash_table_insert (assembly
->typeref
, type
, GUINT_TO_POINTER(token
));
2814 register_dyn_token (assembly
, token
, (MonoObject
*)mono_class_get_ref_info (klass
));
2819 * Despite the name, we handle also TypeSpec (with the above helper).
2822 mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
)
2824 return mono_image_typedef_or_ref_full (assembly
, type
, TRUE
);
2827 #ifndef DISABLE_REFLECTION_EMIT
2829 mono_image_add_memberef_row (MonoDynamicImage
*assembly
, guint32 parent
, const char *name
, guint32 sig
)
2831 MONO_REQ_GC_NEUTRAL_MODE
;
2833 MonoDynamicTable
*table
;
2835 guint32 token
, pclass
;
2837 switch (parent
& MONO_TYPEDEFORREF_MASK
) {
2838 case MONO_TYPEDEFORREF_TYPEREF
:
2839 pclass
= MONO_MEMBERREF_PARENT_TYPEREF
;
2841 case MONO_TYPEDEFORREF_TYPESPEC
:
2842 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
2844 case MONO_TYPEDEFORREF_TYPEDEF
:
2845 pclass
= MONO_MEMBERREF_PARENT_TYPEDEF
;
2848 g_warning ("unknown typeref or def token 0x%08x for %s", parent
, name
);
2851 /* extract the index */
2852 parent
>>= MONO_TYPEDEFORREF_BITS
;
2854 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2856 if (assembly
->save
) {
2857 alloc_table (table
, table
->rows
+ 1);
2858 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2859 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
2860 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2861 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2864 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2871 * Insert a memberef row into the metadata: the token that point to the memberref
2872 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2873 * mono_image_get_fieldref_token()).
2874 * The sig param is an index to an already built signature.
2877 mono_image_get_memberref_token (MonoDynamicImage
*assembly
, MonoType
*type
, const char *name
, guint32 sig
)
2879 MONO_REQ_GC_NEUTRAL_MODE
;
2881 guint32 parent
= mono_image_typedef_or_ref (assembly
, type
);
2882 return mono_image_add_memberef_row (assembly
, parent
, name
, sig
);
2887 mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
)
2889 MONO_REQ_GC_NEUTRAL_MODE
;
2892 MonoMethodSignature
*sig
;
2894 create_typespec
= create_typespec
&& method
->is_generic
&& method
->klass
->image
!= &assembly
->image
;
2896 if (create_typespec
) {
2897 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1)));
2902 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2903 if (token
&& !create_typespec
)
2906 g_assert (!method
->is_inflated
);
2909 * A methodref signature can't contain an unmanaged calling convention.
2911 sig
= mono_metadata_signature_dup (mono_method_signature (method
));
2912 if ((sig
->call_convention
!= MONO_CALL_DEFAULT
) && (sig
->call_convention
!= MONO_CALL_VARARG
))
2913 sig
->call_convention
= MONO_CALL_DEFAULT
;
2914 token
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
,
2915 method
->name
, method_encode_signature (assembly
, sig
));
2917 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2920 if (create_typespec
) {
2921 MonoDynamicTable
*table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2922 g_assert (mono_metadata_token_table (token
) == MONO_TABLE_MEMBERREF
);
2923 token
= (mono_metadata_token_index (token
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2925 if (assembly
->save
) {
2928 alloc_table (table
, table
->rows
+ 1);
2929 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2930 values
[MONO_METHODSPEC_METHOD
] = token
;
2931 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_sig (assembly
, &mono_method_get_generic_container (method
)->context
);
2934 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2936 /*methodspec and memberef tokens are diferent, */
2937 g_hash_table_insert (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1), GUINT_TO_POINTER (token
));
2944 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
, MonoError
*error
)
2946 guint32 token
, parent
, sig
;
2947 ReflectionMethodBuilder rmb
;
2948 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)method
->type
;
2950 mono_error_init (error
);
2951 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2955 if (!reflection_methodbuilder_from_method_builder (&rmb
, method
, error
))
2959 * A methodref signature can't contain an unmanaged calling convention.
2960 * Since some flags are encoded as part of call_conv, we need to check against it.
2962 if ((rmb
.call_conv
& ~0x60) != MONO_CALL_DEFAULT
&& (rmb
.call_conv
& ~0x60) != MONO_CALL_VARARG
)
2963 rmb
.call_conv
= (rmb
.call_conv
& 0x60) | MONO_CALL_DEFAULT
;
2965 sig
= method_builder_encode_signature (assembly
, &rmb
, error
);
2966 return_val_if_nok (error
, 0);
2968 if (tb
->generic_params
) {
2969 parent
= create_generic_typespec (assembly
, tb
, error
);
2970 return_val_if_nok (error
, 0);
2972 MonoType
*t
= mono_reflection_type_get_handle ((MonoReflectionType
*)rmb
.type
, error
);
2973 return_val_if_nok (error
, 0);
2975 parent
= mono_image_typedef_or_ref (assembly
, t
);
2978 char *name
= mono_string_to_utf8 (method
->name
);
2980 token
= mono_image_add_memberef_row (assembly
, parent
, name
, sig
);
2983 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2989 mono_image_get_varargs_method_token (MonoDynamicImage
*assembly
, guint32 original
,
2990 const gchar
*name
, guint32 sig
)
2992 MonoDynamicTable
*table
;
2996 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2998 if (assembly
->save
) {
2999 alloc_table (table
, table
->rows
+ 1);
3000 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
3001 values
[MONO_MEMBERREF_CLASS
] = original
;
3002 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
3003 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
3006 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
3013 encode_generic_method_definition_sig (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
3017 guint32 nparams
= mono_array_length (mb
->generic_params
);
3020 if (!assembly
->save
)
3023 sigbuffer_init (&buf
, 32);
3025 sigbuffer_add_value (&buf
, 0xa);
3026 sigbuffer_add_value (&buf
, nparams
);
3028 for (i
= 0; i
< nparams
; i
++) {
3029 sigbuffer_add_value (&buf
, MONO_TYPE_MVAR
);
3030 sigbuffer_add_value (&buf
, i
);
3033 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
3034 sigbuffer_free (&buf
);
3039 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, MonoError
*error
)
3041 MonoDynamicTable
*table
;
3043 guint32 token
, mtoken
= 0;
3045 mono_error_init (error
);
3046 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->methodspec
, mb
));
3050 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
3052 mtoken
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
, error
);
3053 if (!mono_error_ok (error
))
3056 switch (mono_metadata_token_table (mtoken
)) {
3057 case MONO_TABLE_MEMBERREF
:
3058 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
3060 case MONO_TABLE_METHOD
:
3061 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
3064 g_assert_not_reached ();
3067 if (assembly
->save
) {
3068 alloc_table (table
, table
->rows
+ 1);
3069 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
3070 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
3071 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_definition_sig (assembly
, mb
);
3074 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
3077 mono_g_hash_table_insert (assembly
->methodspec
, mb
, GUINT_TO_POINTER(token
));
3082 mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_methodspec
, MonoError
*error
)
3086 mono_error_init (error
);
3088 if (mb
->generic_params
&& create_methodspec
)
3089 return mono_image_get_methodspec_token_for_generic_method_definition (assembly
, mb
, error
);
3091 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, mb
));
3095 token
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
, error
);
3096 if (!mono_error_ok (error
))
3098 mono_g_hash_table_insert (assembly
->handleref_managed
, mb
, GUINT_TO_POINTER(token
));
3103 mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*mb
, MonoError
*error
)
3105 guint32 token
, parent
, sig
;
3106 ReflectionMethodBuilder rmb
;
3108 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
3110 mono_error_init (error
);
3112 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, mb
));
3116 if (!reflection_methodbuilder_from_ctor_builder (&rmb
, mb
, error
))
3119 if (tb
->generic_params
) {
3120 parent
= create_generic_typespec (assembly
, tb
, error
);
3121 return_val_if_nok (error
, 0);
3123 MonoType
* type
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
, error
);
3124 return_val_if_nok (error
, 0);
3125 parent
= mono_image_typedef_or_ref (assembly
, type
);
3128 name
= mono_string_to_utf8 (rmb
.name
);
3129 sig
= method_builder_encode_signature (assembly
, &rmb
, error
);
3130 return_val_if_nok (error
, 0);
3132 token
= mono_image_add_memberef_row (assembly
, parent
, name
, sig
);
3135 mono_g_hash_table_insert (assembly
->handleref_managed
, mb
, GUINT_TO_POINTER(token
));
3141 is_field_on_inst (MonoClassField
*field
)
3143 return (field
->parent
->generic_class
&& field
->parent
->generic_class
->is_dynamic
&& ((MonoDynamicGenericClass
*)field
->parent
->generic_class
)->fields
);
3147 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3150 get_field_on_inst_generic_type (MonoClassField
*field
)
3152 MonoClass
*klass
, *gtd
;
3153 MonoDynamicGenericClass
*dgclass
;
3156 g_assert (is_field_on_inst (field
));
3158 dgclass
= (MonoDynamicGenericClass
*)field
->parent
->generic_class
;
3160 if (field
>= dgclass
->fields
&& field
- dgclass
->fields
< dgclass
->count_fields
) {
3161 field_index
= field
- dgclass
->fields
;
3162 return dgclass
->field_generic_types
[field_index
];
3165 klass
= field
->parent
;
3166 gtd
= klass
->generic_class
->container_class
;
3168 if (field
>= klass
->fields
&& field
- klass
->fields
< klass
->field
.count
) {
3169 field_index
= field
- klass
->fields
;
3170 return gtd
->fields
[field_index
].type
;
3173 g_assert_not_reached ();
3177 #ifndef DISABLE_REFLECTION_EMIT
3179 mono_image_get_fieldref_token (MonoDynamicImage
*assembly
, MonoObject
*f
, MonoClassField
*field
)
3185 g_assert (field
->parent
);
3187 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, f
));
3191 if (field
->parent
->generic_class
&& field
->parent
->generic_class
->container_class
&& field
->parent
->generic_class
->container_class
->fields
) {
3192 int index
= field
- field
->parent
->fields
;
3193 type
= mono_field_get_type (&field
->parent
->generic_class
->container_class
->fields
[index
]);
3195 if (is_field_on_inst (field
))
3196 type
= get_field_on_inst_generic_type (field
);
3198 type
= mono_field_get_type (field
);
3200 token
= mono_image_get_memberref_token (assembly
, &field
->parent
->byval_arg
,
3201 mono_field_get_name (field
),
3202 fieldref_encode_signature (assembly
, field
->parent
->image
, type
));
3203 mono_g_hash_table_insert (assembly
->handleref_managed
, f
, GUINT_TO_POINTER(token
));
3208 mono_image_get_field_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionFieldOnTypeBuilderInst
*f
, MonoError
*error
)
3212 MonoGenericClass
*gclass
;
3216 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, f
));
3219 if (is_sre_field_builder (mono_object_class (f
->fb
))) {
3220 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)f
->fb
;
3221 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)f
->inst
, error
);
3222 return_val_if_nok (error
, 0);
3223 klass
= mono_class_from_mono_type (type
);
3224 gclass
= type
->data
.generic_class
;
3225 g_assert (gclass
->is_dynamic
);
3227 guint32 sig_token
= field_encode_signature (assembly
, fb
, error
);
3228 return_val_if_nok (error
, 0);
3229 name
= mono_string_to_utf8 (fb
->name
);
3230 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig_token
);
3232 } else if (is_sr_mono_field (mono_object_class (f
->fb
))) {
3234 MonoClassField
*field
= ((MonoReflectionField
*)f
->fb
)->field
;
3236 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)f
->inst
, error
);
3237 return_val_if_nok (error
, 0);
3238 klass
= mono_class_from_mono_type (type
);
3240 sig
= fieldref_encode_signature (assembly
, field
->parent
->image
, field
->type
);
3241 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, field
->name
, sig
);
3243 char *name
= mono_type_get_full_name (mono_object_class (f
->fb
));
3244 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name
);
3247 mono_g_hash_table_insert (assembly
->handleref_managed
, f
, GUINT_TO_POINTER (token
));
3252 mono_image_get_ctor_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionCtorOnTypeBuilderInst
*c
, gboolean create_methodspec
, MonoError
*error
)
3256 MonoGenericClass
*gclass
;
3259 mono_error_init (error
);
3261 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3263 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, c
));
3267 if (is_sre_ctor_builder (mono_object_class (c
->cb
))) {
3268 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)c
->cb
;
3269 ReflectionMethodBuilder rmb
;
3272 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)c
->inst
, error
);
3273 return_val_if_nok (error
, 0);
3274 klass
= mono_class_from_mono_type (type
);
3276 gclass
= type
->data
.generic_class
;
3277 g_assert (gclass
->is_dynamic
);
3279 if (!reflection_methodbuilder_from_ctor_builder (&rmb
, cb
, error
))
3282 sig
= method_builder_encode_signature (assembly
, &rmb
, error
);
3283 return_val_if_nok (error
, 0);
3285 name
= mono_string_to_utf8 (rmb
.name
);
3287 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
3289 } else if (is_sr_mono_cmethod (mono_object_class (c
->cb
))) {
3290 MonoMethod
*mm
= ((MonoReflectionMethod
*)c
->cb
)->method
;
3292 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)c
->inst
, error
);
3293 return_val_if_nok (error
, 0);
3294 klass
= mono_class_from_mono_type (type
);
3296 sig
= method_encode_signature (assembly
, mono_method_signature (mm
));
3297 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, mm
->name
, sig
);
3299 char *name
= mono_type_get_full_name (mono_object_class (c
->cb
));
3300 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name
);
3304 mono_g_hash_table_insert (assembly
->handleref_managed
, c
, GUINT_TO_POINTER (token
));
3309 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst
*m
, MonoError
*error
)
3312 MonoGenericContext tmp_context
;
3313 MonoType
**type_argv
;
3314 MonoGenericInst
*ginst
;
3315 MonoMethod
*method
, *inflated
;
3318 mono_error_init (error
);
3320 init_type_builder_generics ((MonoObject
*)m
->inst
);
3322 method
= inflate_method (m
->inst
, (MonoObject
*)m
->mb
, error
);
3323 return_val_if_nok (error
, NULL
);
3325 klass
= method
->klass
;
3327 if (m
->method_args
== NULL
)
3330 if (method
->is_inflated
)
3331 method
= ((MonoMethodInflated
*) method
)->declaring
;
3333 count
= mono_array_length (m
->method_args
);
3335 type_argv
= g_new0 (MonoType
*, count
);
3336 for (i
= 0; i
< count
; i
++) {
3337 MonoReflectionType
*garg
= (MonoReflectionType
*)mono_array_get (m
->method_args
, gpointer
, i
);
3338 type_argv
[i
] = mono_reflection_type_get_handle (garg
, error
);
3339 return_val_if_nok (error
, NULL
);
3341 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
3344 tmp_context
.class_inst
= klass
->generic_class
? klass
->generic_class
->context
.class_inst
: NULL
;
3345 tmp_context
.method_inst
= ginst
;
3347 inflated
= mono_class_inflate_generic_method_checked (method
, &tmp_context
, error
);
3348 mono_error_assert_ok (error
);
3353 mono_image_get_method_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionMethodOnTypeBuilderInst
*m
, gboolean create_methodspec
, MonoError
*error
)
3355 guint32 sig
, token
= 0;
3359 mono_error_init (error
);
3361 if (m
->method_args
) {
3362 MonoMethod
*inflated
;
3364 inflated
= mono_reflection_method_on_tb_inst_get_handle (m
, error
);
3365 return_val_if_nok (error
, 0);
3367 if (create_methodspec
)
3368 token
= mono_image_get_methodspec_token (assembly
, inflated
);
3370 token
= mono_image_get_inflated_method_token (assembly
, inflated
);
3374 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, m
));
3378 if (is_sre_method_builder (mono_object_class (m
->mb
))) {
3379 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)m
->mb
;
3380 MonoGenericClass
*gclass
;
3381 ReflectionMethodBuilder rmb
;
3384 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)m
->inst
, error
);
3385 return_val_if_nok (error
, 0);
3386 klass
= mono_class_from_mono_type (type
);
3387 gclass
= type
->data
.generic_class
;
3388 g_assert (gclass
->is_dynamic
);
3390 if (!reflection_methodbuilder_from_method_builder (&rmb
, mb
, error
))
3393 sig
= method_builder_encode_signature (assembly
, &rmb
, error
);
3394 return_val_if_nok (error
, 0);
3396 name
= mono_string_to_utf8 (rmb
.name
);
3398 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
3400 } else if (is_sr_mono_method (mono_object_class (m
->mb
))) {
3401 MonoMethod
*mm
= ((MonoReflectionMethod
*)m
->mb
)->method
;
3403 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)m
->inst
, error
);
3404 return_val_if_nok (error
, 0);
3405 klass
= mono_class_from_mono_type (type
);
3407 sig
= method_encode_signature (assembly
, mono_method_signature (mm
));
3408 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, mm
->name
, sig
);
3410 char *name
= mono_type_get_full_name (mono_object_class (m
->mb
));
3411 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name
);
3414 mono_g_hash_table_insert (assembly
->handleref_managed
, m
, GUINT_TO_POINTER (token
));
3419 encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
)
3423 guint32 nparams
= context
->method_inst
->type_argc
;
3426 if (!assembly
->save
)
3429 sigbuffer_init (&buf
, 32);
3431 * FIXME: vararg, explicit_this, differenc call_conv values...
3433 sigbuffer_add_value (&buf
, 0xa); /* FIXME FIXME FIXME */
3434 sigbuffer_add_value (&buf
, nparams
);
3436 for (i
= 0; i
< nparams
; i
++)
3437 encode_type (assembly
, context
->method_inst
->type_argv
[i
], &buf
);
3439 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
3440 sigbuffer_free (&buf
);
3445 method_encode_methodspec (MonoDynamicImage
*assembly
, MonoMethod
*method
)
3447 MonoDynamicTable
*table
;
3449 guint32 token
, mtoken
= 0, sig
;
3450 MonoMethodInflated
*imethod
;
3451 MonoMethod
*declaring
;
3453 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
3455 g_assert (method
->is_inflated
);
3456 imethod
= (MonoMethodInflated
*) method
;
3457 declaring
= imethod
->declaring
;
3459 sig
= method_encode_signature (assembly
, mono_method_signature (declaring
));
3460 mtoken
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
, declaring
->name
, sig
);
3462 if (!mono_method_signature (declaring
)->generic_param_count
)
3465 switch (mono_metadata_token_table (mtoken
)) {
3466 case MONO_TABLE_MEMBERREF
:
3467 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
3469 case MONO_TABLE_METHOD
:
3470 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
3473 g_assert_not_reached ();
3476 sig
= encode_generic_method_sig (assembly
, mono_method_get_context (method
));
3478 if (assembly
->save
) {
3479 alloc_table (table
, table
->rows
+ 1);
3480 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
3481 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
3482 values
[MONO_METHODSPEC_SIGNATURE
] = sig
;
3485 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
3492 mono_image_get_methodspec_token (MonoDynamicImage
*assembly
, MonoMethod
*method
)
3494 MonoMethodInflated
*imethod
;
3497 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
3501 g_assert (method
->is_inflated
);
3502 imethod
= (MonoMethodInflated
*) method
;
3504 if (mono_method_signature (imethod
->declaring
)->generic_param_count
) {
3505 token
= method_encode_methodspec (assembly
, method
);
3507 guint32 sig
= method_encode_signature (
3508 assembly
, mono_method_signature (imethod
->declaring
));
3509 token
= mono_image_get_memberref_token (
3510 assembly
, &method
->klass
->byval_arg
, method
->name
, sig
);
3513 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
3518 mono_image_get_inflated_method_token (MonoDynamicImage
*assembly
, MonoMethod
*m
)
3520 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) m
;
3523 sig
= method_encode_signature (assembly
, mono_method_signature (imethod
->declaring
));
3524 token
= mono_image_get_memberref_token (
3525 assembly
, &m
->klass
->byval_arg
, m
->name
, sig
);
3531 create_generic_typespec (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
, MonoError
*error
)
3533 MonoDynamicTable
*table
;
3542 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3543 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3544 * Because of this, we must not insert it into the `typeref' hash table.
3546 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
, error
);
3547 return_val_if_nok (error
, 0);
3548 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, type
));
3552 sigbuffer_init (&buf
, 32);
3554 g_assert (tb
->generic_params
);
3555 klass
= mono_class_from_mono_type (type
);
3557 if (tb
->generic_container
)
3558 mono_reflection_create_generic_class (tb
);
3560 sigbuffer_add_value (&buf
, MONO_TYPE_GENERICINST
);
3561 g_assert (klass
->generic_container
);
3562 sigbuffer_add_value (&buf
, klass
->byval_arg
.type
);
3563 sigbuffer_add_value (&buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
3565 count
= mono_array_length (tb
->generic_params
);
3566 sigbuffer_add_value (&buf
, count
);
3567 for (i
= 0; i
< count
; i
++) {
3568 MonoReflectionGenericParam
*gparam
;
3570 gparam
= mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
);
3571 MonoType
*gparam_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)gparam
, error
);
3575 encode_type (assembly
, gparam_type
, &buf
);
3578 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
3580 if (assembly
->save
) {
3581 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
3582 alloc_table (table
, table
->rows
+ 1);
3583 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
3584 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
3586 sigbuffer_free (&buf
);
3588 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
3589 g_hash_table_insert (assembly
->typespec
, type
, GUINT_TO_POINTER(token
));
3593 sigbuffer_free (&buf
);
3598 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3601 add_custom_modifiers (MonoDynamicImage
*assembly
, MonoType
*type
, MonoArray
*modreq
, MonoArray
*modopt
, MonoError
*error
)
3603 int i
, count
, len
, pos
;
3606 mono_error_init (error
);
3610 count
+= mono_array_length (modreq
);
3612 count
+= mono_array_length (modopt
);
3615 return mono_metadata_type_dup (NULL
, type
);
3617 len
= MONO_SIZEOF_TYPE
+ ((gint32
)count
) * sizeof (MonoCustomMod
);
3618 t
= (MonoType
*)g_malloc (len
);
3619 memcpy (t
, type
, MONO_SIZEOF_TYPE
);
3621 t
->num_mods
= count
;
3624 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
3625 MonoType
*mod
= mono_type_array_get_and_resolve (modreq
, i
, error
);
3628 t
->modifiers
[pos
].required
= 1;
3629 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
);
3634 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
3635 MonoType
*mod
= mono_type_array_get_and_resolve (modopt
, i
, error
);
3638 t
->modifiers
[pos
].required
= 0;
3639 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
);
3651 init_type_builder_generics (MonoObject
*type
)
3653 MonoReflectionTypeBuilder
*tb
;
3655 if (!is_sre_type_builder(mono_object_class (type
)))
3657 tb
= (MonoReflectionTypeBuilder
*)type
;
3659 if (tb
&& tb
->generic_container
)
3660 mono_reflection_create_generic_class (tb
);
3664 mono_image_get_generic_field_token (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
, MonoError
*error
)
3666 MonoDynamicTable
*table
;
3667 MonoType
*custom
= NULL
, *type
;
3669 guint32 token
, pclass
, parent
, sig
;
3672 mono_error_init (error
);
3674 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, fb
));
3678 MonoType
*typeb
= mono_reflection_type_get_handle (fb
->typeb
, error
);
3679 return_val_if_nok (error
, 0);
3680 /* FIXME: is this call necessary? */
3681 mono_class_from_mono_type (typeb
);
3683 /*FIXME this is one more layer of ugliness due how types are created.*/
3684 init_type_builder_generics (fb
->type
);
3686 /* fb->type does not include the custom modifiers */
3687 /* FIXME: We should do this in one place when a fieldbuilder is created */
3688 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
, error
);
3689 return_val_if_nok (error
, 0);
3691 if (fb
->modreq
|| fb
->modopt
) {
3692 type
= custom
= add_custom_modifiers (assembly
, type
, fb
->modreq
, fb
->modopt
, error
);
3693 return_val_if_nok (error
, 0);
3696 sig
= fieldref_encode_signature (assembly
, NULL
, type
);
3699 parent
= create_generic_typespec (assembly
, (MonoReflectionTypeBuilder
*) fb
->typeb
, error
);
3700 return_val_if_nok (error
, 0);
3701 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_TYPEDEFORREF_TYPESPEC
);
3703 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
3704 parent
>>= MONO_TYPEDEFORREF_BITS
;
3706 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
3708 name
= mono_string_to_utf8 (fb
->name
);
3710 if (assembly
->save
) {
3711 alloc_table (table
, table
->rows
+ 1);
3712 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
3713 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
3714 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
3715 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
3718 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
3720 mono_g_hash_table_insert (assembly
->handleref_managed
, fb
, GUINT_TO_POINTER(token
));
3726 mono_reflection_encode_sighelper (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
, MonoError
*error
)
3732 mono_error_init (error
);
3734 if (!assembly
->save
)
3737 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3738 g_assert (helper
->type
== 2);
3740 if (helper
->arguments
)
3741 nargs
= mono_array_length (helper
->arguments
);
3745 sigbuffer_init (&buf
, 32);
3747 /* Encode calling convention */
3748 /* Change Any to Standard */
3749 if ((helper
->call_conv
& 0x03) == 0x03)
3750 helper
->call_conv
= 0x01;
3751 /* explicit_this implies has_this */
3752 if (helper
->call_conv
& 0x40)
3753 helper
->call_conv
&= 0x20;
3755 if (helper
->call_conv
== 0) { /* Unmanaged */
3756 idx
= helper
->unmanaged_call_conv
- 1;
3759 idx
= helper
->call_conv
& 0x60; /* has_this + explicit_this */
3760 if (helper
->call_conv
& 0x02) /* varargs */
3764 sigbuffer_add_byte (&buf
, idx
);
3765 sigbuffer_add_value (&buf
, nargs
);
3766 encode_reflection_type (assembly
, helper
->return_type
, &buf
, error
);
3769 for (i
= 0; i
< nargs
; ++i
) {
3770 MonoArray
*modreqs
= NULL
;
3771 MonoArray
*modopts
= NULL
;
3772 MonoReflectionType
*pt
;
3774 if (helper
->modreqs
&& (i
< mono_array_length (helper
->modreqs
)))
3775 modreqs
= mono_array_get (helper
->modreqs
, MonoArray
*, i
);
3776 if (helper
->modopts
&& (i
< mono_array_length (helper
->modopts
)))
3777 modopts
= mono_array_get (helper
->modopts
, MonoArray
*, i
);
3779 encode_custom_modifiers (assembly
, modreqs
, modopts
, &buf
, error
);
3782 pt
= mono_array_get (helper
->arguments
, MonoReflectionType
*, i
);
3783 encode_reflection_type (assembly
, pt
, &buf
, error
);
3787 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
3788 sigbuffer_free (&buf
);
3792 sigbuffer_free (&buf
);
3797 mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
, MonoError
*error
)
3800 MonoDynamicTable
*table
;
3803 mono_error_init (error
);
3805 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
3806 idx
= table
->next_idx
++;
3808 alloc_table (table
, table
->rows
);
3809 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
3811 values
[MONO_STAND_ALONE_SIGNATURE
] =
3812 mono_reflection_encode_sighelper (assembly
, helper
, error
);
3813 return_val_if_nok (error
, 0);
3819 reflection_cc_to_file (int call_conv
) {
3820 switch (call_conv
& 0x3) {
3822 case 1: return MONO_CALL_DEFAULT
;
3823 case 2: return MONO_CALL_VARARG
;
3825 g_assert_not_reached ();
3829 #endif /* !DISABLE_REFLECTION_EMIT */
3833 MonoMethodSignature
*sig
;
3838 #ifndef DISABLE_REFLECTION_EMIT
3840 mono_image_get_array_token (MonoDynamicImage
*assembly
, MonoReflectionArrayMethod
*m
, MonoError
*error
)
3845 MonoMethodSignature
*sig
;
3846 ArrayMethod
*am
= NULL
;
3849 mono_error_init (error
);
3851 nparams
= mono_array_length (m
->parameters
);
3852 sig
= (MonoMethodSignature
*)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE
+ sizeof (MonoType
*) * nparams
);
3854 sig
->sentinelpos
= -1;
3855 sig
->call_convention
= reflection_cc_to_file (m
->call_conv
);
3856 sig
->param_count
= nparams
;
3858 sig
->ret
= mono_reflection_type_get_handle (m
->ret
, error
);
3862 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
3864 mtype
= mono_reflection_type_get_handle (m
->parent
, error
);
3868 for (i
= 0; i
< nparams
; ++i
) {
3869 sig
->params
[i
] = mono_type_array_get_and_resolve (m
->parameters
, i
, error
);
3874 name
= mono_string_to_utf8 (m
->name
);
3875 for (tmp
= assembly
->array_methods
; tmp
; tmp
= tmp
->next
) {
3876 am
= (ArrayMethod
*)tmp
->data
;
3877 if (strcmp (name
, am
->name
) == 0 &&
3878 mono_metadata_type_equal (am
->parent
, mtype
) &&
3879 mono_metadata_signature_equal (am
->sig
, sig
)) {
3882 m
->table_idx
= am
->token
& 0xffffff;
3886 am
= g_new0 (ArrayMethod
, 1);
3890 am
->token
= mono_image_get_memberref_token (assembly
, am
->parent
, name
,
3891 method_encode_signature (assembly
, sig
));
3892 assembly
->array_methods
= g_list_prepend (assembly
->array_methods
, am
);
3893 m
->table_idx
= am
->token
& 0xffffff;
3904 * Insert into the metadata tables all the info about the TypeBuilder tb.
3905 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3908 mono_image_get_type_info (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
, MonoDynamicImage
*assembly
, MonoError
*error
)
3910 MonoDynamicTable
*table
;
3912 int i
, is_object
= 0, is_system
= 0;
3915 mono_error_init (error
);
3917 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
3918 values
= table
->values
+ tb
->table_idx
* MONO_TYPEDEF_SIZE
;
3919 values
[MONO_TYPEDEF_FLAGS
] = tb
->attrs
;
3920 n
= mono_string_to_utf8 (tb
->name
);
3921 if (strcmp (n
, "Object") == 0)
3923 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, n
);
3925 n
= mono_string_to_utf8 (tb
->nspace
);
3926 if (strcmp (n
, "System") == 0)
3928 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, n
);
3930 if (tb
->parent
&& !(is_system
&& is_object
) &&
3931 !(tb
->attrs
& TYPE_ATTRIBUTE_INTERFACE
)) { /* interfaces don't have a parent */
3932 MonoType
*parent_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
->parent
, error
);
3933 return_val_if_nok (error
, FALSE
);
3934 values
[MONO_TYPEDEF_EXTENDS
] = mono_image_typedef_or_ref (assembly
, parent_type
);
3936 values
[MONO_TYPEDEF_EXTENDS
] = 0;
3938 values
[MONO_TYPEDEF_FIELD_LIST
] = assembly
->tables
[MONO_TABLE_FIELD
].next_idx
;
3939 values
[MONO_TYPEDEF_METHOD_LIST
] = assembly
->tables
[MONO_TABLE_METHOD
].next_idx
;
3942 * if we have explicitlayout or sequentiallayouts, output data in the
3943 * ClassLayout table.
3945 if (((tb
->attrs
& TYPE_ATTRIBUTE_LAYOUT_MASK
) != TYPE_ATTRIBUTE_AUTO_LAYOUT
) &&
3946 ((tb
->class_size
> 0) || (tb
->packing_size
> 0))) {
3947 table
= &assembly
->tables
[MONO_TABLE_CLASSLAYOUT
];
3949 alloc_table (table
, table
->rows
);
3950 values
= table
->values
+ table
->rows
* MONO_CLASS_LAYOUT_SIZE
;
3951 values
[MONO_CLASS_LAYOUT_PARENT
] = tb
->table_idx
;
3952 values
[MONO_CLASS_LAYOUT_CLASS_SIZE
] = tb
->class_size
;
3953 values
[MONO_CLASS_LAYOUT_PACKING_SIZE
] = tb
->packing_size
;
3956 /* handle interfaces */
3957 if (tb
->interfaces
) {
3958 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
3960 table
->rows
+= mono_array_length (tb
->interfaces
);
3961 alloc_table (table
, table
->rows
);
3962 values
= table
->values
+ (i
+ 1) * MONO_INTERFACEIMPL_SIZE
;
3963 for (i
= 0; i
< mono_array_length (tb
->interfaces
); ++i
) {
3964 MonoReflectionType
* iface
= (MonoReflectionType
*) mono_array_get (tb
->interfaces
, gpointer
, i
);
3965 MonoType
*iface_type
= mono_reflection_type_get_handle (iface
, error
);
3966 return_val_if_nok (error
, FALSE
);
3967 values
[MONO_INTERFACEIMPL_CLASS
] = tb
->table_idx
;
3968 values
[MONO_INTERFACEIMPL_INTERFACE
] = mono_image_typedef_or_ref (assembly
, iface_type
);
3969 values
+= MONO_INTERFACEIMPL_SIZE
;
3975 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
3976 table
->rows
+= tb
->num_fields
;
3977 alloc_table (table
, table
->rows
);
3978 for (i
= 0; i
< tb
->num_fields
; ++i
) {
3979 mono_image_get_field_info (
3980 mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
), assembly
, error
);
3981 return_val_if_nok (error
, FALSE
);
3985 /* handle constructors */
3987 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
3988 table
->rows
+= mono_array_length (tb
->ctors
);
3989 alloc_table (table
, table
->rows
);
3990 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
3991 if (!mono_image_get_ctor_info (domain
,
3992 mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
),
3998 /* handle methods */
4000 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
4001 table
->rows
+= tb
->num_methods
;
4002 alloc_table (table
, table
->rows
);
4003 for (i
= 0; i
< tb
->num_methods
; ++i
) {
4004 if (!mono_image_get_method_info (
4005 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
), assembly
, error
))
4010 /* Do the same with properties etc.. */
4011 if (tb
->events
&& mono_array_length (tb
->events
)) {
4012 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
4013 table
->rows
+= mono_array_length (tb
->events
);
4014 alloc_table (table
, table
->rows
);
4015 table
= &assembly
->tables
[MONO_TABLE_EVENTMAP
];
4017 alloc_table (table
, table
->rows
);
4018 values
= table
->values
+ table
->rows
* MONO_EVENT_MAP_SIZE
;
4019 values
[MONO_EVENT_MAP_PARENT
] = tb
->table_idx
;
4020 values
[MONO_EVENT_MAP_EVENTLIST
] = assembly
->tables
[MONO_TABLE_EVENT
].next_idx
;
4021 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
) {
4022 mono_image_get_event_info (
4023 mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
), assembly
, error
);
4024 return_val_if_nok (error
, FALSE
);
4027 if (tb
->properties
&& mono_array_length (tb
->properties
)) {
4028 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
4029 table
->rows
+= mono_array_length (tb
->properties
);
4030 alloc_table (table
, table
->rows
);
4031 table
= &assembly
->tables
[MONO_TABLE_PROPERTYMAP
];
4033 alloc_table (table
, table
->rows
);
4034 values
= table
->values
+ table
->rows
* MONO_PROPERTY_MAP_SIZE
;
4035 values
[MONO_PROPERTY_MAP_PARENT
] = tb
->table_idx
;
4036 values
[MONO_PROPERTY_MAP_PROPERTY_LIST
] = assembly
->tables
[MONO_TABLE_PROPERTY
].next_idx
;
4037 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
) {
4038 mono_image_get_property_info (
4039 mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
), assembly
, error
);
4040 return_val_if_nok (error
, FALSE
);
4044 /* handle generic parameters */
4045 if (tb
->generic_params
) {
4046 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
4047 table
->rows
+= mono_array_length (tb
->generic_params
);
4048 alloc_table (table
, table
->rows
);
4049 for (i
= 0; i
< mono_array_length (tb
->generic_params
); ++i
) {
4050 guint32 owner
= MONO_TYPEORMETHOD_TYPE
| (tb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
4052 mono_image_get_generic_param_info (
4053 mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
), owner
, assembly
);
4057 mono_image_add_decl_security (assembly
,
4058 mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
), tb
->permissions
);
4061 MonoDynamicTable
*ntable
;
4063 ntable
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
4064 ntable
->rows
+= mono_array_length (tb
->subtypes
);
4065 alloc_table (ntable
, ntable
->rows
);
4066 values
= ntable
->values
+ ntable
->next_idx
* MONO_NESTED_CLASS_SIZE
;
4068 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
4069 MonoReflectionTypeBuilder
*subtype
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
4071 values
[MONO_NESTED_CLASS_NESTED
] = subtype
->table_idx
;
4072 values
[MONO_NESTED_CLASS_ENCLOSING
] = tb
->table_idx
;
4073 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4074 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4075 mono_string_to_utf8 (tb->name), tb->table_idx,
4076 ntable->next_idx, ntable->rows);*/
4077 values
+= MONO_NESTED_CLASS_SIZE
;
4087 collect_types (MonoPtrArray
*types
, MonoReflectionTypeBuilder
*type
)
4091 mono_ptr_array_append (*types
, type
);
4093 if (!type
->subtypes
)
4096 for (i
= 0; i
< mono_array_length (type
->subtypes
); ++i
) {
4097 MonoReflectionTypeBuilder
*subtype
= mono_array_get (type
->subtypes
, MonoReflectionTypeBuilder
*, i
);
4098 collect_types (types
, subtype
);
4103 compare_types_by_table_idx (MonoReflectionTypeBuilder
**type1
, MonoReflectionTypeBuilder
**type2
)
4105 if ((*type1
)->table_idx
< (*type2
)->table_idx
)
4108 if ((*type1
)->table_idx
> (*type2
)->table_idx
)
4115 params_add_cattrs (MonoDynamicImage
*assembly
, MonoArray
*pinfo
, MonoError
*error
) {
4118 mono_error_init (error
);
4121 for (i
= 0; i
< mono_array_length (pinfo
); ++i
) {
4122 MonoReflectionParamBuilder
*pb
;
4123 pb
= mono_array_get (pinfo
, MonoReflectionParamBuilder
*, i
);
4126 if (!mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PARAMDEF
, pb
->cattrs
, error
))
4134 type_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
, MonoError
*error
) {
4137 mono_error_init (error
);
4139 if (!mono_image_add_cattrs (assembly
, tb
->table_idx
, MONO_CUSTOM_ATTR_TYPEDEF
, tb
->cattrs
, error
))
4142 for (i
= 0; i
< tb
->num_fields
; ++i
) {
4143 MonoReflectionFieldBuilder
* fb
;
4144 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
);
4145 if (!mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
, error
))
4150 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
) {
4151 MonoReflectionEventBuilder
* eb
;
4152 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
4153 if (!mono_image_add_cattrs (assembly
, eb
->table_idx
, MONO_CUSTOM_ATTR_EVENT
, eb
->cattrs
, error
))
4157 if (tb
->properties
) {
4158 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
) {
4159 MonoReflectionPropertyBuilder
* pb
;
4160 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
4161 if (!mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PROPERTY
, pb
->cattrs
, error
))
4166 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
4167 MonoReflectionCtorBuilder
* cb
;
4168 cb
= mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
);
4169 if (!mono_image_add_cattrs (assembly
, cb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, cb
->cattrs
, error
) ||
4170 !params_add_cattrs (assembly
, cb
->pinfo
, error
))
4176 for (i
= 0; i
< tb
->num_methods
; ++i
) {
4177 MonoReflectionMethodBuilder
* mb
;
4178 mb
= mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
4179 if (!mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
, error
) ||
4180 !params_add_cattrs (assembly
, mb
->pinfo
, error
))
4186 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
4187 if (!type_add_cattrs (assembly
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
), error
))
4196 module_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionModuleBuilder
*moduleb
, MonoError
*error
)
4200 mono_error_init (error
);
4202 if (!mono_image_add_cattrs (assembly
, moduleb
->table_idx
, MONO_CUSTOM_ATTR_MODULE
, moduleb
->cattrs
, error
))
4205 if (moduleb
->global_methods
) {
4206 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
4207 MonoReflectionMethodBuilder
* mb
= mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
4208 if (!mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
, error
) ||
4209 !params_add_cattrs (assembly
, mb
->pinfo
, error
))
4214 if (moduleb
->global_fields
) {
4215 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
) {
4216 MonoReflectionFieldBuilder
*fb
= mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
);
4217 if (!mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
, error
))
4222 if (moduleb
->types
) {
4223 for (i
= 0; i
< moduleb
->num_types
; ++i
) {
4224 if (!type_add_cattrs (assembly
, mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
), error
))
4233 mono_image_fill_file_table (MonoDomain
*domain
, MonoReflectionModule
*module
, MonoDynamicImage
*assembly
)
4235 MonoDynamicTable
*table
;
4239 char *b
= blob_size
;
4242 table
= &assembly
->tables
[MONO_TABLE_FILE
];
4244 alloc_table (table
, table
->rows
);
4245 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
4246 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_METADATA
;
4247 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, module
->image
->module_name
);
4248 if (image_is_dynamic (module
->image
)) {
4249 /* This depends on the fact that the main module is emitted last */
4250 dir
= mono_string_to_utf8 (((MonoReflectionModuleBuilder
*)module
)->assemblyb
->dir
);
4251 path
= g_strdup_printf ("%s%c%s", dir
, G_DIR_SEPARATOR
, module
->image
->module_name
);
4254 path
= g_strdup (module
->image
->name
);
4256 mono_sha1_get_digest_from_file (path
, hash
);
4259 mono_metadata_encode_value (20, b
, &b
);
4260 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
4261 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
4266 mono_image_fill_module_table (MonoDomain
*domain
, MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
)
4268 MonoDynamicTable
*table
;
4271 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
4272 mb
->table_idx
= table
->next_idx
++;
4273 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->module
.name
);
4274 i
= mono_image_add_stream_data (&assembly
->guid
, mono_array_addr (mb
->guid
, char, 0), 16);
4277 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_GENERATION
] = 0;
4278 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_MVID
] = i
;
4279 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENC
] = 0;
4280 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENCBASE
] = 0;
4284 mono_image_fill_export_table_from_class (MonoDomain
*domain
, MonoClass
*klass
,
4285 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
)
4287 MonoDynamicTable
*table
;
4291 visib
= klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
4292 if (! ((visib
& TYPE_ATTRIBUTE_PUBLIC
) || (visib
& TYPE_ATTRIBUTE_NESTED_PUBLIC
)))
4295 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
4297 alloc_table (table
, table
->rows
);
4298 values
= table
->values
+ table
->next_idx
* MONO_EXP_TYPE_SIZE
;
4300 values
[MONO_EXP_TYPE_FLAGS
] = klass
->flags
;
4301 values
[MONO_EXP_TYPE_TYPEDEF
] = klass
->type_token
;
4302 if (klass
->nested_in
)
4303 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (parent_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_EXP_TYPE
;
4305 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (module_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_FILE
;
4306 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
4307 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
4309 res
= table
->next_idx
;
4313 /* Emit nested types */
4314 if (klass
->ext
&& klass
->ext
->nested_classes
) {
4317 for (tmp
= klass
->ext
->nested_classes
; tmp
; tmp
= tmp
->next
)
4318 mono_image_fill_export_table_from_class (domain
, (MonoClass
*)tmp
->data
, module_index
, table
->next_idx
- 1, assembly
);
4325 mono_image_fill_export_table (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
,
4326 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
,
4332 mono_error_init (error
);
4334 MonoType
*t
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
, error
);
4335 return_if_nok (error
);
4337 klass
= mono_class_from_mono_type (t
);
4339 klass
->type_token
= mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
);
4341 idx
= mono_image_fill_export_table_from_class (domain
, klass
, module_index
,
4342 parent_index
, assembly
);
4346 * We need to do this ourselves since klass->nested_classes is not set up.
4349 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
4350 mono_image_fill_export_table (domain
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
), module_index
, idx
, assembly
, error
);
4351 return_if_nok (error
);
4357 mono_image_fill_export_table_from_module (MonoDomain
*domain
, MonoReflectionModule
*module
,
4358 guint32 module_index
, MonoDynamicImage
*assembly
)
4360 MonoImage
*image
= module
->image
;
4364 t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
4366 for (i
= 0; i
< t
->rows
; ++i
) {
4368 MonoClass
*klass
= mono_class_get_checked (image
, mono_metadata_make_token (MONO_TABLE_TYPEDEF
, i
+ 1), &error
);
4369 g_assert (mono_error_ok (&error
)); /* FIXME don't swallow the error */
4371 if (klass
->flags
& TYPE_ATTRIBUTE_PUBLIC
)
4372 mono_image_fill_export_table_from_class (domain
, klass
, module_index
, 0, assembly
);
4377 add_exported_type (MonoReflectionAssemblyBuilder
*assemblyb
, MonoDynamicImage
*assembly
, MonoClass
*klass
, guint32 parent_index
)
4379 MonoDynamicTable
*table
;
4381 guint32 scope
, scope_idx
, impl
, current_idx
;
4382 gboolean forwarder
= TRUE
;
4383 gpointer iter
= NULL
;
4386 if (klass
->nested_in
) {
4387 impl
= (parent_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_EXP_TYPE
;
4390 scope
= resolution_scope_from_image (assembly
, klass
->image
);
4391 g_assert ((scope
& MONO_RESOLUTION_SCOPE_MASK
) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF
);
4392 scope_idx
= scope
>> MONO_RESOLUTION_SCOPE_BITS
;
4393 impl
= (scope_idx
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_ASSEMBLYREF
;
4396 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
4399 alloc_table (table
, table
->rows
);
4400 current_idx
= table
->next_idx
;
4401 values
= table
->values
+ current_idx
* MONO_EXP_TYPE_SIZE
;
4403 values
[MONO_EXP_TYPE_FLAGS
] = forwarder
? TYPE_ATTRIBUTE_FORWARDER
: 0;
4404 values
[MONO_EXP_TYPE_TYPEDEF
] = 0;
4405 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = impl
;
4406 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
4407 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
4411 while ((nested
= mono_class_get_nested_types (klass
, &iter
)))
4412 add_exported_type (assemblyb
, assembly
, nested
, current_idx
);
4416 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder
*assemblyb
, MonoDynamicImage
*assembly
)
4422 if (!assemblyb
->type_forwarders
)
4425 for (i
= 0; i
< mono_array_length (assemblyb
->type_forwarders
); ++i
) {
4426 MonoReflectionType
*t
= mono_array_get (assemblyb
->type_forwarders
, MonoReflectionType
*, i
);
4431 type
= mono_reflection_type_get_handle (t
, &error
);
4432 mono_error_assert_ok (&error
);
4435 klass
= mono_class_from_mono_type (type
);
4437 add_exported_type (assemblyb
, assembly
, klass
, 0);
4441 #define align_pointer(base,p)\
4443 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4445 (p) += 4 - (__diff & 3);\
4449 compare_constants (const void *a
, const void *b
)
4451 const guint32
*a_values
= (const guint32
*)a
;
4452 const guint32
*b_values
= (const guint32
*)b
;
4453 return a_values
[MONO_CONSTANT_PARENT
] - b_values
[MONO_CONSTANT_PARENT
];
4457 compare_semantics (const void *a
, const void *b
)
4459 const guint32
*a_values
= (const guint32
*)a
;
4460 const guint32
*b_values
= (const guint32
*)b
;
4461 int assoc
= a_values
[MONO_METHOD_SEMA_ASSOCIATION
] - b_values
[MONO_METHOD_SEMA_ASSOCIATION
];
4464 return a_values
[MONO_METHOD_SEMA_SEMANTICS
] - b_values
[MONO_METHOD_SEMA_SEMANTICS
];
4468 compare_custom_attrs (const void *a
, const void *b
)
4470 const guint32
*a_values
= (const guint32
*)a
;
4471 const guint32
*b_values
= (const guint32
*)b
;
4473 return a_values
[MONO_CUSTOM_ATTR_PARENT
] - b_values
[MONO_CUSTOM_ATTR_PARENT
];
4477 compare_field_marshal (const void *a
, const void *b
)
4479 const guint32
*a_values
= (const guint32
*)a
;
4480 const guint32
*b_values
= (const guint32
*)b
;
4482 return a_values
[MONO_FIELD_MARSHAL_PARENT
] - b_values
[MONO_FIELD_MARSHAL_PARENT
];
4486 compare_nested (const void *a
, const void *b
)
4488 const guint32
*a_values
= (const guint32
*)a
;
4489 const guint32
*b_values
= (const guint32
*)b
;
4491 return a_values
[MONO_NESTED_CLASS_NESTED
] - b_values
[MONO_NESTED_CLASS_NESTED
];
4495 compare_genericparam (const void *a
, const void *b
)
4498 const GenericParamTableEntry
**a_entry
= (const GenericParamTableEntry
**) a
;
4499 const GenericParamTableEntry
**b_entry
= (const GenericParamTableEntry
**) b
;
4501 if ((*b_entry
)->owner
== (*a_entry
)->owner
) {
4502 MonoType
*a_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)(*a_entry
)->gparam
, &error
);
4503 mono_error_assert_ok (&error
);
4504 MonoType
*b_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)(*b_entry
)->gparam
, &error
);
4505 mono_error_assert_ok (&error
);
4507 mono_type_get_generic_param_num (a_type
) -
4508 mono_type_get_generic_param_num (b_type
);
4510 return (*a_entry
)->owner
- (*b_entry
)->owner
;
4514 compare_declsecurity_attrs (const void *a
, const void *b
)
4516 const guint32
*a_values
= (const guint32
*)a
;
4517 const guint32
*b_values
= (const guint32
*)b
;
4519 return a_values
[MONO_DECL_SECURITY_PARENT
] - b_values
[MONO_DECL_SECURITY_PARENT
];
4523 compare_interface_impl (const void *a
, const void *b
)
4525 const guint32
*a_values
= (const guint32
*)a
;
4526 const guint32
*b_values
= (const guint32
*)b
;
4528 int klass
= a_values
[MONO_INTERFACEIMPL_CLASS
] - b_values
[MONO_INTERFACEIMPL_CLASS
];
4532 return a_values
[MONO_INTERFACEIMPL_INTERFACE
] - b_values
[MONO_INTERFACEIMPL_INTERFACE
];
4536 pad_heap (MonoDynamicStream
*sh
)
4538 if (sh
->index
& 3) {
4539 int sz
= 4 - (sh
->index
& 3);
4540 memset (sh
->data
+ sh
->index
, 0, sz
);
4547 MonoDynamicStream
*stream
;
4551 * build_compressed_metadata() fills in the blob of data that represents the
4552 * raw metadata as it will be saved in the PE file. The five streams are output
4553 * and the metadata tables are comnpressed from the guint32 array representation,
4554 * to the compressed on-disk format.
4557 build_compressed_metadata (MonoDynamicImage
*assembly
, MonoError
*error
)
4559 MonoDynamicTable
*table
;
4561 guint64 valid_mask
= 0;
4562 guint64 sorted_mask
;
4563 guint32 heapt_size
= 0;
4564 guint32 meta_size
= 256; /* allow for header and other stuff */
4565 guint32 table_offset
;
4566 guint32 ntables
= 0;
4572 struct StreamDesc stream_desc
[5];
4574 mono_error_init (error
);
4576 qsort (assembly
->gen_params
->pdata
, assembly
->gen_params
->len
, sizeof (gpointer
), compare_genericparam
);
4577 for (i
= 0; i
< assembly
->gen_params
->len
; i
++) {
4578 GenericParamTableEntry
*entry
= (GenericParamTableEntry
*)g_ptr_array_index (assembly
->gen_params
, i
);
4579 if (!write_generic_param_entry (assembly
, entry
, error
))
4583 stream_desc
[0].name
= "#~";
4584 stream_desc
[0].stream
= &assembly
->tstream
;
4585 stream_desc
[1].name
= "#Strings";
4586 stream_desc
[1].stream
= &assembly
->sheap
;
4587 stream_desc
[2].name
= "#US";
4588 stream_desc
[2].stream
= &assembly
->us
;
4589 stream_desc
[3].name
= "#Blob";
4590 stream_desc
[3].stream
= &assembly
->blob
;
4591 stream_desc
[4].name
= "#GUID";
4592 stream_desc
[4].stream
= &assembly
->guid
;
4594 /* tables that are sorted */
4595 sorted_mask
= ((guint64
)1 << MONO_TABLE_CONSTANT
) | ((guint64
)1 << MONO_TABLE_FIELDMARSHAL
)
4596 | ((guint64
)1 << MONO_TABLE_METHODSEMANTICS
) | ((guint64
)1 << MONO_TABLE_CLASSLAYOUT
)
4597 | ((guint64
)1 << MONO_TABLE_FIELDLAYOUT
) | ((guint64
)1 << MONO_TABLE_FIELDRVA
)
4598 | ((guint64
)1 << MONO_TABLE_IMPLMAP
) | ((guint64
)1 << MONO_TABLE_NESTEDCLASS
)
4599 | ((guint64
)1 << MONO_TABLE_METHODIMPL
) | ((guint64
)1 << MONO_TABLE_CUSTOMATTRIBUTE
)
4600 | ((guint64
)1 << MONO_TABLE_DECLSECURITY
) | ((guint64
)1 << MONO_TABLE_GENERICPARAM
)
4601 | ((guint64
)1 << MONO_TABLE_INTERFACEIMPL
);
4603 /* Compute table sizes */
4604 /* the MonoImage has already been created in mono_image_basic_init() */
4605 meta
= &assembly
->image
;
4607 /* sizes should be multiple of 4 */
4608 pad_heap (&assembly
->blob
);
4609 pad_heap (&assembly
->guid
);
4610 pad_heap (&assembly
->sheap
);
4611 pad_heap (&assembly
->us
);
4613 /* Setup the info used by compute_sizes () */
4614 meta
->idx_blob_wide
= assembly
->blob
.index
>= 65536 ? 1 : 0;
4615 meta
->idx_guid_wide
= assembly
->guid
.index
>= 65536 ? 1 : 0;
4616 meta
->idx_string_wide
= assembly
->sheap
.index
>= 65536 ? 1 : 0;
4618 meta_size
+= assembly
->blob
.index
;
4619 meta_size
+= assembly
->guid
.index
;
4620 meta_size
+= assembly
->sheap
.index
;
4621 meta_size
+= assembly
->us
.index
;
4623 for (i
=0; i
< MONO_TABLE_NUM
; ++i
)
4624 meta
->tables
[i
].rows
= assembly
->tables
[i
].rows
;
4626 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
4627 if (meta
->tables
[i
].rows
== 0)
4629 valid_mask
|= (guint64
)1 << i
;
4631 meta
->tables
[i
].row_size
= mono_metadata_compute_size (
4632 meta
, i
, &meta
->tables
[i
].size_bitfield
);
4633 heapt_size
+= meta
->tables
[i
].row_size
* meta
->tables
[i
].rows
;
4635 heapt_size
+= 24; /* #~ header size */
4636 heapt_size
+= ntables
* 4;
4637 /* make multiple of 4 */
4640 meta_size
+= heapt_size
;
4641 meta
->raw_metadata
= (char *)g_malloc0 (meta_size
);
4642 p
= (unsigned char*)meta
->raw_metadata
;
4643 /* the metadata signature */
4644 *p
++ = 'B'; *p
++ = 'S'; *p
++ = 'J'; *p
++ = 'B';
4645 /* version numbers and 4 bytes reserved */
4646 int16val
= (guint16
*)p
;
4647 *int16val
++ = GUINT16_TO_LE (meta
->md_version_major
);
4648 *int16val
= GUINT16_TO_LE (meta
->md_version_minor
);
4650 /* version string */
4651 int32val
= (guint32
*)p
;
4652 *int32val
= GUINT32_TO_LE ((strlen (meta
->version
) + 3) & (~3)); /* needs to be multiple of 4 */
4654 memcpy (p
, meta
->version
, strlen (meta
->version
));
4655 p
+= GUINT32_FROM_LE (*int32val
);
4656 align_pointer (meta
->raw_metadata
, p
);
4657 int16val
= (guint16
*)p
;
4658 *int16val
++ = GUINT16_TO_LE (0); /* flags must be 0 */
4659 *int16val
= GUINT16_TO_LE (5); /* number of streams */
4663 * write the stream info.
4665 table_offset
= (p
- (unsigned char*)meta
->raw_metadata
) + 5 * 8 + 40; /* room needed for stream headers */
4666 table_offset
+= 3; table_offset
&= ~3;
4668 assembly
->tstream
.index
= heapt_size
;
4669 for (i
= 0; i
< 5; ++i
) {
4670 int32val
= (guint32
*)p
;
4671 stream_desc
[i
].stream
->offset
= table_offset
;
4672 *int32val
++ = GUINT32_TO_LE (table_offset
);
4673 *int32val
= GUINT32_TO_LE (stream_desc
[i
].stream
->index
);
4674 table_offset
+= GUINT32_FROM_LE (*int32val
);
4675 table_offset
+= 3; table_offset
&= ~3;
4677 strcpy ((char*)p
, stream_desc
[i
].name
);
4678 p
+= strlen (stream_desc
[i
].name
) + 1;
4679 align_pointer (meta
->raw_metadata
, p
);
4682 * now copy the data, the table stream header and contents goes first.
4684 g_assert ((p
- (unsigned char*)meta
->raw_metadata
) < assembly
->tstream
.offset
);
4685 p
= (guchar
*)meta
->raw_metadata
+ assembly
->tstream
.offset
;
4686 int32val
= (guint32
*)p
;
4687 *int32val
= GUINT32_TO_LE (0); /* reserved */
4690 *p
++ = 2; /* version */
4693 if (meta
->idx_string_wide
)
4695 if (meta
->idx_guid_wide
)
4697 if (meta
->idx_blob_wide
)
4700 *p
++ = 1; /* reserved */
4701 int64val
= (guint64
*)p
;
4702 *int64val
++ = GUINT64_TO_LE (valid_mask
);
4703 *int64val
++ = GUINT64_TO_LE (valid_mask
& sorted_mask
); /* bitvector of sorted tables */
4705 int32val
= (guint32
*)p
;
4706 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
4707 if (meta
->tables
[i
].rows
== 0)
4709 *int32val
++ = GUINT32_TO_LE (meta
->tables
[i
].rows
);
4711 p
= (unsigned char*)int32val
;
4713 /* sort the tables that still need sorting */
4714 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
4716 qsort (table
->values
+ MONO_CONSTANT_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CONSTANT_SIZE
, compare_constants
);
4717 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
4719 qsort (table
->values
+ MONO_METHOD_SEMA_SIZE
, table
->rows
, sizeof (guint32
) * MONO_METHOD_SEMA_SIZE
, compare_semantics
);
4720 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4722 qsort (table
->values
+ MONO_CUSTOM_ATTR_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CUSTOM_ATTR_SIZE
, compare_custom_attrs
);
4723 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
4725 qsort (table
->values
+ MONO_FIELD_MARSHAL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_FIELD_MARSHAL_SIZE
, compare_field_marshal
);
4726 table
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
4728 qsort (table
->values
+ MONO_NESTED_CLASS_SIZE
, table
->rows
, sizeof (guint32
) * MONO_NESTED_CLASS_SIZE
, compare_nested
);
4729 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4730 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
4732 qsort (table
->values
+ MONO_DECL_SECURITY_SIZE
, table
->rows
, sizeof (guint32
) * MONO_DECL_SECURITY_SIZE
, compare_declsecurity_attrs
);
4733 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
4735 qsort (table
->values
+ MONO_INTERFACEIMPL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_INTERFACEIMPL_SIZE
, compare_interface_impl
);
4737 /* compress the tables */
4738 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
4741 guint32 bitfield
= meta
->tables
[i
].size_bitfield
;
4742 if (!meta
->tables
[i
].rows
)
4744 if (assembly
->tables
[i
].columns
!= mono_metadata_table_count (bitfield
))
4745 g_error ("col count mismatch in %d: %d %d", i
, assembly
->tables
[i
].columns
, mono_metadata_table_count (bitfield
));
4746 meta
->tables
[i
].base
= (char*)p
;
4747 for (row
= 1; row
<= meta
->tables
[i
].rows
; ++row
) {
4748 values
= assembly
->tables
[i
].values
+ row
* assembly
->tables
[i
].columns
;
4749 for (col
= 0; col
< assembly
->tables
[i
].columns
; ++col
) {
4750 switch (mono_metadata_table_size (bitfield
, col
)) {
4752 *p
++ = values
[col
];
4755 *p
++ = values
[col
] & 0xff;
4756 *p
++ = (values
[col
] >> 8) & 0xff;
4759 *p
++ = values
[col
] & 0xff;
4760 *p
++ = (values
[col
] >> 8) & 0xff;
4761 *p
++ = (values
[col
] >> 16) & 0xff;
4762 *p
++ = (values
[col
] >> 24) & 0xff;
4765 g_assert_not_reached ();
4769 g_assert ((p
- (const unsigned char*)meta
->tables
[i
].base
) == (meta
->tables
[i
].rows
* meta
->tables
[i
].row_size
));
4772 g_assert (assembly
->guid
.offset
+ assembly
->guid
.index
< meta_size
);
4773 memcpy (meta
->raw_metadata
+ assembly
->sheap
.offset
, assembly
->sheap
.data
, assembly
->sheap
.index
);
4774 memcpy (meta
->raw_metadata
+ assembly
->us
.offset
, assembly
->us
.data
, assembly
->us
.index
);
4775 memcpy (meta
->raw_metadata
+ assembly
->blob
.offset
, assembly
->blob
.data
, assembly
->blob
.index
);
4776 memcpy (meta
->raw_metadata
+ assembly
->guid
.offset
, assembly
->guid
.data
, assembly
->guid
.index
);
4778 assembly
->meta_size
= assembly
->guid
.offset
+ assembly
->guid
.index
;
4784 * Some tables in metadata need to be sorted according to some criteria, but
4785 * when methods and fields are first created with reflection, they may be assigned a token
4786 * that doesn't correspond to the final token they will get assigned after the sorting.
4787 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4788 * with the reflection objects that represent them. Once all the tables are set up, the
4789 * reflection objects will contains the correct table index. fixup_method() will fixup the
4790 * tokens for the method with ILGenerator @ilgen.
4793 fixup_method (MonoReflectionILGen
*ilgen
, gpointer value
, MonoDynamicImage
*assembly
)
4795 guint32 code_idx
= GPOINTER_TO_UINT (value
);
4796 MonoReflectionILTokenInfo
*iltoken
;
4797 MonoReflectionFieldBuilder
*field
;
4798 MonoReflectionCtorBuilder
*ctor
;
4799 MonoReflectionMethodBuilder
*method
;
4800 MonoReflectionTypeBuilder
*tb
;
4801 MonoReflectionArrayMethod
*am
;
4803 unsigned char *target
;
4805 for (i
= 0; i
< ilgen
->num_token_fixups
; ++i
) {
4806 iltoken
= (MonoReflectionILTokenInfo
*)mono_array_addr_with_size (ilgen
->token_fixups
, sizeof (MonoReflectionILTokenInfo
), i
);
4807 target
= (guchar
*)assembly
->code
.data
+ code_idx
+ iltoken
->code_pos
;
4808 switch (target
[3]) {
4809 case MONO_TABLE_FIELD
:
4810 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
4811 field
= (MonoReflectionFieldBuilder
*)iltoken
->member
;
4812 idx
= field
->table_idx
;
4813 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
4814 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
4815 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->field_to_table_idx
, f
));
4817 g_assert_not_reached ();
4820 case MONO_TABLE_METHOD
:
4821 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
4822 method
= (MonoReflectionMethodBuilder
*)iltoken
->member
;
4823 idx
= method
->table_idx
;
4824 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
4825 ctor
= (MonoReflectionCtorBuilder
*)iltoken
->member
;
4826 idx
= ctor
->table_idx
;
4827 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
4828 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod")) {
4829 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4830 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
4832 g_assert_not_reached ();
4835 case MONO_TABLE_TYPEDEF
:
4836 if (strcmp (iltoken
->member
->vtable
->klass
->name
, "TypeBuilder"))
4837 g_assert_not_reached ();
4838 tb
= (MonoReflectionTypeBuilder
*)iltoken
->member
;
4839 idx
= tb
->table_idx
;
4841 case MONO_TABLE_MEMBERREF
:
4842 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoArrayMethod")) {
4843 am
= (MonoReflectionArrayMethod
*)iltoken
->member
;
4844 idx
= am
->table_idx
;
4845 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
4846 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod") ||
4847 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod") ||
4848 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericCMethod")) {
4849 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4850 g_assert (m
->klass
->generic_class
|| m
->klass
->generic_container
);
4852 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
4854 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
4855 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
4856 g_assert (is_field_on_inst (f
));
4858 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder") ||
4859 !strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
4861 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldOnTypeBuilderInst")) {
4863 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodOnTypeBuilderInst")) {
4865 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst")) {
4868 g_assert_not_reached ();
4871 case MONO_TABLE_METHODSPEC
:
4872 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod")) {
4873 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4874 g_assert (mono_method_signature (m
)->generic_param_count
);
4876 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
4878 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodOnTypeBuilderInst")) {
4881 g_assert_not_reached ();
4885 g_error ("got unexpected table 0x%02x in fixup", target
[3]);
4887 target
[0] = idx
& 0xff;
4888 target
[1] = (idx
>> 8) & 0xff;
4889 target
[2] = (idx
>> 16) & 0xff;
4896 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4897 * value is not known when the table is emitted.
4900 fixup_cattrs (MonoDynamicImage
*assembly
)
4902 MonoDynamicTable
*table
;
4904 guint32 type
, i
, idx
, token
;
4907 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4909 for (i
= 0; i
< table
->rows
; ++i
) {
4910 values
= table
->values
+ ((i
+ 1) * MONO_CUSTOM_ATTR_SIZE
);
4912 type
= values
[MONO_CUSTOM_ATTR_TYPE
];
4913 if ((type
& MONO_CUSTOM_ATTR_TYPE_MASK
) == MONO_CUSTOM_ATTR_TYPE_METHODDEF
) {
4914 idx
= type
>> MONO_CUSTOM_ATTR_TYPE_BITS
;
4915 token
= mono_metadata_make_token (MONO_TABLE_METHOD
, idx
);
4916 ctor
= (MonoObject
*)mono_g_hash_table_lookup (assembly
->remapped_tokens
, GUINT_TO_POINTER (token
));
4919 if (!strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
4920 MonoMethod
*m
= ((MonoReflectionMethod
*)ctor
)->method
;
4921 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
4922 values
[MONO_CUSTOM_ATTR_TYPE
] = (idx
<< MONO_CUSTOM_ATTR_TYPE_BITS
) | MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
4923 } else if (!strcmp (ctor
->vtable
->klass
->name
, "ConstructorBuilder")) {
4924 MonoMethod
*m
= ((MonoReflectionCtorBuilder
*)ctor
)->mhandle
;
4925 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
4926 values
[MONO_CUSTOM_ATTR_TYPE
] = (idx
<< MONO_CUSTOM_ATTR_TYPE_BITS
) | MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
4933 assembly_add_resource_manifest (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
, guint32 implementation
)
4935 MonoDynamicTable
*table
;
4938 table
= &assembly
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4940 alloc_table (table
, table
->rows
);
4941 values
= table
->values
+ table
->next_idx
* MONO_MANIFEST_SIZE
;
4942 values
[MONO_MANIFEST_OFFSET
] = rsrc
->offset
;
4943 values
[MONO_MANIFEST_FLAGS
] = rsrc
->attrs
;
4944 values
[MONO_MANIFEST_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, rsrc
->name
);
4945 values
[MONO_MANIFEST_IMPLEMENTATION
] = implementation
;
4950 assembly_add_resource (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
)
4952 MonoDynamicTable
*table
;
4956 char *b
= blob_size
;
4958 guint32 idx
, offset
;
4960 if (rsrc
->filename
) {
4961 name
= mono_string_to_utf8 (rsrc
->filename
);
4962 sname
= g_path_get_basename (name
);
4964 table
= &assembly
->tables
[MONO_TABLE_FILE
];
4966 alloc_table (table
, table
->rows
);
4967 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
4968 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_NO_METADATA
;
4969 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, sname
);
4972 mono_sha1_get_digest_from_file (name
, hash
);
4973 mono_metadata_encode_value (20, b
, &b
);
4974 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
4975 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
4977 idx
= table
->next_idx
++;
4979 idx
= MONO_IMPLEMENTATION_FILE
| (idx
<< MONO_IMPLEMENTATION_BITS
);
4985 data
= mono_array_addr (rsrc
->data
, char, 0);
4986 len
= mono_array_length (rsrc
->data
);
4992 sizebuf
[0] = offset
; sizebuf
[1] = offset
>> 8;
4993 sizebuf
[2] = offset
>> 16; sizebuf
[3] = offset
>> 24;
4994 rsrc
->offset
= mono_image_add_stream_data (&assembly
->resources
, sizebuf
, 4);
4995 mono_image_add_stream_data (&assembly
->resources
, data
, len
);
4999 * The entry should be emitted into the MANIFESTRESOURCE table of
5000 * the main module, but that needs to reference the FILE table
5001 * which isn't emitted yet.
5008 assembly_add_resource_manifest (mb
, assembly
, rsrc
, idx
);
5012 set_version_from_string (MonoString
*version
, guint32
*values
)
5014 gchar
*ver
, *p
, *str
;
5017 values
[MONO_ASSEMBLY_MAJOR_VERSION
] = 0;
5018 values
[MONO_ASSEMBLY_MINOR_VERSION
] = 0;
5019 values
[MONO_ASSEMBLY_REV_NUMBER
] = 0;
5020 values
[MONO_ASSEMBLY_BUILD_NUMBER
] = 0;
5023 ver
= str
= mono_string_to_utf8 (version
);
5024 for (i
= 0; i
< 4; ++i
) {
5025 values
[MONO_ASSEMBLY_MAJOR_VERSION
+ i
] = strtol (ver
, &p
, 10);
5031 /* handle Revision and Build */
5041 load_public_key (MonoArray
*pkey
, MonoDynamicImage
*assembly
) {
5045 char *b
= blob_size
;
5050 len
= mono_array_length (pkey
);
5051 mono_metadata_encode_value (len
, b
, &b
);
5052 token
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
- blob_size
);
5053 mono_image_add_stream_data (&assembly
->blob
, mono_array_addr (pkey
, char, 0), len
);
5055 assembly
->public_key
= (guint8
*)g_malloc (len
);
5056 memcpy (assembly
->public_key
, mono_array_addr (pkey
, char, 0), len
);
5057 assembly
->public_key_len
= len
;
5059 /* Special case: check for ECMA key (16 bytes) */
5060 if ((len
== MONO_ECMA_KEY_LENGTH
) && mono_is_ecma_key (mono_array_addr (pkey
, char, 0), len
)) {
5061 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5062 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
;
5063 } else if (len
>= MONO_PUBLIC_KEY_HEADER_LENGTH
+ MONO_MINIMUM_PUBLIC_KEY_LENGTH
) {
5064 /* minimum key size (in 2.0) is 384 bits */
5065 assembly
->strong_name_size
= len
- MONO_PUBLIC_KEY_HEADER_LENGTH
;
5067 /* FIXME - verifier */
5068 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len
), (int)len
);
5069 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
; /* to be safe */
5071 assembly
->strong_name
= (char *)g_malloc0 (assembly
->strong_name_size
);
5077 mono_image_emit_manifest (MonoReflectionModuleBuilder
*moduleb
, MonoError
*error
)
5079 MonoDynamicTable
*table
;
5080 MonoDynamicImage
*assembly
;
5081 MonoReflectionAssemblyBuilder
*assemblyb
;
5085 guint32 module_index
;
5087 mono_error_init (error
);
5089 assemblyb
= moduleb
->assemblyb
;
5090 assembly
= moduleb
->dynamic_image
;
5091 domain
= mono_object_domain (assemblyb
);
5093 /* Emit ASSEMBLY table */
5094 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLY
];
5095 alloc_table (table
, 1);
5096 values
= table
->values
+ MONO_ASSEMBLY_SIZE
;
5097 values
[MONO_ASSEMBLY_HASH_ALG
] = assemblyb
->algid
? assemblyb
->algid
: ASSEMBLY_HASH_SHA1
;
5098 values
[MONO_ASSEMBLY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->name
);
5099 if (assemblyb
->culture
) {
5100 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->culture
);
5102 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert (&assembly
->sheap
, "");
5104 values
[MONO_ASSEMBLY_PUBLIC_KEY
] = load_public_key (assemblyb
->public_key
, assembly
);
5105 values
[MONO_ASSEMBLY_FLAGS
] = assemblyb
->flags
;
5106 set_version_from_string (assemblyb
->version
, values
);
5108 /* Emit FILE + EXPORTED_TYPE table */
5110 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
5112 MonoReflectionModuleBuilder
*file_module
=
5113 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
5114 if (file_module
!= moduleb
) {
5115 mono_image_fill_file_table (domain
, (MonoReflectionModule
*)file_module
, assembly
);
5117 if (file_module
->types
) {
5118 for (j
= 0; j
< file_module
->num_types
; ++j
) {
5119 MonoReflectionTypeBuilder
*tb
= mono_array_get (file_module
->types
, MonoReflectionTypeBuilder
*, j
);
5120 mono_image_fill_export_table (domain
, tb
, module_index
, 0, assembly
, error
);
5121 return_if_nok (error
);
5126 if (assemblyb
->loaded_modules
) {
5127 for (i
= 0; i
< mono_array_length (assemblyb
->loaded_modules
); ++i
) {
5128 MonoReflectionModule
*file_module
=
5129 mono_array_get (assemblyb
->loaded_modules
, MonoReflectionModule
*, i
);
5130 mono_image_fill_file_table (domain
, file_module
, assembly
);
5132 mono_image_fill_export_table_from_module (domain
, file_module
, module_index
, assembly
);
5135 if (assemblyb
->type_forwarders
)
5136 mono_image_fill_export_table_from_type_forwarders (assemblyb
, assembly
);
5138 /* Emit MANIFESTRESOURCE table */
5140 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
5142 MonoReflectionModuleBuilder
*file_module
=
5143 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
5144 /* The table for the main module is emitted later */
5145 if (file_module
!= moduleb
) {
5147 if (file_module
->resources
) {
5148 int len
= mono_array_length (file_module
->resources
);
5149 for (j
= 0; j
< len
; ++j
) {
5150 MonoReflectionResource
* res
= (MonoReflectionResource
*)mono_array_addr (file_module
->resources
, MonoReflectionResource
, j
);
5151 assembly_add_resource_manifest (file_module
, assembly
, res
, MONO_IMPLEMENTATION_FILE
| (module_index
<< MONO_IMPLEMENTATION_BITS
));
5158 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5161 * mono_image_build_metadata() will fill the info in all the needed metadata tables
5162 * for the modulebuilder @moduleb.
5163 * At the end of the process, method and field tokens are fixed up and the
5164 * on-disk compressed metadata representation is created.
5165 * Return TRUE on success, or FALSE on failure and sets @error
5168 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
, MonoError
*error
)
5170 MonoDynamicTable
*table
;
5171 MonoDynamicImage
*assembly
;
5172 MonoReflectionAssemblyBuilder
*assemblyb
;
5178 mono_error_init (error
);
5180 assemblyb
= moduleb
->assemblyb
;
5181 assembly
= moduleb
->dynamic_image
;
5182 domain
= mono_object_domain (assemblyb
);
5184 if (assembly
->text_rva
)
5187 assembly
->text_rva
= START_TEXT_RVA
;
5189 if (moduleb
->is_main
) {
5190 mono_image_emit_manifest (moduleb
, error
);
5191 return_val_if_nok (error
, FALSE
);
5194 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
5195 table
->rows
= 1; /* .<Module> */
5197 alloc_table (table
, table
->rows
);
5199 * Set the first entry.
5201 values
= table
->values
+ table
->columns
;
5202 values
[MONO_TYPEDEF_FLAGS
] = 0;
5203 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, "<Module>") ;
5204 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, "") ;
5205 values
[MONO_TYPEDEF_EXTENDS
] = 0;
5206 values
[MONO_TYPEDEF_FIELD_LIST
] = 1;
5207 values
[MONO_TYPEDEF_METHOD_LIST
] = 1;
5210 * handle global methods
5211 * FIXME: test what to do when global methods are defined in multiple modules.
5213 if (moduleb
->global_methods
) {
5214 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
5215 table
->rows
+= mono_array_length (moduleb
->global_methods
);
5216 alloc_table (table
, table
->rows
);
5217 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
5218 if (!mono_image_get_method_info (
5219 mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
), assembly
, error
))
5223 if (moduleb
->global_fields
) {
5224 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
5225 table
->rows
+= mono_array_length (moduleb
->global_fields
);
5226 alloc_table (table
, table
->rows
);
5227 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
) {
5228 mono_image_get_field_info (
5229 mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
), assembly
,
5236 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
5237 alloc_table (table
, 1);
5238 mono_image_fill_module_table (domain
, moduleb
, assembly
);
5240 /* Collect all types into a list sorted by their table_idx */
5241 mono_ptr_array_init (types
, moduleb
->num_types
, MONO_ROOT_SOURCE_REFLECTION
, "dynamic module types list");
5244 for (i
= 0; i
< moduleb
->num_types
; ++i
) {
5245 MonoReflectionTypeBuilder
*type
= mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
);
5246 collect_types (&types
, type
);
5249 mono_ptr_array_sort (types
, (int (*)(const void *, const void *))compare_types_by_table_idx
);
5250 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
5251 table
->rows
+= mono_ptr_array_size (types
);
5252 alloc_table (table
, table
->rows
);
5255 * Emit type names + namespaces at one place inside the string heap,
5256 * so load_class_names () needs to touch fewer pages.
5258 for (i
= 0; i
< mono_ptr_array_size (types
); ++i
) {
5259 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mono_ptr_array_get (types
, i
);
5260 string_heap_insert_mstring (&assembly
->sheap
, tb
->nspace
);
5262 for (i
= 0; i
< mono_ptr_array_size (types
); ++i
) {
5263 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mono_ptr_array_get (types
, i
);
5264 string_heap_insert_mstring (&assembly
->sheap
, tb
->name
);
5267 for (i
= 0; i
< mono_ptr_array_size (types
); ++i
) {
5268 MonoReflectionTypeBuilder
*type
= (MonoReflectionTypeBuilder
*)mono_ptr_array_get (types
, i
);
5269 if (!mono_image_get_type_info (domain
, type
, assembly
, error
))
5274 * table->rows is already set above and in mono_image_fill_module_table.
5276 /* add all the custom attributes at the end, once all the indexes are stable */
5277 if (!mono_image_add_cattrs (assembly
, 1, MONO_CUSTOM_ATTR_ASSEMBLY
, assemblyb
->cattrs
, error
))
5280 /* CAS assembly permissions */
5281 if (assemblyb
->permissions_minimum
)
5282 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_minimum
);
5283 if (assemblyb
->permissions_optional
)
5284 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_optional
);
5285 if (assemblyb
->permissions_refused
)
5286 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_refused
);
5288 if (!module_add_cattrs (assembly
, moduleb
, error
))
5292 mono_g_hash_table_foreach (assembly
->token_fixups
, (GHFunc
)fixup_method
, assembly
);
5294 /* Create the MethodImpl table. We do this after emitting all methods so we already know
5295 * the final tokens and don't need another fixup pass. */
5297 if (moduleb
->global_methods
) {
5298 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
5299 MonoReflectionMethodBuilder
*mb
= mono_array_get (
5300 moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
5301 if (!mono_image_add_methodimpl (assembly
, mb
, error
))
5306 for (i
= 0; i
< mono_ptr_array_size (types
); ++i
) {
5307 MonoReflectionTypeBuilder
*type
= (MonoReflectionTypeBuilder
*)mono_ptr_array_get (types
, i
);
5308 if (type
->methods
) {
5309 for (j
= 0; j
< type
->num_methods
; ++j
) {
5310 MonoReflectionMethodBuilder
*mb
= mono_array_get (
5311 type
->methods
, MonoReflectionMethodBuilder
*, j
);
5313 if (!mono_image_add_methodimpl (assembly
, mb
, error
))
5319 fixup_cattrs (assembly
);
5322 mono_ptr_array_destroy (types
);
5325 return mono_error_ok (error
);
5328 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5331 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
, MonoError
*error
)
5333 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5336 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5340 guint32 import_lookup_table
;
5344 guint32 import_address_table_rva
;
5352 #ifndef DISABLE_REFLECTION_EMIT
5355 * mono_image_insert_string:
5356 * @module: module builder object
5359 * Insert @str into the user string stream of @module.
5362 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
5364 MonoDynamicImage
*assembly
;
5369 if (!module
->dynamic_image
)
5370 mono_image_module_basic_init (module
);
5372 assembly
= module
->dynamic_image
;
5374 if (assembly
->save
) {
5375 mono_metadata_encode_value (1 | (str
->length
* 2), b
, &b
);
5376 idx
= mono_image_add_stream_data (&assembly
->us
, buf
, b
-buf
);
5377 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5379 char *swapped
= g_malloc (2 * mono_string_length (str
));
5380 const char *p
= (const char*)mono_string_chars (str
);
5382 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
5383 mono_image_add_stream_data (&assembly
->us
, swapped
, str
->length
* 2);
5387 mono_image_add_stream_data (&assembly
->us
, (const char*)mono_string_chars (str
), str
->length
* 2);
5389 mono_image_add_stream_data (&assembly
->us
, "", 1);
5391 idx
= assembly
->us
.index
++;
5394 register_dyn_token (assembly
, MONO_TOKEN_STRING
| idx
, (MonoObject
*)str
);
5396 return MONO_TOKEN_STRING
| idx
;
5400 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
, MonoError
*error
)
5404 MonoMethodSignature
*sig
;
5406 mono_error_init (error
);
5408 klass
= obj
->vtable
->klass
;
5409 if (strcmp (klass
->name
, "MonoMethod") == 0 || strcmp (klass
->name
, "MonoCMethod") == 0) {
5410 MonoMethod
*method
= ((MonoReflectionMethod
*)obj
)->method
;
5411 MonoMethodSignature
*old
;
5412 guint32 sig_token
, parent
;
5415 g_assert (opt_param_types
&& (mono_method_signature (method
)->sentinelpos
>= 0));
5417 nargs
= mono_array_length (opt_param_types
);
5418 old
= mono_method_signature (method
);
5419 sig
= mono_metadata_signature_alloc ( &assembly
->image
, old
->param_count
+ nargs
);
5421 sig
->hasthis
= old
->hasthis
;
5422 sig
->explicit_this
= old
->explicit_this
;
5423 sig
->call_convention
= old
->call_convention
;
5424 sig
->generic_param_count
= old
->generic_param_count
;
5425 sig
->param_count
= old
->param_count
+ nargs
;
5426 sig
->sentinelpos
= old
->param_count
;
5427 sig
->ret
= old
->ret
;
5429 for (i
= 0; i
< old
->param_count
; i
++)
5430 sig
->params
[i
] = old
->params
[i
];
5432 for (i
= 0; i
< nargs
; i
++) {
5433 MonoReflectionType
*rt
= mono_array_get (opt_param_types
, MonoReflectionType
*, i
);
5434 sig
->params
[old
->param_count
+ i
] = mono_reflection_type_get_handle (rt
, error
);
5435 if (!is_ok (error
)) goto fail
;
5438 parent
= mono_image_typedef_or_ref (assembly
, &method
->klass
->byval_arg
);
5439 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_MEMBERREF_PARENT_TYPEREF
);
5440 parent
>>= MONO_TYPEDEFORREF_BITS
;
5442 parent
<<= MONO_MEMBERREF_PARENT_BITS
;
5443 parent
|= MONO_MEMBERREF_PARENT_TYPEREF
;
5445 sig_token
= method_encode_signature (assembly
, sig
);
5446 token
= mono_image_get_varargs_method_token (assembly
, parent
, method
->name
, sig_token
);
5447 } else if (strcmp (klass
->name
, "MethodBuilder") == 0) {
5448 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
5449 ReflectionMethodBuilder rmb
;
5450 guint32 parent
, sig_token
;
5451 int nopt_args
, nparams
, ngparams
, i
;
5453 if (!reflection_methodbuilder_from_method_builder (&rmb
, mb
, error
))
5456 rmb
.opt_types
= opt_param_types
;
5457 nopt_args
= mono_array_length (opt_param_types
);
5459 nparams
= rmb
.parameters
? mono_array_length (rmb
.parameters
): 0;
5460 ngparams
= rmb
.generic_params
? mono_array_length (rmb
.generic_params
): 0;
5461 sig
= mono_metadata_signature_alloc (&assembly
->image
, nparams
+ nopt_args
);
5463 sig
->hasthis
= !(rmb
.attrs
& METHOD_ATTRIBUTE_STATIC
);
5464 sig
->explicit_this
= (rmb
.call_conv
& 0x40) == 0x40;
5465 sig
->call_convention
= rmb
.call_conv
;
5466 sig
->generic_param_count
= ngparams
;
5467 sig
->param_count
= nparams
+ nopt_args
;
5468 sig
->sentinelpos
= nparams
;
5469 sig
->ret
= mono_reflection_type_get_handle (rmb
.rtype
, error
);
5470 if (!is_ok (error
)) goto fail
;
5472 for (i
= 0; i
< nparams
; i
++) {
5473 MonoReflectionType
*rt
= mono_array_get (rmb
.parameters
, MonoReflectionType
*, i
);
5474 sig
->params
[i
] = mono_reflection_type_get_handle (rt
, error
);
5475 if (!is_ok (error
)) goto fail
;
5478 for (i
= 0; i
< nopt_args
; i
++) {
5479 MonoReflectionType
*rt
= mono_array_get (opt_param_types
, MonoReflectionType
*, i
);
5480 sig
->params
[nparams
+ i
] = mono_reflection_type_get_handle (rt
, error
);
5481 if (!is_ok (error
)) goto fail
;
5484 sig_token
= method_builder_encode_signature (assembly
, &rmb
, error
);
5488 parent
= mono_image_create_token (assembly
, obj
, TRUE
, TRUE
, error
);
5489 if (!mono_error_ok (error
))
5491 g_assert (mono_metadata_token_table (parent
) == MONO_TABLE_METHOD
);
5493 parent
= mono_metadata_token_index (parent
) << MONO_MEMBERREF_PARENT_BITS
;
5494 parent
|= MONO_MEMBERREF_PARENT_METHODDEF
;
5496 char *name
= mono_string_to_utf8 (rmb
.name
);
5497 token
= mono_image_get_varargs_method_token (
5498 assembly
, parent
, name
, sig_token
);
5501 g_error ("requested method token for %s\n", klass
->name
);
5504 g_hash_table_insert (assembly
->vararg_aux_hash
, GUINT_TO_POINTER (token
), sig
);
5505 register_dyn_token (assembly
, token
, obj
);
5508 g_assert (!mono_error_ok (error
));
5513 * mono_image_create_token:
5514 * @assembly: a dynamic assembly
5516 * @register_token: Whenever to register the token in the assembly->tokens hash.
5518 * Get a token to insert in the IL code stream for the given MemberInfo.
5519 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
5520 * the table_idx-es were recomputed, so registering the token would overwrite an existing
5524 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
5525 gboolean create_open_instance
, gboolean register_token
,
5531 mono_error_init (error
);
5533 klass
= obj
->vtable
->klass
;
5535 /* Check for user defined reflection objects */
5536 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5537 if (klass
->image
!= mono_defaults
.corlib
|| (strcmp (klass
->name
, "TypeDelegator") == 0)) {
5538 mono_error_set_not_supported (error
, "User defined subclasses of System.Type are not yet supported");
5542 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
5543 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
5544 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
5546 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
&& !mb
->generic_params
)
5547 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
5549 token
= mono_image_get_methodbuilder_token (assembly
, mb
, create_open_instance
, error
);
5550 if (!mono_error_ok (error
))
5553 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5554 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
5555 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
5556 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
5558 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
)
5559 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
5561 token
= mono_image_get_ctorbuilder_token (assembly
, mb
, error
);
5562 if (!mono_error_ok (error
))
5565 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5566 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
5567 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
5568 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
5569 if (tb
->generic_params
) {
5570 token
= mono_image_get_generic_field_token (assembly
, fb
, error
);
5571 return_val_if_nok (error
, 0);
5573 if (tb
->module
->dynamic_image
== assembly
) {
5574 token
= fb
->table_idx
| MONO_TOKEN_FIELD_DEF
;
5576 token
= mono_image_get_fieldref_token (assembly
, (MonoObject
*)fb
, fb
->handle
);
5579 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
5580 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
5581 if (create_open_instance
&& tb
->generic_params
) {
5583 init_type_builder_generics (obj
);
5584 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
5585 return_val_if_nok (error
, 0);
5586 token
= mono_image_typedef_or_ref_full (assembly
, type
, TRUE
);
5587 token
= mono_metadata_token_from_dor (token
);
5588 } else if (tb
->module
->dynamic_image
== assembly
) {
5589 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
5592 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
5593 return_val_if_nok (error
, 0);
5594 token
= mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly
, type
));
5596 } else if (strcmp (klass
->name
, "MonoType") == 0) {
5597 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
5598 return_val_if_nok (error
, 0);
5599 MonoClass
*mc
= mono_class_from_mono_type (type
);
5600 token
= mono_metadata_token_from_dor (
5601 mono_image_typedef_or_ref_full (assembly
, type
, mc
->generic_container
== NULL
|| create_open_instance
));
5602 } else if (strcmp (klass
->name
, "GenericTypeParameterBuilder") == 0) {
5603 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
5604 return_val_if_nok (error
, 0);
5605 token
= mono_metadata_token_from_dor (
5606 mono_image_typedef_or_ref (assembly
, type
));
5607 } else if (strcmp (klass
->name
, "MonoGenericClass") == 0) {
5608 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
5609 return_val_if_nok (error
, 0);
5610 token
= mono_metadata_token_from_dor (
5611 mono_image_typedef_or_ref (assembly
, type
));
5612 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
5613 strcmp (klass
->name
, "MonoMethod") == 0 ||
5614 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
5615 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
5616 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
5617 if (m
->method
->is_inflated
) {
5618 if (create_open_instance
)
5619 token
= mono_image_get_methodspec_token (assembly
, m
->method
);
5621 token
= mono_image_get_inflated_method_token (assembly
, m
->method
);
5622 } else if ((m
->method
->klass
->image
== &assembly
->image
) &&
5623 !m
->method
->klass
->generic_class
) {
5624 static guint32 method_table_idx
= 0xffffff;
5625 if (m
->method
->klass
->wastypebuilder
) {
5626 /* we use the same token as the one that was assigned
5627 * to the Methodbuilder.
5628 * FIXME: do the equivalent for Fields.
5630 token
= m
->method
->token
;
5633 * Each token should have a unique index, but the indexes are
5634 * assigned by managed code, so we don't know about them. An
5635 * easy solution is to count backwards...
5637 method_table_idx
--;
5638 token
= MONO_TOKEN_METHOD_DEF
| method_table_idx
;
5641 token
= mono_image_get_methodref_token (assembly
, m
->method
, create_open_instance
);
5643 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5644 } else if (strcmp (klass
->name
, "MonoField") == 0) {
5645 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
5646 if ((f
->field
->parent
->image
== &assembly
->image
) && !is_field_on_inst (f
->field
)) {
5647 static guint32 field_table_idx
= 0xffffff;
5649 token
= MONO_TOKEN_FIELD_DEF
| field_table_idx
;
5651 token
= mono_image_get_fieldref_token (assembly
, (MonoObject
*)f
, f
->field
);
5653 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5654 } else if (strcmp (klass
->name
, "MonoArrayMethod") == 0) {
5655 MonoReflectionArrayMethod
*m
= (MonoReflectionArrayMethod
*)obj
;
5656 token
= mono_image_get_array_token (assembly
, m
, error
);
5657 return_val_if_nok (error
, 0);
5658 } else if (strcmp (klass
->name
, "SignatureHelper") == 0) {
5659 MonoReflectionSigHelper
*s
= (MonoReflectionSigHelper
*)obj
;
5660 token
= MONO_TOKEN_SIGNATURE
| mono_image_get_sighelper_token (assembly
, s
, error
);
5661 return_val_if_nok (error
, 0);
5662 } else if (strcmp (klass
->name
, "EnumBuilder") == 0) {
5663 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
5664 return_val_if_nok (error
, 0);
5665 token
= mono_metadata_token_from_dor (
5666 mono_image_typedef_or_ref (assembly
, type
));
5667 } else if (strcmp (klass
->name
, "FieldOnTypeBuilderInst") == 0) {
5668 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
5669 token
= mono_image_get_field_on_inst_token (assembly
, f
, error
);
5670 return_val_if_nok (error
, 0);
5671 } else if (strcmp (klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
5672 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
5673 token
= mono_image_get_ctor_on_inst_token (assembly
, c
, create_open_instance
, error
);
5674 if (!mono_error_ok (error
))
5676 } else if (strcmp (klass
->name
, "MethodOnTypeBuilderInst") == 0) {
5677 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
5678 token
= mono_image_get_method_on_inst_token (assembly
, m
, create_open_instance
, error
);
5679 if (!mono_error_ok (error
))
5681 } else if (is_sre_array (klass
) || is_sre_byref (klass
) || is_sre_pointer (klass
)) {
5682 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
5683 return_val_if_nok (error
, 0);
5684 token
= mono_metadata_token_from_dor (
5685 mono_image_typedef_or_ref (assembly
, type
));
5687 g_error ("requested token for %s\n", klass
->name
);
5691 mono_image_register_token (assembly
, token
, obj
);
5697 * mono_image_register_token:
5699 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5700 * the Module.ResolveXXXToken () methods to work.
5703 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
5707 dynamic_image_lock (assembly
);
5708 prev
= (MonoObject
*)mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
5710 /* There could be multiple MethodInfo objects with the same token */
5711 //g_assert (prev == obj);
5713 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), obj
);
5715 dynamic_image_unlock (assembly
);
5718 static MonoDynamicImage
*
5719 create_dynamic_mono_image (MonoDynamicAssembly
*assembly
, char *assembly_name
, char *module_name
)
5721 static const guchar entrycode
[16] = {0xff, 0x25, 0};
5722 MonoDynamicImage
*image
;
5725 const char *version
;
5727 if (!strcmp (mono_get_runtime_info ()->framework_version
, "2.1"))
5728 version
= "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5730 version
= mono_get_runtime_info ()->runtime_version
;
5733 /* The MonoGHashTable's need GC tracking */
5734 image
= (MonoDynamicImage
*)GC_MALLOC (sizeof (MonoDynamicImage
));
5736 image
= g_new0 (MonoDynamicImage
, 1);
5739 mono_profiler_module_event (&image
->image
, MONO_PROFILE_START_LOAD
);
5741 /*g_print ("created image %p\n", image);*/
5742 /* keep in sync with image.c */
5743 image
->image
.name
= assembly_name
;
5744 image
->image
.assembly_name
= image
->image
.name
; /* they may be different */
5745 image
->image
.module_name
= module_name
;
5746 image
->image
.version
= g_strdup (version
);
5747 image
->image
.md_version_major
= 1;
5748 image
->image
.md_version_minor
= 1;
5749 image
->image
.dynamic
= TRUE
;
5751 image
->image
.references
= g_new0 (MonoAssembly
*, 1);
5752 image
->image
.references
[0] = NULL
;
5754 mono_image_init (&image
->image
);
5756 image
->token_fixups
= mono_g_hash_table_new_type ((GHashFunc
)mono_object_hash
, NULL
, MONO_HASH_KEY_GC
, MONO_ROOT_SOURCE_REFLECTION
, "dynamic module token fixups table");
5757 image
->method_to_table_idx
= g_hash_table_new (NULL
, NULL
);
5758 image
->field_to_table_idx
= g_hash_table_new (NULL
, NULL
);
5759 image
->method_aux_hash
= g_hash_table_new (NULL
, NULL
);
5760 image
->vararg_aux_hash
= g_hash_table_new (NULL
, NULL
);
5761 image
->handleref
= g_hash_table_new (NULL
, NULL
);
5762 image
->handleref_managed
= mono_g_hash_table_new_type ((GHashFunc
)mono_object_hash
, NULL
, MONO_HASH_KEY_GC
, MONO_ROOT_SOURCE_REFLECTION
, "dynamic module reference-to-token table");
5763 image
->tokens
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
, MONO_ROOT_SOURCE_REFLECTION
, "dynamic module tokens table");
5764 image
->generic_def_objects
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
, MONO_ROOT_SOURCE_REFLECTION
, "dynamic module generic definitions table");
5765 image
->methodspec
= mono_g_hash_table_new_type ((GHashFunc
)mono_object_hash
, NULL
, MONO_HASH_KEY_GC
, MONO_ROOT_SOURCE_REFLECTION
, "dynamic module method specifications table");
5766 image
->typespec
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
5767 image
->typeref
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
5768 image
->blob_cache
= g_hash_table_new ((GHashFunc
)mono_blob_entry_hash
, (GCompareFunc
)mono_blob_entry_equal
);
5769 image
->gen_params
= g_ptr_array_new ();
5770 image
->remapped_tokens
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
, MONO_ROOT_SOURCE_REFLECTION
, "dynamic module remapped tokens table");
5772 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5773 string_heap_init (&image
->sheap
);
5774 mono_image_add_stream_data (&image
->us
, "", 1);
5775 add_to_blob_cached (image
, (char*) "", 1, NULL
, 0);
5776 /* import tables... */
5777 mono_image_add_stream_data (&image
->code
, (char*)entrycode
, sizeof (entrycode
));
5778 image
->iat_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two IAT entries */
5779 image
->idt_offset
= mono_image_add_stream_zero (&image
->code
, 2 * sizeof (MonoIDT
)); /* two IDT entries */
5780 image
->imp_names_offset
= mono_image_add_stream_zero (&image
->code
, 2); /* flags for name entry */
5781 mono_image_add_stream_data (&image
->code
, "_CorExeMain", 12);
5782 mono_image_add_stream_data (&image
->code
, "mscoree.dll", 12);
5783 image
->ilt_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two ILT entries */
5784 stream_data_align (&image
->code
);
5786 image
->cli_header_offset
= mono_image_add_stream_zero (&image
->code
, sizeof (MonoCLIHeader
));
5788 for (i
=0; i
< MONO_TABLE_NUM
; ++i
) {
5789 image
->tables
[i
].next_idx
= 1;
5790 image
->tables
[i
].columns
= table_sizes
[i
];
5793 image
->image
.assembly
= (MonoAssembly
*)assembly
;
5794 image
->run
= assembly
->run
;
5795 image
->save
= assembly
->save
;
5796 image
->pe_kind
= 0x1; /* ILOnly */
5797 image
->machine
= 0x14c; /* I386 */
5799 mono_profiler_module_loaded (&image
->image
, MONO_PROFILE_OK
);
5801 dynamic_images_lock ();
5803 if (!dynamic_images
)
5804 dynamic_images
= g_ptr_array_new ();
5806 g_ptr_array_add (dynamic_images
, image
);
5808 dynamic_images_unlock ();
5815 free_blob_cache_entry (gpointer key
, gpointer val
, gpointer user_data
)
5821 release_hashtable (MonoGHashTable
**hash
)
5824 mono_g_hash_table_destroy (*hash
);
5830 mono_dynamic_image_release_gc_roots (MonoDynamicImage
*image
)
5832 release_hashtable (&image
->token_fixups
);
5833 release_hashtable (&image
->handleref_managed
);
5834 release_hashtable (&image
->tokens
);
5835 release_hashtable (&image
->remapped_tokens
);
5836 release_hashtable (&image
->generic_def_objects
);
5837 release_hashtable (&image
->methodspec
);
5840 // Free dynamic image pass one: Free resources but not image itself
5842 mono_dynamic_image_free (MonoDynamicImage
*image
)
5844 MonoDynamicImage
*di
= image
;
5849 mono_g_hash_table_destroy (di
->methodspec
);
5851 g_hash_table_destroy (di
->typespec
);
5853 g_hash_table_destroy (di
->typeref
);
5855 g_hash_table_destroy (di
->handleref
);
5856 if (di
->handleref_managed
)
5857 mono_g_hash_table_destroy (di
->handleref_managed
);
5859 mono_g_hash_table_destroy (di
->tokens
);
5860 if (di
->remapped_tokens
)
5861 mono_g_hash_table_destroy (di
->remapped_tokens
);
5862 if (di
->generic_def_objects
)
5863 mono_g_hash_table_destroy (di
->generic_def_objects
);
5864 if (di
->blob_cache
) {
5865 g_hash_table_foreach (di
->blob_cache
, free_blob_cache_entry
, NULL
);
5866 g_hash_table_destroy (di
->blob_cache
);
5868 if (di
->standalonesig_cache
)
5869 g_hash_table_destroy (di
->standalonesig_cache
);
5870 for (list
= di
->array_methods
; list
; list
= list
->next
) {
5871 ArrayMethod
*am
= (ArrayMethod
*)list
->data
;
5876 g_list_free (di
->array_methods
);
5877 if (di
->gen_params
) {
5878 for (i
= 0; i
< di
->gen_params
->len
; i
++) {
5879 GenericParamTableEntry
*entry
= (GenericParamTableEntry
*)g_ptr_array_index (di
->gen_params
, i
);
5880 mono_gc_deregister_root ((char*) &entry
->gparam
);
5883 g_ptr_array_free (di
->gen_params
, TRUE
);
5885 if (di
->token_fixups
)
5886 mono_g_hash_table_destroy (di
->token_fixups
);
5887 if (di
->method_to_table_idx
)
5888 g_hash_table_destroy (di
->method_to_table_idx
);
5889 if (di
->field_to_table_idx
)
5890 g_hash_table_destroy (di
->field_to_table_idx
);
5891 if (di
->method_aux_hash
)
5892 g_hash_table_destroy (di
->method_aux_hash
);
5893 if (di
->vararg_aux_hash
)
5894 g_hash_table_destroy (di
->vararg_aux_hash
);
5895 g_free (di
->strong_name
);
5896 g_free (di
->win32_res
);
5898 g_free (di
->public_key
);
5900 /*g_print ("string heap destroy for image %p\n", di);*/
5901 mono_dynamic_stream_reset (&di
->sheap
);
5902 mono_dynamic_stream_reset (&di
->code
);
5903 mono_dynamic_stream_reset (&di
->resources
);
5904 mono_dynamic_stream_reset (&di
->us
);
5905 mono_dynamic_stream_reset (&di
->blob
);
5906 mono_dynamic_stream_reset (&di
->tstream
);
5907 mono_dynamic_stream_reset (&di
->guid
);
5908 for (i
= 0; i
< MONO_TABLE_NUM
; ++i
) {
5909 g_free (di
->tables
[i
].values
);
5912 dynamic_images_lock ();
5915 g_ptr_array_remove (dynamic_images
, di
);
5917 dynamic_images_unlock ();
5920 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5922 mono_dynamic_image_free_image (MonoDynamicImage
*image
)
5924 /* See create_dynamic_mono_image () */
5926 /* Allocated using GC_MALLOC */
5932 #ifndef DISABLE_REFLECTION_EMIT
5935 * mono_image_basic_init:
5936 * @assembly: an assembly builder object
5938 * Create the MonoImage that represents the assembly builder and setup some
5939 * of the helper hash table and the basic metadata streams.
5942 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
5944 MonoDynamicAssembly
*assembly
;
5945 MonoDynamicImage
*image
;
5946 MonoDomain
*domain
= mono_object_domain (assemblyb
);
5948 if (assemblyb
->dynamic_assembly
)
5952 /* assembly->assembly.image might be GC allocated */
5953 assembly
= assemblyb
->dynamic_assembly
= (MonoDynamicAssembly
*)GC_MALLOC (sizeof (MonoDynamicAssembly
));
5955 assembly
= assemblyb
->dynamic_assembly
= g_new0 (MonoDynamicAssembly
, 1);
5958 mono_profiler_assembly_event (&assembly
->assembly
, MONO_PROFILE_START_LOAD
);
5960 assembly
->assembly
.ref_count
= 1;
5961 assembly
->assembly
.dynamic
= TRUE
;
5962 assembly
->assembly
.corlib_internal
= assemblyb
->corlib_internal
;
5963 assemblyb
->assembly
.assembly
= (MonoAssembly
*)assembly
;
5964 assembly
->assembly
.basedir
= mono_string_to_utf8 (assemblyb
->dir
);
5965 if (assemblyb
->culture
)
5966 assembly
->assembly
.aname
.culture
= mono_string_to_utf8 (assemblyb
->culture
);
5968 assembly
->assembly
.aname
.culture
= g_strdup ("");
5970 if (assemblyb
->version
) {
5971 char *vstr
= mono_string_to_utf8 (assemblyb
->version
);
5972 char **version
= g_strsplit (vstr
, ".", 4);
5973 char **parts
= version
;
5974 assembly
->assembly
.aname
.major
= atoi (*parts
++);
5975 assembly
->assembly
.aname
.minor
= atoi (*parts
++);
5976 assembly
->assembly
.aname
.build
= *parts
!= NULL
? atoi (*parts
++) : 0;
5977 assembly
->assembly
.aname
.revision
= *parts
!= NULL
? atoi (*parts
) : 0;
5979 g_strfreev (version
);
5982 assembly
->assembly
.aname
.major
= 0;
5983 assembly
->assembly
.aname
.minor
= 0;
5984 assembly
->assembly
.aname
.build
= 0;
5985 assembly
->assembly
.aname
.revision
= 0;
5988 assembly
->run
= assemblyb
->access
!= 2;
5989 assembly
->save
= assemblyb
->access
!= 1;
5990 assembly
->domain
= domain
;
5992 image
= create_dynamic_mono_image (assembly
, mono_string_to_utf8 (assemblyb
->name
), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5993 image
->initial_image
= TRUE
;
5994 assembly
->assembly
.aname
.name
= image
->image
.name
;
5995 assembly
->assembly
.image
= &image
->image
;
5996 if (assemblyb
->pktoken
&& assemblyb
->pktoken
->max_length
) {
5997 /* -1 to correct for the trailing NULL byte */
5998 if (assemblyb
->pktoken
->max_length
!= MONO_PUBLIC_KEY_TOKEN_LENGTH
- 1) {
5999 g_error ("Public key token length invalid for assembly %s: %i", assembly
->assembly
.aname
.name
, assemblyb
->pktoken
->max_length
);
6001 memcpy (&assembly
->assembly
.aname
.public_key_token
, mono_array_addr (assemblyb
->pktoken
, guint8
, 0), assemblyb
->pktoken
->max_length
);
6004 mono_domain_assemblies_lock (domain
);
6005 domain
->domain_assemblies
= g_slist_append (domain
->domain_assemblies
, assembly
);
6006 mono_domain_assemblies_unlock (domain
);
6008 register_assembly (mono_object_domain (assemblyb
), &assemblyb
->assembly
, &assembly
->assembly
);
6010 mono_profiler_assembly_loaded (&assembly
->assembly
, MONO_PROFILE_OK
);
6012 mono_assembly_invoke_load_hook ((MonoAssembly
*)assembly
);
6015 #endif /* !DISABLE_REFLECTION_EMIT */
6017 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6020 calc_section_size (MonoDynamicImage
*assembly
)
6024 /* alignment constraints */
6025 mono_image_add_stream_zero (&assembly
->code
, 4 - (assembly
->code
.index
% 4));
6026 g_assert ((assembly
->code
.index
% 4) == 0);
6027 assembly
->meta_size
+= 3;
6028 assembly
->meta_size
&= ~3;
6029 mono_image_add_stream_zero (&assembly
->resources
, 4 - (assembly
->resources
.index
% 4));
6030 g_assert ((assembly
->resources
.index
% 4) == 0);
6032 assembly
->sections
[MONO_SECTION_TEXT
].size
= assembly
->meta_size
+ assembly
->code
.index
+ assembly
->resources
.index
+ assembly
->strong_name_size
;
6033 assembly
->sections
[MONO_SECTION_TEXT
].attrs
= SECT_FLAGS_HAS_CODE
| SECT_FLAGS_MEM_EXECUTE
| SECT_FLAGS_MEM_READ
;
6036 if (assembly
->win32_res
) {
6037 guint32 res_size
= (assembly
->win32_res_size
+ 3) & ~3;
6039 assembly
->sections
[MONO_SECTION_RSRC
].size
= res_size
;
6040 assembly
->sections
[MONO_SECTION_RSRC
].attrs
= SECT_FLAGS_HAS_INITIALIZED_DATA
| SECT_FLAGS_MEM_READ
;
6044 assembly
->sections
[MONO_SECTION_RELOC
].size
= 12;
6045 assembly
->sections
[MONO_SECTION_RELOC
].attrs
= SECT_FLAGS_MEM_READ
| SECT_FLAGS_MEM_DISCARDABLE
| SECT_FLAGS_HAS_INITIALIZED_DATA
;
6055 MonoReflectionWin32Resource
*win32_res
; /* Only for leaf nodes */
6059 resource_tree_compare_by_id (gconstpointer a
, gconstpointer b
)
6061 ResTreeNode
*t1
= (ResTreeNode
*)a
;
6062 ResTreeNode
*t2
= (ResTreeNode
*)b
;
6064 return t1
->id
- t2
->id
;
6068 * resource_tree_create:
6070 * Organize the resources into a resource tree.
6072 static ResTreeNode
*
6073 resource_tree_create (MonoArray
*win32_resources
)
6075 ResTreeNode
*tree
, *res_node
, *type_node
, *lang_node
;
6079 tree
= g_new0 (ResTreeNode
, 1);
6081 for (i
= 0; i
< mono_array_length (win32_resources
); ++i
) {
6082 MonoReflectionWin32Resource
*win32_res
=
6083 (MonoReflectionWin32Resource
*)mono_array_addr (win32_resources
, MonoReflectionWin32Resource
, i
);
6087 /* FIXME: BUG: this stores managed references in unmanaged memory */
6088 lang_node
= g_new0 (ResTreeNode
, 1);
6089 lang_node
->id
= win32_res
->lang_id
;
6090 lang_node
->win32_res
= win32_res
;
6092 /* Create type node if neccesary */
6094 for (l
= tree
->children
; l
; l
= l
->next
)
6095 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_type
) {
6096 type_node
= (ResTreeNode
*)l
->data
;
6101 type_node
= g_new0 (ResTreeNode
, 1);
6102 type_node
->id
= win32_res
->res_type
;
6105 * The resource types have to be sorted otherwise
6106 * Windows Explorer can't display the version information.
6108 tree
->children
= g_slist_insert_sorted (tree
->children
,
6109 type_node
, resource_tree_compare_by_id
);
6112 /* Create res node if neccesary */
6114 for (l
= type_node
->children
; l
; l
= l
->next
)
6115 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_id
) {
6116 res_node
= (ResTreeNode
*)l
->data
;
6121 res_node
= g_new0 (ResTreeNode
, 1);
6122 res_node
->id
= win32_res
->res_id
;
6123 type_node
->children
= g_slist_append (type_node
->children
, res_node
);
6126 res_node
->children
= g_slist_append (res_node
->children
, lang_node
);
6133 * resource_tree_encode:
6135 * Encode the resource tree into the format used in the PE file.
6138 resource_tree_encode (ResTreeNode
*node
, char *begin
, char *p
, char **endbuf
)
6141 MonoPEResourceDir dir
;
6142 MonoPEResourceDirEntry dir_entry
;
6143 MonoPEResourceDataEntry data_entry
;
6145 guint32 res_id_entries
;
6148 * For the format of the resource directory, see the article
6149 * "An In-Depth Look into the Win32 Portable Executable File Format" by
6153 memset (&dir
, 0, sizeof (dir
));
6154 memset (&dir_entry
, 0, sizeof (dir_entry
));
6155 memset (&data_entry
, 0, sizeof (data_entry
));
6157 g_assert (sizeof (dir
) == 16);
6158 g_assert (sizeof (dir_entry
) == 8);
6159 g_assert (sizeof (data_entry
) == 16);
6161 node
->offset
= p
- begin
;
6163 /* IMAGE_RESOURCE_DIRECTORY */
6164 res_id_entries
= g_slist_length (node
->children
);
6165 dir
.res_id_entries
= GUINT16_TO_LE (res_id_entries
);
6167 memcpy (p
, &dir
, sizeof (dir
));
6170 /* Reserve space for entries */
6172 p
+= sizeof (dir_entry
) * res_id_entries
;
6174 /* Write children */
6175 for (l
= node
->children
; l
; l
= l
->next
) {
6176 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
6178 if (child
->win32_res
) {
6181 child
->offset
= p
- begin
;
6183 /* IMAGE_RESOURCE_DATA_ENTRY */
6184 data_entry
.rde_data_offset
= GUINT32_TO_LE (p
- begin
+ sizeof (data_entry
));
6185 size
= mono_array_length (child
->win32_res
->res_data
);
6186 data_entry
.rde_size
= GUINT32_TO_LE (size
);
6188 memcpy (p
, &data_entry
, sizeof (data_entry
));
6189 p
+= sizeof (data_entry
);
6191 memcpy (p
, mono_array_addr (child
->win32_res
->res_data
, char, 0), size
);
6194 resource_tree_encode (child
, begin
, p
, &p
);
6198 /* IMAGE_RESOURCE_ENTRY */
6199 for (l
= node
->children
; l
; l
= l
->next
) {
6200 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
6202 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry
, FALSE
, child
->id
);
6203 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry
, !child
->win32_res
, child
->offset
);
6205 memcpy (entries
, &dir_entry
, sizeof (dir_entry
));
6206 entries
+= sizeof (dir_entry
);
6213 resource_tree_free (ResTreeNode
* node
)
6216 for (list
= node
->children
; list
; list
= list
->next
)
6217 resource_tree_free ((ResTreeNode
*)list
->data
);
6218 g_slist_free(node
->children
);
6223 assembly_add_win32_resources (MonoDynamicImage
*assembly
, MonoReflectionAssemblyBuilder
*assemblyb
)
6228 MonoReflectionWin32Resource
*win32_res
;
6231 if (!assemblyb
->win32_resources
)
6235 * Resources are stored in a three level tree inside the PE file.
6236 * - level one contains a node for each type of resource
6237 * - level two contains a node for each resource
6238 * - level three contains a node for each instance of a resource for a
6239 * specific language.
6242 tree
= resource_tree_create (assemblyb
->win32_resources
);
6244 /* Estimate the size of the encoded tree */
6246 for (i
= 0; i
< mono_array_length (assemblyb
->win32_resources
); ++i
) {
6247 win32_res
= (MonoReflectionWin32Resource
*)mono_array_addr (assemblyb
->win32_resources
, MonoReflectionWin32Resource
, i
);
6248 size
+= mono_array_length (win32_res
->res_data
);
6250 /* Directory structure */
6251 size
+= mono_array_length (assemblyb
->win32_resources
) * 256;
6252 p
= buf
= (char *)g_malloc (size
);
6254 resource_tree_encode (tree
, p
, p
, &p
);
6256 g_assert (p
- buf
<= size
);
6258 assembly
->win32_res
= (char *)g_malloc (p
- buf
);
6259 assembly
->win32_res_size
= p
- buf
;
6260 memcpy (assembly
->win32_res
, buf
, p
- buf
);
6263 resource_tree_free (tree
);
6267 fixup_resource_directory (char *res_section
, char *p
, guint32 rva
)
6269 MonoPEResourceDir
*dir
= (MonoPEResourceDir
*)p
;
6272 p
+= sizeof (MonoPEResourceDir
);
6273 for (i
= 0; i
< GUINT16_FROM_LE (dir
->res_named_entries
) + GUINT16_FROM_LE (dir
->res_id_entries
); ++i
) {
6274 MonoPEResourceDirEntry
*dir_entry
= (MonoPEResourceDirEntry
*)p
;
6275 char *child
= res_section
+ MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry
);
6276 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry
)) {
6277 fixup_resource_directory (res_section
, child
, rva
);
6279 MonoPEResourceDataEntry
*data_entry
= (MonoPEResourceDataEntry
*)child
;
6280 data_entry
->rde_data_offset
= GUINT32_TO_LE (GUINT32_FROM_LE (data_entry
->rde_data_offset
) + rva
);
6283 p
+= sizeof (MonoPEResourceDirEntry
);
6288 checked_write_file (HANDLE f
, gconstpointer buffer
, guint32 numbytes
)
6291 if (!WriteFile (f
, buffer
, numbytes
, &dummy
, NULL
))
6292 g_error ("WriteFile returned %d\n", GetLastError ());
6296 * mono_image_create_pefile:
6297 * @mb: a module builder object
6299 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
6300 * assembly->pefile where it can be easily retrieved later in chunks.
6303 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
, MonoError
*error
)
6305 MonoMSDOSHeader
*msdos
;
6306 MonoDotNetHeader
*header
;
6307 MonoSectionTable
*section
;
6308 MonoCLIHeader
*cli_header
;
6309 guint32 size
, image_size
, virtual_base
, text_offset
;
6310 guint32 header_start
, section_start
, file_offset
, virtual_offset
;
6311 MonoDynamicImage
*assembly
;
6312 MonoReflectionAssemblyBuilder
*assemblyb
;
6313 MonoDynamicStream pefile_stream
= {0};
6314 MonoDynamicStream
*pefile
= &pefile_stream
;
6316 guint32
*rva
, value
;
6318 static const unsigned char msheader
[] = {
6319 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6320 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6323 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6324 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6325 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6326 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6329 mono_error_init (error
);
6331 assemblyb
= mb
->assemblyb
;
6333 mono_image_basic_init (assemblyb
);
6334 assembly
= mb
->dynamic_image
;
6336 assembly
->pe_kind
= assemblyb
->pe_kind
;
6337 assembly
->machine
= assemblyb
->machine
;
6338 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->pe_kind
= assemblyb
->pe_kind
;
6339 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->machine
= assemblyb
->machine
;
6341 if (!mono_image_build_metadata (mb
, error
))
6345 if (mb
->is_main
&& assemblyb
->resources
) {
6346 int len
= mono_array_length (assemblyb
->resources
);
6347 for (i
= 0; i
< len
; ++i
)
6348 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (assemblyb
->resources
, MonoReflectionResource
, i
));
6351 if (mb
->resources
) {
6352 int len
= mono_array_length (mb
->resources
);
6353 for (i
= 0; i
< len
; ++i
)
6354 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (mb
->resources
, MonoReflectionResource
, i
));
6357 if (!build_compressed_metadata (assembly
, error
))
6361 assembly_add_win32_resources (assembly
, assemblyb
);
6363 nsections
= calc_section_size (assembly
);
6365 /* The DOS header and stub */
6366 g_assert (sizeof (MonoMSDOSHeader
) == sizeof (msheader
));
6367 mono_image_add_stream_data (pefile
, (char*)msheader
, sizeof (msheader
));
6369 /* the dotnet header */
6370 header_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoDotNetHeader
));
6372 /* the section tables */
6373 section_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoSectionTable
) * nsections
);
6375 file_offset
= section_start
+ sizeof (MonoSectionTable
) * nsections
;
6376 virtual_offset
= VIRT_ALIGN
;
6379 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
6380 if (!assembly
->sections
[i
].size
)
6383 file_offset
+= FILE_ALIGN
- 1;
6384 file_offset
&= ~(FILE_ALIGN
- 1);
6385 virtual_offset
+= VIRT_ALIGN
- 1;
6386 virtual_offset
&= ~(VIRT_ALIGN
- 1);
6388 assembly
->sections
[i
].offset
= file_offset
;
6389 assembly
->sections
[i
].rva
= virtual_offset
;
6391 file_offset
+= assembly
->sections
[i
].size
;
6392 virtual_offset
+= assembly
->sections
[i
].size
;
6393 image_size
+= (assembly
->sections
[i
].size
+ VIRT_ALIGN
- 1) & ~(VIRT_ALIGN
- 1);
6396 file_offset
+= FILE_ALIGN
- 1;
6397 file_offset
&= ~(FILE_ALIGN
- 1);
6399 image_size
+= section_start
+ sizeof (MonoSectionTable
) * nsections
;
6401 /* back-patch info */
6402 msdos
= (MonoMSDOSHeader
*)pefile
->data
;
6403 msdos
->pe_offset
= GUINT32_FROM_LE (sizeof (MonoMSDOSHeader
));
6405 header
= (MonoDotNetHeader
*)(pefile
->data
+ header_start
);
6406 header
->pesig
[0] = 'P';
6407 header
->pesig
[1] = 'E';
6409 header
->coff
.coff_machine
= GUINT16_FROM_LE (assemblyb
->machine
);
6410 header
->coff
.coff_sections
= GUINT16_FROM_LE (nsections
);
6411 header
->coff
.coff_time
= GUINT32_FROM_LE (time (NULL
));
6412 header
->coff
.coff_opt_header_size
= GUINT16_FROM_LE (sizeof (MonoDotNetHeader
) - sizeof (MonoCOFFHeader
) - 4);
6413 if (assemblyb
->pekind
== 1) {
6415 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x210e);
6418 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x010e);
6421 virtual_base
= 0x400000; /* FIXME: 0x10000000 if a DLL */
6423 header
->pe
.pe_magic
= GUINT16_FROM_LE (0x10B);
6424 header
->pe
.pe_major
= 6;
6425 header
->pe
.pe_minor
= 0;
6426 size
= assembly
->sections
[MONO_SECTION_TEXT
].size
;
6427 size
+= FILE_ALIGN
- 1;
6428 size
&= ~(FILE_ALIGN
- 1);
6429 header
->pe
.pe_code_size
= GUINT32_FROM_LE(size
);
6430 size
= assembly
->sections
[MONO_SECTION_RSRC
].size
;
6431 size
+= FILE_ALIGN
- 1;
6432 size
&= ~(FILE_ALIGN
- 1);
6433 header
->pe
.pe_data_size
= GUINT32_FROM_LE(size
);
6434 g_assert (START_TEXT_RVA
== assembly
->sections
[MONO_SECTION_TEXT
].rva
);
6435 header
->pe
.pe_rva_code_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
6436 header
->pe
.pe_rva_data_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
6437 /* pe_rva_entry_point always at the beginning of the text section */
6438 header
->pe
.pe_rva_entry_point
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
6440 header
->nt
.pe_image_base
= GUINT32_FROM_LE (virtual_base
);
6441 header
->nt
.pe_section_align
= GUINT32_FROM_LE (VIRT_ALIGN
);
6442 header
->nt
.pe_file_alignment
= GUINT32_FROM_LE (FILE_ALIGN
);
6443 header
->nt
.pe_os_major
= GUINT16_FROM_LE (4);
6444 header
->nt
.pe_os_minor
= GUINT16_FROM_LE (0);
6445 header
->nt
.pe_subsys_major
= GUINT16_FROM_LE (4);
6446 size
= section_start
;
6447 size
+= FILE_ALIGN
- 1;
6448 size
&= ~(FILE_ALIGN
- 1);
6449 header
->nt
.pe_header_size
= GUINT32_FROM_LE (size
);
6451 size
+= VIRT_ALIGN
- 1;
6452 size
&= ~(VIRT_ALIGN
- 1);
6453 header
->nt
.pe_image_size
= GUINT32_FROM_LE (size
);
6456 // Translate the PEFileKind value to the value expected by the Windows loader
6462 // PEFileKinds.Dll == 1
6463 // PEFileKinds.ConsoleApplication == 2
6464 // PEFileKinds.WindowApplication == 3
6467 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6468 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6470 if (assemblyb
->pekind
== 3)
6475 header
->nt
.pe_subsys_required
= GUINT16_FROM_LE (kind
);
6477 header
->nt
.pe_stack_reserve
= GUINT32_FROM_LE (0x00100000);
6478 header
->nt
.pe_stack_commit
= GUINT32_FROM_LE (0x00001000);
6479 header
->nt
.pe_heap_reserve
= GUINT32_FROM_LE (0x00100000);
6480 header
->nt
.pe_heap_commit
= GUINT32_FROM_LE (0x00001000);
6481 header
->nt
.pe_loader_flags
= GUINT32_FROM_LE (0);
6482 header
->nt
.pe_data_dir_count
= GUINT32_FROM_LE (16);
6484 /* fill data directory entries */
6486 header
->datadir
.pe_resource_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].size
);
6487 header
->datadir
.pe_resource_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
6489 header
->datadir
.pe_reloc_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].size
);
6490 header
->datadir
.pe_reloc_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].rva
);
6492 header
->datadir
.pe_cli_header
.size
= GUINT32_FROM_LE (72);
6493 header
->datadir
.pe_cli_header
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->cli_header_offset
);
6494 header
->datadir
.pe_iat
.size
= GUINT32_FROM_LE (8);
6495 header
->datadir
.pe_iat
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
6496 /* patch entrypoint name */
6497 if (assemblyb
->pekind
== 1)
6498 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorDllMain", 12);
6500 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorExeMain", 12);
6501 /* patch imported function RVA name */
6502 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->iat_offset
);
6503 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
);
6505 /* the import table */
6506 header
->datadir
.pe_import_table
.size
= GUINT32_FROM_LE (79); /* FIXME: magic number? */
6507 header
->datadir
.pe_import_table
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->idt_offset
);
6508 /* patch imported dll RVA name and other entries in the dir */
6509 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, name_rva
));
6510 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
+ 14); /* 14 is hint+strlen+1 of func name */
6511 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_address_table_rva
));
6512 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
6513 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_lookup_table
));
6514 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->ilt_offset
);
6516 p
= (guchar
*)(assembly
->code
.data
+ assembly
->ilt_offset
);
6517 value
= (assembly
->text_rva
+ assembly
->imp_names_offset
);
6518 *p
++ = (value
) & 0xff;
6519 *p
++ = (value
>> 8) & (0xff);
6520 *p
++ = (value
>> 16) & (0xff);
6521 *p
++ = (value
>> 24) & (0xff);
6523 /* the CLI header info */
6524 cli_header
= (MonoCLIHeader
*)(assembly
->code
.data
+ assembly
->cli_header_offset
);
6525 cli_header
->ch_size
= GUINT32_FROM_LE (72);
6526 cli_header
->ch_runtime_major
= GUINT16_FROM_LE (2);
6527 cli_header
->ch_runtime_minor
= GUINT16_FROM_LE (5);
6528 cli_header
->ch_flags
= GUINT32_FROM_LE (assemblyb
->pe_kind
);
6529 if (assemblyb
->entry_point
) {
6530 guint32 table_idx
= 0;
6531 if (!strcmp (assemblyb
->entry_point
->object
.vtable
->klass
->name
, "MethodBuilder")) {
6532 MonoReflectionMethodBuilder
*methodb
= (MonoReflectionMethodBuilder
*)assemblyb
->entry_point
;
6533 table_idx
= methodb
->table_idx
;
6535 table_idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, assemblyb
->entry_point
->method
));
6537 cli_header
->ch_entry_point
= GUINT32_FROM_LE (table_idx
| MONO_TOKEN_METHOD_DEF
);
6539 cli_header
->ch_entry_point
= GUINT32_FROM_LE (0);
6541 /* The embedded managed resources */
6542 text_offset
= assembly
->text_rva
+ assembly
->code
.index
;
6543 cli_header
->ch_resources
.rva
= GUINT32_FROM_LE (text_offset
);
6544 cli_header
->ch_resources
.size
= GUINT32_FROM_LE (assembly
->resources
.index
);
6545 text_offset
+= assembly
->resources
.index
;
6546 cli_header
->ch_metadata
.rva
= GUINT32_FROM_LE (text_offset
);
6547 cli_header
->ch_metadata
.size
= GUINT32_FROM_LE (assembly
->meta_size
);
6548 text_offset
+= assembly
->meta_size
;
6549 if (assembly
->strong_name_size
) {
6550 cli_header
->ch_strong_name
.rva
= GUINT32_FROM_LE (text_offset
);
6551 cli_header
->ch_strong_name
.size
= GUINT32_FROM_LE (assembly
->strong_name_size
);
6552 text_offset
+= assembly
->strong_name_size
;
6555 /* write the section tables and section content */
6556 section
= (MonoSectionTable
*)(pefile
->data
+ section_start
);
6557 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
6558 static const char section_names
[][7] = {
6559 ".text", ".rsrc", ".reloc"
6561 if (!assembly
->sections
[i
].size
)
6563 strcpy (section
->st_name
, section_names
[i
]);
6564 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6565 section
->st_virtual_address
= GUINT32_FROM_LE (assembly
->sections
[i
].rva
);
6566 section
->st_virtual_size
= GUINT32_FROM_LE (assembly
->sections
[i
].size
);
6567 section
->st_raw_data_size
= GUINT32_FROM_LE (GUINT32_TO_LE (section
->st_virtual_size
) + (FILE_ALIGN
- 1));
6568 section
->st_raw_data_size
&= GUINT32_FROM_LE (~(FILE_ALIGN
- 1));
6569 section
->st_raw_data_ptr
= GUINT32_FROM_LE (assembly
->sections
[i
].offset
);
6570 section
->st_flags
= GUINT32_FROM_LE (assembly
->sections
[i
].attrs
);
6574 checked_write_file (file
, pefile
->data
, pefile
->index
);
6576 mono_dynamic_stream_reset (pefile
);
6578 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
6579 if (!assembly
->sections
[i
].size
)
6582 if (SetFilePointer (file
, assembly
->sections
[i
].offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
6583 g_error ("SetFilePointer returned %d\n", GetLastError ());
6586 case MONO_SECTION_TEXT
:
6587 /* patch entry point */
6588 p
= (guchar
*)(assembly
->code
.data
+ 2);
6589 value
= (virtual_base
+ assembly
->text_rva
+ assembly
->iat_offset
);
6590 *p
++ = (value
) & 0xff;
6591 *p
++ = (value
>> 8) & 0xff;
6592 *p
++ = (value
>> 16) & 0xff;
6593 *p
++ = (value
>> 24) & 0xff;
6595 checked_write_file (file
, assembly
->code
.data
, assembly
->code
.index
);
6596 checked_write_file (file
, assembly
->resources
.data
, assembly
->resources
.index
);
6597 checked_write_file (file
, assembly
->image
.raw_metadata
, assembly
->meta_size
);
6598 checked_write_file (file
, assembly
->strong_name
, assembly
->strong_name_size
);
6601 g_free (assembly
->image
.raw_metadata
);
6603 case MONO_SECTION_RELOC
: {
6607 guint16 type_and_offset
;
6611 g_assert (sizeof (reloc
) == 12);
6613 reloc
.page_rva
= GUINT32_FROM_LE (assembly
->text_rva
);
6614 reloc
.block_size
= GUINT32_FROM_LE (12);
6617 * the entrypoint is always at the start of the text section
6618 * 3 is IMAGE_REL_BASED_HIGHLOW
6619 * 2 is patch_size_rva - text_rva
6621 reloc
.type_and_offset
= GUINT16_FROM_LE ((3 << 12) + (2));
6624 checked_write_file (file
, &reloc
, sizeof (reloc
));
6628 case MONO_SECTION_RSRC
:
6629 if (assembly
->win32_res
) {
6631 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6632 fixup_resource_directory (assembly
->win32_res
, assembly
->win32_res
, assembly
->sections
[i
].rva
);
6633 checked_write_file (file
, assembly
->win32_res
, assembly
->win32_res_size
);
6637 g_assert_not_reached ();
6641 /* check that the file is properly padded */
6642 if (SetFilePointer (file
, file_offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
6643 g_error ("SetFilePointer returned %d\n", GetLastError ());
6644 if (! SetEndOfFile (file
))
6645 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6647 mono_dynamic_stream_reset (&assembly
->code
);
6648 mono_dynamic_stream_reset (&assembly
->us
);
6649 mono_dynamic_stream_reset (&assembly
->blob
);
6650 mono_dynamic_stream_reset (&assembly
->guid
);
6651 mono_dynamic_stream_reset (&assembly
->sheap
);
6653 g_hash_table_foreach (assembly
->blob_cache
, (GHFunc
)g_free
, NULL
);
6654 g_hash_table_destroy (assembly
->blob_cache
);
6655 assembly
->blob_cache
= NULL
;
6660 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6663 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
, MonoError
*error
)
6665 g_assert_not_reached ();
6668 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6670 #ifndef DISABLE_REFLECTION_EMIT
6672 MonoReflectionModule
*
6673 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
, MonoError
*error
)
6677 MonoImageOpenStatus status
;
6678 MonoDynamicAssembly
*assembly
;
6679 guint32 module_count
;
6680 MonoImage
**new_modules
;
6681 gboolean
*new_modules_loaded
;
6683 mono_error_init (error
);
6685 name
= mono_string_to_utf8 (fileName
);
6687 image
= mono_image_open (name
, &status
);
6689 if (status
== MONO_IMAGE_ERROR_ERRNO
)
6690 mono_error_set_exception_instance (error
, mono_get_exception_file_not_found (fileName
));
6692 mono_error_set_bad_image_name (error
, name
, NULL
);
6699 assembly
= ab
->dynamic_assembly
;
6700 image
->assembly
= (MonoAssembly
*)assembly
;
6702 module_count
= image
->assembly
->image
->module_count
;
6703 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
6704 new_modules_loaded
= g_new0 (gboolean
, module_count
+ 1);
6706 if (image
->assembly
->image
->modules
)
6707 memcpy (new_modules
, image
->assembly
->image
->modules
, module_count
* sizeof (MonoImage
*));
6708 if (image
->assembly
->image
->modules_loaded
)
6709 memcpy (new_modules_loaded
, image
->assembly
->image
->modules_loaded
, module_count
* sizeof (gboolean
));
6710 new_modules
[module_count
] = image
;
6711 new_modules_loaded
[module_count
] = TRUE
;
6712 mono_image_addref (image
);
6714 g_free (image
->assembly
->image
->modules
);
6715 image
->assembly
->image
->modules
= new_modules
;
6716 image
->assembly
->image
->modules_loaded
= new_modules_loaded
;
6717 image
->assembly
->image
->module_count
++;
6719 mono_assembly_load_references (image
, &status
);
6721 mono_image_close (image
);
6722 mono_error_set_exception_instance (error
, mono_get_exception_file_not_found (fileName
));
6726 return mono_module_get_object_checked (mono_domain_get (), image
, error
);
6729 #endif /* DISABLE_REFLECTION_EMIT */
6732 * We need to return always the same object for MethodInfo, FieldInfo etc..
6733 * but we need to consider the reflected type.
6734 * type uses a different hash, since it uses custom hash/equal functions.
6739 MonoClass
*refclass
;
6743 reflected_equal (gconstpointer a
, gconstpointer b
) {
6744 const ReflectedEntry
*ea
= (const ReflectedEntry
*)a
;
6745 const ReflectedEntry
*eb
= (const ReflectedEntry
*)b
;
6747 return (ea
->item
== eb
->item
) && (ea
->refclass
== eb
->refclass
);
6751 reflected_hash (gconstpointer a
) {
6752 const ReflectedEntry
*ea
= (const ReflectedEntry
*)a
;
6753 return mono_aligned_addr_hash (ea
->item
);
6756 #define CHECK_OBJECT(t,p,k) \
6762 mono_domain_lock (domain); \
6763 if (!domain->refobject_hash) \
6764 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6765 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6766 mono_domain_unlock (domain); \
6769 mono_domain_unlock (domain); \
6772 #ifdef HAVE_BOEHM_GC
6773 /* ReflectedEntry doesn't need to be GC tracked */
6774 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6775 #define FREE_REFENTRY(entry) g_free ((entry))
6776 #define REFENTRY_REQUIRES_CLEANUP
6778 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6780 #define FREE_REFENTRY(entry)
6783 #define CACHE_OBJECT(t,p,o,k) \
6786 ReflectedEntry pe; \
6788 pe.refclass = (k); \
6789 mono_domain_lock (domain); \
6790 if (!domain->refobject_hash) \
6791 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table"); \
6792 _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6794 ReflectedEntry *e = ALLOC_REFENTRY; \
6796 e->refclass = (k); \
6797 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6800 mono_domain_unlock (domain); \
6805 clear_cached_object (MonoDomain
*domain
, gpointer o
, MonoClass
*klass
)
6807 mono_domain_lock (domain
);
6808 if (domain
->refobject_hash
) {
6810 gpointer orig_pe
, orig_value
;
6813 pe
.refclass
= klass
;
6814 if (mono_g_hash_table_lookup_extended (domain
->refobject_hash
, &pe
, &orig_pe
, &orig_value
)) {
6815 mono_g_hash_table_remove (domain
->refobject_hash
, &pe
);
6816 FREE_REFENTRY (orig_pe
);
6819 mono_domain_unlock (domain
);
6822 #ifdef REFENTRY_REQUIRES_CLEANUP
6824 cleanup_refobject_hash (gpointer key
, gpointer value
, gpointer user_data
)
6826 FREE_REFENTRY (key
);
6831 mono_reflection_cleanup_domain (MonoDomain
*domain
)
6833 if (domain
->refobject_hash
) {
6834 /*let's avoid scanning the whole hashtable if not needed*/
6835 #ifdef REFENTRY_REQUIRES_CLEANUP
6836 mono_g_hash_table_foreach (domain
->refobject_hash
, cleanup_refobject_hash
, NULL
);
6838 mono_g_hash_table_destroy (domain
->refobject_hash
);
6839 domain
->refobject_hash
= NULL
;
6843 #ifndef DISABLE_REFLECTION_EMIT
6845 register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
)
6847 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
6851 register_module (MonoDomain
*domain
, MonoReflectionModuleBuilder
*res
, MonoDynamicImage
*module
)
6853 CACHE_OBJECT (MonoReflectionModuleBuilder
*, module
, res
, NULL
);
6857 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
6859 MonoDynamicImage
*image
= moduleb
->dynamic_image
;
6860 MonoReflectionAssemblyBuilder
*ab
= moduleb
->assemblyb
;
6864 MonoImage
**new_modules
;
6866 char *name
, *fqname
;
6868 * FIXME: we already created an image in mono_image_basic_init (), but
6869 * we don't know which module it belongs to, since that is only
6870 * determined at assembly save time.
6872 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6873 name
= mono_string_to_utf8 (ab
->name
);
6874 fqname
= mono_string_to_utf8_checked (moduleb
->module
.fqname
, &error
);
6875 if (!mono_error_ok (&error
)) {
6877 mono_error_raise_exception (&error
);
6879 image
= create_dynamic_mono_image (ab
->dynamic_assembly
, name
, fqname
);
6881 moduleb
->module
.image
= &image
->image
;
6882 moduleb
->dynamic_image
= image
;
6883 register_module (mono_object_domain (moduleb
), moduleb
, image
);
6885 /* register the module with the assembly */
6886 ass
= ab
->dynamic_assembly
->assembly
.image
;
6887 module_count
= ass
->module_count
;
6888 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
6891 memcpy (new_modules
, ass
->modules
, module_count
* sizeof (MonoImage
*));
6892 new_modules
[module_count
] = &image
->image
;
6893 mono_image_addref (&image
->image
);
6895 g_free (ass
->modules
);
6896 ass
->modules
= new_modules
;
6897 ass
->module_count
++;
6902 mono_image_set_wrappers_type (MonoReflectionModuleBuilder
*moduleb
, MonoReflectionType
*type
)
6904 MonoDynamicImage
*image
= moduleb
->dynamic_image
;
6906 g_assert (type
->type
);
6907 image
->wrappers_type
= mono_class_from_mono_type (type
->type
);
6913 * mono_assembly_get_object:
6914 * @domain: an app domain
6915 * @assembly: an assembly
6917 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6919 MonoReflectionAssembly
*
6920 mono_assembly_get_object (MonoDomain
*domain
, MonoAssembly
*assembly
)
6923 MonoReflectionAssembly
*result
;
6924 result
= mono_assembly_get_object_checked (domain
, assembly
, &error
);
6925 mono_error_cleanup (&error
); /* FIXME new API that doesn't swallow the error */
6929 * mono_assembly_get_object_checked:
6930 * @domain: an app domain
6931 * @assembly: an assembly
6933 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6935 MonoReflectionAssembly
*
6936 mono_assembly_get_object_checked (MonoDomain
*domain
, MonoAssembly
*assembly
, MonoError
*error
)
6938 MonoReflectionAssembly
*res
;
6940 mono_error_init (error
);
6942 CHECK_OBJECT (MonoReflectionAssembly
*, assembly
, NULL
);
6943 res
= (MonoReflectionAssembly
*)mono_object_new_checked (domain
, mono_class_get_mono_assembly_class (), error
);
6946 res
->assembly
= assembly
;
6948 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
6953 MonoReflectionModule
*
6954 mono_module_get_object (MonoDomain
*domain
, MonoImage
*image
)
6957 MonoReflectionModule
*result
;
6958 result
= mono_module_get_object_checked (domain
, image
, &error
);
6959 mono_error_raise_exception (&error
);
6963 MonoReflectionModule
*
6964 mono_module_get_object_checked (MonoDomain
*domain
, MonoImage
*image
, MonoError
*error
)
6966 MonoReflectionModule
*res
;
6969 mono_error_init (error
);
6970 CHECK_OBJECT (MonoReflectionModule
*, image
, NULL
);
6971 res
= (MonoReflectionModule
*)mono_object_new_checked (domain
, mono_class_get_mono_module_class (), error
);
6976 MonoReflectionAssembly
*assm_obj
= mono_assembly_get_object_checked (domain
, image
->assembly
, error
);
6979 MONO_OBJECT_SETREF (res
, assembly
, assm_obj
);
6981 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, image
->name
));
6982 basename
= g_path_get_basename (image
->name
);
6983 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, basename
));
6984 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, image
->module_name
));
6988 if (image
->assembly
->image
== image
) {
6989 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULE
, 1);
6993 if (image
->assembly
->image
->modules
) {
6994 for (i
= 0; i
< image
->assembly
->image
->module_count
; i
++) {
6995 if (image
->assembly
->image
->modules
[i
] == image
)
6996 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULEREF
, i
+ 1);
6998 g_assert (res
->token
);
7002 CACHE_OBJECT (MonoReflectionModule
*, image
, res
, NULL
);
7005 MonoReflectionModule
*
7006 mono_module_file_get_object (MonoDomain
*domain
, MonoImage
*image
, int table_index
)
7009 MonoReflectionModule
*result
;
7010 result
= mono_module_file_get_object_checked (domain
, image
, table_index
, &error
);
7011 mono_error_cleanup (&error
); /* FIXME new API that doesn't swallow the error */
7015 MonoReflectionModule
*
7016 mono_module_file_get_object_checked (MonoDomain
*domain
, MonoImage
*image
, int table_index
, MonoError
*error
)
7018 MonoReflectionModule
*res
;
7019 MonoTableInfo
*table
;
7020 guint32 cols
[MONO_FILE_SIZE
];
7022 guint32 i
, name_idx
;
7025 mono_error_init (error
);
7027 res
= (MonoReflectionModule
*)mono_object_new_checked (domain
, mono_class_get_mono_module_class (), error
);
7031 table
= &image
->tables
[MONO_TABLE_FILE
];
7032 g_assert (table_index
< table
->rows
);
7033 mono_metadata_decode_row (table
, table_index
, cols
, MONO_FILE_SIZE
);
7036 MonoReflectionAssembly
*assm_obj
= mono_assembly_get_object_checked (domain
, image
->assembly
, error
);
7039 MONO_OBJECT_SETREF (res
, assembly
, assm_obj
);
7040 name
= mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]);
7042 /* Check whenever the row has a corresponding row in the moduleref table */
7043 table
= &image
->tables
[MONO_TABLE_MODULEREF
];
7044 for (i
= 0; i
< table
->rows
; ++i
) {
7045 name_idx
= mono_metadata_decode_row_col (table
, i
, MONO_MODULEREF_NAME
);
7046 val
= mono_metadata_string_heap (image
, name_idx
);
7047 if (strcmp (val
, name
) == 0)
7048 res
->image
= image
->modules
[i
];
7051 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, name
));
7052 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, name
));
7053 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, name
));
7054 res
->is_resource
= cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
;
7055 res
->token
= mono_metadata_make_token (MONO_TABLE_FILE
, table_index
+ 1);
7061 verify_safe_for_managed_space (MonoType
*type
)
7063 switch (type
->type
) {
7065 case MONO_TYPE_ARRAY
:
7066 return verify_safe_for_managed_space (&type
->data
.array
->eklass
->byval_arg
);
7068 return verify_safe_for_managed_space (type
->data
.type
);
7069 case MONO_TYPE_SZARRAY
:
7070 return verify_safe_for_managed_space (&type
->data
.klass
->byval_arg
);
7071 case MONO_TYPE_GENERICINST
: {
7072 MonoGenericInst
*inst
= type
->data
.generic_class
->inst
;
7076 for (i
= 0; i
< inst
->type_argc
; ++i
)
7077 if (!verify_safe_for_managed_space (inst
->type_argv
[i
]))
7083 case MONO_TYPE_MVAR
:
7091 mono_type_normalize (MonoType
*type
)
7094 MonoGenericClass
*gclass
;
7095 MonoGenericInst
*ginst
;
7097 MonoGenericContainer
*gcontainer
;
7098 MonoType
**argv
= NULL
;
7099 gboolean is_denorm_gtd
= TRUE
, requires_rebind
= FALSE
;
7101 if (type
->type
!= MONO_TYPE_GENERICINST
)
7104 gclass
= type
->data
.generic_class
;
7105 ginst
= gclass
->context
.class_inst
;
7106 if (!ginst
->is_open
)
7109 gtd
= gclass
->container_class
;
7110 gcontainer
= gtd
->generic_container
;
7111 argv
= g_newa (MonoType
*, ginst
->type_argc
);
7113 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
7114 MonoType
*t
= ginst
->type_argv
[i
], *norm
;
7115 if (t
->type
!= MONO_TYPE_VAR
|| t
->data
.generic_param
->num
!= i
|| t
->data
.generic_param
->owner
!= gcontainer
)
7116 is_denorm_gtd
= FALSE
;
7117 norm
= mono_type_normalize (t
);
7120 requires_rebind
= TRUE
;
7124 return type
->byref
== gtd
->byval_arg
.byref
? >d
->byval_arg
: >d
->this_arg
;
7126 if (requires_rebind
) {
7127 MonoClass
*klass
= mono_class_bind_generic_parameters (gtd
, ginst
->type_argc
, argv
, gclass
->is_dynamic
);
7128 return type
->byref
== klass
->byval_arg
.byref
? &klass
->byval_arg
: &klass
->this_arg
;
7134 * mono_type_get_object:
7135 * @domain: an app domain
7138 * Return an System.MonoType object representing the type @type.
7141 mono_type_get_object (MonoDomain
*domain
, MonoType
*type
)
7144 MonoReflectionType
*ret
= mono_type_get_object_checked (domain
, type
, &error
);
7145 mono_error_raise_exception (&error
);
7151 mono_type_get_object_checked (MonoDomain
*domain
, MonoType
*type
, MonoError
*error
)
7153 MonoType
*norm_type
;
7154 MonoReflectionType
*res
;
7157 mono_error_init (error
);
7159 klass
= mono_class_from_mono_type (type
);
7161 /*we must avoid using @type as it might have come
7162 * from a mono_metadata_type_dup and the caller
7163 * expects that is can be freed.
7164 * Using the right type from
7166 type
= klass
->byval_arg
.byref
== type
->byref
? &klass
->byval_arg
: &klass
->this_arg
;
7168 /* void is very common */
7169 if (type
->type
== MONO_TYPE_VOID
&& domain
->typeof_void
)
7170 return (MonoReflectionType
*)domain
->typeof_void
;
7173 * If the vtable of the given class was already created, we can use
7174 * the MonoType from there and avoid all locking and hash table lookups.
7176 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7177 * that the resulting object is different.
7179 if (type
== &klass
->byval_arg
&& !image_is_dynamic (klass
->image
)) {
7180 MonoVTable
*vtable
= mono_class_try_get_vtable (domain
, klass
);
7181 if (vtable
&& vtable
->type
)
7182 return (MonoReflectionType
*)vtable
->type
;
7185 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7186 mono_domain_lock (domain
);
7187 if (!domain
->type_hash
)
7188 domain
->type_hash
= mono_g_hash_table_new_type ((GHashFunc
)mono_metadata_type_hash
,
7189 (GCompareFunc
)mono_metadata_type_equal
, MONO_HASH_VALUE_GC
, MONO_ROOT_SOURCE_DOMAIN
, "domain reflection types table");
7190 if ((res
= (MonoReflectionType
*)mono_g_hash_table_lookup (domain
->type_hash
, type
))) {
7191 mono_domain_unlock (domain
);
7192 mono_loader_unlock ();
7196 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7197 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7198 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7199 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7200 * artifact of how generics are encoded and should be transparent to managed code so we
7201 * need to weed out this diference when retrieving managed System.Type objects.
7203 norm_type
= mono_type_normalize (type
);
7204 if (norm_type
!= type
) {
7205 res
= mono_type_get_object_checked (domain
, norm_type
, error
);
7206 if (!mono_error_ok (error
))
7208 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
7209 mono_domain_unlock (domain
);
7210 mono_loader_unlock ();
7214 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7215 if ((type
->type
== MONO_TYPE_GENERICINST
) && type
->data
.generic_class
->is_dynamic
&& !type
->data
.generic_class
->container_class
->wastypebuilder
)
7218 if (!verify_safe_for_managed_space (type
)) {
7219 mono_domain_unlock (domain
);
7220 mono_loader_unlock ();
7221 mono_error_set_generic_error (error
, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7225 if (mono_class_get_ref_info (klass
) && !klass
->wastypebuilder
) {
7226 gboolean is_type_done
= TRUE
;
7227 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7228 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7229 * We can't simply close the types as this will interfere with other parts of the generics machinery.
7231 if (klass
->byval_arg
.type
== MONO_TYPE_MVAR
|| klass
->byval_arg
.type
== MONO_TYPE_VAR
) {
7232 MonoGenericParam
*gparam
= klass
->byval_arg
.data
.generic_param
;
7234 if (gparam
->owner
&& gparam
->owner
->is_method
) {
7235 MonoMethod
*method
= gparam
->owner
->owner
.method
;
7236 if (method
&& mono_class_get_generic_type_definition (method
->klass
)->wastypebuilder
)
7237 is_type_done
= FALSE
;
7238 } else if (gparam
->owner
&& !gparam
->owner
->is_method
) {
7239 MonoClass
*klass
= gparam
->owner
->owner
.klass
;
7240 if (klass
&& mono_class_get_generic_type_definition (klass
)->wastypebuilder
)
7241 is_type_done
= FALSE
;
7245 /* g_assert_not_reached (); */
7246 /* should this be considered an error condition? */
7247 if (is_type_done
&& !type
->byref
) {
7248 mono_domain_unlock (domain
);
7249 mono_loader_unlock ();
7250 return (MonoReflectionType
*)mono_class_get_ref_info (klass
);
7253 /* This is stored in vtables/JITted code so it has to be pinned */
7254 res
= (MonoReflectionType
*)mono_object_new_pinned (domain
, mono_defaults
.monotype_class
, error
);
7255 if (!mono_error_ok (error
))
7259 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
7261 if (type
->type
== MONO_TYPE_VOID
)
7262 domain
->typeof_void
= (MonoObject
*)res
;
7264 mono_domain_unlock (domain
);
7265 mono_loader_unlock ();
7270 * mono_method_get_object:
7271 * @domain: an app domain
7273 * @refclass: the reflected type (can be NULL)
7275 * Return an System.Reflection.MonoMethod object representing the method @method.
7277 MonoReflectionMethod
*
7278 mono_method_get_object (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
)
7281 MonoReflectionMethod
*ret
= NULL
;
7282 ret
= mono_method_get_object_checked (domain
, method
, refclass
, &error
);
7283 mono_error_raise_exception (&error
);
7288 * mono_method_get_object_checked:
7289 * @domain: an app domain
7291 * @refclass: the reflected type (can be NULL)
7292 * @error: set on error.
7294 * Return an System.Reflection.MonoMethod object representing the method @method.
7295 * Returns NULL and sets @error on error.
7297 MonoReflectionMethod
*
7298 mono_method_get_object_checked (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
, MonoError
*error
)
7301 * We use the same C representation for methods and constructors, but the type
7302 * name in C# is different.
7304 MonoReflectionType
*rt
;
7306 MonoReflectionMethod
*ret
;
7308 mono_error_init (error
);
7310 if (method
->is_inflated
) {
7311 MonoReflectionGenericMethod
*gret
;
7314 refclass
= method
->klass
;
7315 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
7316 if ((*method
->name
== '.') && (!strcmp (method
->name
, ".ctor") || !strcmp (method
->name
, ".cctor"))) {
7317 klass
= mono_class_get_mono_generic_cmethod_class ();
7319 klass
= mono_class_get_mono_generic_method_class ();
7321 gret
= (MonoReflectionGenericMethod
*)mono_object_new_checked (domain
, klass
, error
);
7322 if (!mono_error_ok (error
))
7324 gret
->method
.method
= method
;
7326 MONO_OBJECT_SETREF (gret
, method
.name
, mono_string_new (domain
, method
->name
));
7328 rt
= mono_type_get_object_checked (domain
, &refclass
->byval_arg
, error
);
7329 if (!mono_error_ok (error
))
7332 MONO_OBJECT_SETREF (gret
, method
.reftype
, rt
);
7334 CACHE_OBJECT (MonoReflectionMethod
*, method
, (MonoReflectionMethod
*)gret
, refclass
);
7338 refclass
= method
->klass
;
7340 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
7341 if (*method
->name
== '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0)) {
7342 klass
= mono_class_get_mono_cmethod_class ();
7345 klass
= mono_class_get_mono_method_class ();
7347 ret
= (MonoReflectionMethod
*)mono_object_new_checked (domain
, klass
, error
);
7348 if (!mono_error_ok (error
))
7350 ret
->method
= method
;
7352 rt
= mono_type_get_object_checked (domain
, &refclass
->byval_arg
, error
);
7353 if (!mono_error_ok (error
))
7356 MONO_OBJECT_SETREF (ret
, reftype
, rt
);
7358 CACHE_OBJECT (MonoReflectionMethod
*, method
, ret
, refclass
);
7361 g_assert (!mono_error_ok (error
));
7366 * mono_method_clear_object:
7368 * Clear the cached reflection objects for the dynamic method METHOD.
7371 mono_method_clear_object (MonoDomain
*domain
, MonoMethod
*method
)
7374 g_assert (method_is_dynamic (method
));
7376 klass
= method
->klass
;
7378 clear_cached_object (domain
, method
, klass
);
7379 klass
= klass
->parent
;
7381 /* Added by mono_param_get_objects () */
7382 clear_cached_object (domain
, &(method
->signature
), NULL
);
7383 klass
= method
->klass
;
7385 clear_cached_object (domain
, &(method
->signature
), klass
);
7386 klass
= klass
->parent
;
7391 * mono_field_get_object:
7392 * @domain: an app domain
7396 * Return an System.Reflection.MonoField object representing the field @field
7399 MonoReflectionField
*
7400 mono_field_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoClassField
*field
)
7403 MonoReflectionField
*result
;
7404 result
= mono_field_get_object_checked (domain
, klass
, field
, &error
);
7405 mono_error_raise_exception (&error
);
7410 * mono_field_get_object_checked:
7411 * @domain: an app domain
7414 * @error: set on error
7416 * Return an System.Reflection.MonoField object representing the field @field
7417 * in class @klass. On error, returns NULL and sets @error.
7419 MonoReflectionField
*
7420 mono_field_get_object_checked (MonoDomain
*domain
, MonoClass
*klass
, MonoClassField
*field
, MonoError
*error
)
7422 MonoReflectionType
*rt
;
7423 MonoReflectionField
*res
;
7425 mono_error_init (error
);
7427 CHECK_OBJECT (MonoReflectionField
*, field
, klass
);
7428 res
= (MonoReflectionField
*)mono_object_new_checked (domain
, mono_class_get_mono_field_class (), error
);
7433 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, mono_field_get_name (field
)));
7435 if (is_field_on_inst (field
)) {
7436 res
->attrs
= get_field_on_inst_generic_type (field
)->attrs
;
7438 rt
= mono_type_get_object_checked (domain
, field
->type
, error
);
7439 if (!mono_error_ok (error
))
7442 MONO_OBJECT_SETREF (res
, type
, rt
);
7445 rt
= mono_type_get_object_checked (domain
, field
->type
, error
);
7446 if (!mono_error_ok (error
))
7449 MONO_OBJECT_SETREF (res
, type
, rt
);
7451 res
->attrs
= mono_field_get_flags (field
);
7453 CACHE_OBJECT (MonoReflectionField
*, field
, res
, klass
);
7457 * mono_property_get_object:
7458 * @domain: an app domain
7460 * @property: a property
7462 * Return an System.Reflection.MonoProperty object representing the property @property
7465 MonoReflectionProperty
*
7466 mono_property_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoProperty
*property
)
7469 MonoReflectionProperty
*result
;
7470 result
= mono_property_get_object_checked (domain
, klass
, property
, &error
);
7471 mono_error_raise_exception (&error
);
7476 * mono_property_get_object:
7477 * @domain: an app domain
7479 * @property: a property
7480 * @error: set on error
7482 * Return an System.Reflection.MonoProperty object representing the property @property
7483 * in class @klass. On error returns NULL and sets @error.
7485 MonoReflectionProperty
*
7486 mono_property_get_object_checked (MonoDomain
*domain
, MonoClass
*klass
, MonoProperty
*property
, MonoError
*error
)
7488 MonoReflectionProperty
*res
;
7490 mono_error_init (error
);
7492 CHECK_OBJECT (MonoReflectionProperty
*, property
, klass
);
7493 res
= (MonoReflectionProperty
*)mono_object_new_checked (domain
, mono_class_get_mono_property_class (), error
);
7497 res
->property
= property
;
7498 CACHE_OBJECT (MonoReflectionProperty
*, property
, res
, klass
);
7502 * mono_event_get_object:
7503 * @domain: an app domain
7507 * Return an System.Reflection.MonoEvent object representing the event @event
7510 MonoReflectionEvent
*
7511 mono_event_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoEvent
*event
)
7514 MonoReflectionEvent
*result
;
7515 result
= mono_event_get_object_checked (domain
, klass
, event
, &error
);
7516 mono_error_raise_exception (&error
);
7521 * mono_event_get_object_checked:
7522 * @domain: an app domain
7525 * @error: set on error
7527 * Return an System.Reflection.MonoEvent object representing the event @event
7528 * in class @klass. On failure sets @error and returns NULL
7530 MonoReflectionEvent
*
7531 mono_event_get_object_checked (MonoDomain
*domain
, MonoClass
*klass
, MonoEvent
*event
, MonoError
*error
)
7533 MonoReflectionEvent
*res
;
7534 MonoReflectionMonoEvent
*mono_event
;
7536 CHECK_OBJECT (MonoReflectionEvent
*, event
, klass
);
7537 mono_event
= (MonoReflectionMonoEvent
*)mono_object_new_checked (domain
, mono_class_get_mono_event_class (), error
);
7540 mono_event
->klass
= klass
;
7541 mono_event
->event
= event
;
7542 res
= (MonoReflectionEvent
*)mono_event
;
7543 CACHE_OBJECT (MonoReflectionEvent
*, event
, res
, klass
);
7547 * mono_get_reflection_missing_object:
7548 * @domain: Domain where the object lives
7550 * Returns the System.Reflection.Missing.Value singleton object
7551 * (of type System.Reflection.Missing).
7553 * Used as the value for ParameterInfo.DefaultValue when Optional
7557 mono_get_reflection_missing_object (MonoDomain
*domain
)
7561 static MonoClassField
*missing_value_field
= NULL
;
7563 if (!missing_value_field
) {
7564 MonoClass
*missing_klass
;
7565 missing_klass
= mono_class_get_missing_class ();
7566 mono_class_init (missing_klass
);
7567 missing_value_field
= mono_class_get_field_from_name (missing_klass
, "Value");
7568 g_assert (missing_value_field
);
7570 obj
= mono_field_get_value_object_checked (domain
, missing_value_field
, NULL
, &error
);
7571 mono_error_assert_ok (&error
);
7576 get_dbnull (MonoDomain
*domain
, MonoObject
**dbnull
)
7579 *dbnull
= mono_get_dbnull_object (domain
);
7584 get_reflection_missing (MonoDomain
*domain
, MonoObject
**reflection_missing
)
7586 if (!*reflection_missing
)
7587 *reflection_missing
= mono_get_reflection_missing_object (domain
);
7588 return *reflection_missing
;
7592 * mono_param_get_objects:
7593 * @domain: an app domain
7596 * Return an System.Reflection.ParameterInfo array object representing the parameters
7597 * in the method @method.
7600 mono_param_get_objects_internal (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
, MonoError
*error
)
7602 static MonoClass
*System_Reflection_ParameterInfo
;
7603 static MonoClass
*System_Reflection_ParameterInfo_array
;
7604 MonoArray
*res
= NULL
;
7605 MonoReflectionMethod
*member
= NULL
;
7606 MonoReflectionParameter
*param
= NULL
;
7607 char **names
= NULL
, **blobs
= NULL
;
7608 guint32
*types
= NULL
;
7609 MonoType
*type
= NULL
;
7610 MonoObject
*dbnull
= NULL
;
7611 MonoObject
*missing
= NULL
;
7612 MonoMarshalSpec
**mspecs
= NULL
;
7613 MonoMethodSignature
*sig
= NULL
;
7614 MonoVTable
*pinfo_vtable
;
7615 MonoReflectionType
*rt
;
7618 mono_error_init (error
);
7620 if (!System_Reflection_ParameterInfo_array
) {
7623 klass
= mono_class_get_mono_parameter_info_class ();
7625 mono_memory_barrier ();
7626 System_Reflection_ParameterInfo
= klass
;
7629 klass
= mono_array_class_get (klass
, 1);
7630 mono_memory_barrier ();
7631 System_Reflection_ParameterInfo_array
= klass
;
7634 sig
= mono_method_signature_checked (method
, error
);
7635 if (!mono_error_ok (error
))
7638 if (!sig
->param_count
) {
7639 res
= mono_array_new_specific_checked (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), 0, error
);
7646 /* Note: the cache is based on the address of the signature into the method
7647 * since we already cache MethodInfos with the method as keys.
7649 CHECK_OBJECT (MonoArray
*, &(method
->signature
), refclass
);
7651 member
= mono_method_get_object_checked (domain
, method
, refclass
, error
);
7654 names
= g_new (char *, sig
->param_count
);
7655 mono_method_get_param_names (method
, (const char **) names
);
7657 mspecs
= g_new (MonoMarshalSpec
*, sig
->param_count
+ 1);
7658 mono_method_get_marshal_info (method
, mspecs
);
7660 res
= mono_array_new_specific_checked (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), sig
->param_count
, error
);
7664 pinfo_vtable
= mono_class_vtable (domain
, System_Reflection_ParameterInfo
);
7665 for (i
= 0; i
< sig
->param_count
; ++i
) {
7666 param
= (MonoReflectionParameter
*) mono_object_new_specific_checked (pinfo_vtable
, error
);
7670 rt
= mono_type_get_object_checked (domain
, sig
->params
[i
], error
);
7674 MONO_OBJECT_SETREF (param
, ClassImpl
, rt
);
7676 MONO_OBJECT_SETREF (param
, MemberImpl
, (MonoObject
*)member
);
7678 MONO_OBJECT_SETREF (param
, NameImpl
, mono_string_new (domain
, names
[i
]));
7680 param
->PositionImpl
= i
;
7681 param
->AttrsImpl
= sig
->params
[i
]->attrs
;
7683 if (!(param
->AttrsImpl
& PARAM_ATTRIBUTE_HAS_DEFAULT
)) {
7684 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
7685 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
7687 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
7691 blobs
= g_new0 (char *, sig
->param_count
);
7692 types
= g_new0 (guint32
, sig
->param_count
);
7693 get_default_param_value_blobs (method
, blobs
, types
);
7696 /* Build MonoType for the type from the Constant Table */
7698 type
= g_new0 (MonoType
, 1);
7699 type
->type
= (MonoTypeEnum
)types
[i
];
7700 type
->data
.klass
= NULL
;
7701 if (types
[i
] == MONO_TYPE_CLASS
)
7702 type
->data
.klass
= mono_defaults
.object_class
;
7703 else if ((sig
->params
[i
]->type
== MONO_TYPE_VALUETYPE
) && sig
->params
[i
]->data
.klass
->enumtype
) {
7704 /* For enums, types [i] contains the base type */
7706 type
->type
= MONO_TYPE_VALUETYPE
;
7707 type
->data
.klass
= mono_class_from_mono_type (sig
->params
[i
]);
7709 type
->data
.klass
= mono_class_from_mono_type (type
);
7711 MonoObject
*default_val_obj
= mono_get_object_from_blob (domain
, type
, blobs
[i
], error
);
7714 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, default_val_obj
);
7716 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7717 if (types
[i
] != MONO_TYPE_CLASS
&& !param
->DefaultValueImpl
) {
7718 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
7719 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
7721 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
7726 if (mspecs
[i
+ 1]) {
7727 MonoReflectionMarshalAsAttribute
* mobj
;
7728 mobj
= mono_reflection_marshal_as_attribute_from_marshal_spec (domain
, method
->klass
, mspecs
[i
+ 1], error
);
7731 MONO_OBJECT_SETREF (param
, MarshalAsImpl
, (MonoObject
*)mobj
);
7734 mono_array_setref (res
, i
, param
);
7744 for (i
= sig
->param_count
; i
>= 0; i
--) {
7746 mono_metadata_free_marshal_spec (mspecs
[i
]);
7754 CACHE_OBJECT (MonoArray
*, &(method
->signature
), res
, refclass
);
7758 mono_param_get_objects (MonoDomain
*domain
, MonoMethod
*method
)
7761 MonoArray
*result
= mono_param_get_objects_internal (domain
, method
, NULL
, &error
);
7762 mono_error_assert_ok (&error
);
7767 * mono_method_body_get_object:
7768 * @domain: an app domain
7771 * Return an System.Reflection.MethodBody object representing the method @method.
7773 MonoReflectionMethodBody
*
7774 mono_method_body_get_object (MonoDomain
*domain
, MonoMethod
*method
)
7777 MonoReflectionMethodBody
*result
= mono_method_body_get_object_checked (domain
, method
, &error
);
7778 mono_error_cleanup (&error
); /* FIXME better API that doesn't swallow the error */
7783 * mono_method_body_get_object_checked:
7784 * @domain: an app domain
7786 * @error: set on error
7788 * Return an System.Reflection.MethodBody object representing the
7789 * method @method. On failure, returns NULL and sets @error.
7791 MonoReflectionMethodBody
*
7792 mono_method_body_get_object_checked (MonoDomain
*domain
, MonoMethod
*method
, MonoError
*error
)
7794 MonoReflectionMethodBody
*ret
;
7795 MonoMethodHeader
*header
;
7797 MonoReflectionType
*rt
;
7798 guint32 method_rva
, local_var_sig_token
;
7800 unsigned char format
, flags
;
7803 mono_error_init (error
);
7805 /* for compatibility with .net */
7806 if (method_is_dynamic (method
)) {
7807 mono_error_set_generic_error (error
, "System", "InvalidOperationException", "");
7811 CHECK_OBJECT (MonoReflectionMethodBody
*, method
, NULL
);
7813 if ((method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
7814 (method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) ||
7815 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
7816 (method
->klass
->image
->raw_data
&& method
->klass
->image
->raw_data
[1] != 'Z') ||
7817 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
))
7820 image
= method
->klass
->image
;
7821 header
= mono_method_get_header_checked (method
, error
);
7822 return_val_if_nok (error
, NULL
);
7824 if (!image_is_dynamic (image
)) {
7825 /* Obtain local vars signature token */
7826 method_rva
= mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_METHOD
], mono_metadata_token_index (method
->token
) - 1, MONO_METHOD_RVA
);
7827 ptr
= mono_image_rva_map (image
, method_rva
);
7828 flags
= *(const unsigned char *) ptr
;
7829 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
7831 case METHOD_HEADER_TINY_FORMAT
:
7832 local_var_sig_token
= 0;
7834 case METHOD_HEADER_FAT_FORMAT
:
7838 local_var_sig_token
= read32 (ptr
);
7841 g_assert_not_reached ();
7844 local_var_sig_token
= 0; //FIXME
7846 ret
= (MonoReflectionMethodBody
*)mono_object_new_checked (domain
, mono_class_get_method_body_class (), error
);
7850 ret
->init_locals
= header
->init_locals
;
7851 ret
->max_stack
= header
->max_stack
;
7852 ret
->local_var_sig_token
= local_var_sig_token
;
7853 MONO_OBJECT_SETREF (ret
, il
, mono_array_new_cached (domain
, mono_defaults
.byte_class
, header
->code_size
));
7854 memcpy (mono_array_addr (ret
->il
, guint8
, 0), header
->code
, header
->code_size
);
7857 MONO_OBJECT_SETREF (ret
, locals
, mono_array_new_cached (domain
, mono_class_get_local_variable_info_class (), header
->num_locals
));
7858 for (i
= 0; i
< header
->num_locals
; ++i
) {
7859 MonoReflectionLocalVariableInfo
*info
= (MonoReflectionLocalVariableInfo
*)mono_object_new_checked (domain
, mono_class_get_local_variable_info_class (), error
);
7863 rt
= mono_type_get_object_checked (domain
, header
->locals
[i
], error
);
7867 MONO_OBJECT_SETREF (info
, local_type
, rt
);
7869 info
->is_pinned
= header
->locals
[i
]->pinned
;
7870 info
->local_index
= i
;
7871 mono_array_setref (ret
->locals
, i
, info
);
7875 MONO_OBJECT_SETREF (ret
, clauses
, mono_array_new_cached (domain
, mono_class_get_exception_handling_clause_class (), header
->num_clauses
));
7876 for (i
= 0; i
< header
->num_clauses
; ++i
) {
7877 MonoReflectionExceptionHandlingClause
*info
= (MonoReflectionExceptionHandlingClause
*)mono_object_new_checked (domain
, mono_class_get_exception_handling_clause_class (), error
);
7880 MonoExceptionClause
*clause
= &header
->clauses
[i
];
7882 info
->flags
= clause
->flags
;
7883 info
->try_offset
= clause
->try_offset
;
7884 info
->try_length
= clause
->try_len
;
7885 info
->handler_offset
= clause
->handler_offset
;
7886 info
->handler_length
= clause
->handler_len
;
7887 if (clause
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
)
7888 info
->filter_offset
= clause
->data
.filter_offset
;
7889 else if (clause
->data
.catch_class
) {
7890 rt
= mono_type_get_object_checked (mono_domain_get (), &clause
->data
.catch_class
->byval_arg
, error
);
7894 MONO_OBJECT_SETREF (info
, catch_type
, rt
);
7897 mono_array_setref (ret
->clauses
, i
, info
);
7900 mono_metadata_free_mh (header
);
7901 CACHE_OBJECT (MonoReflectionMethodBody
*, method
, ret
, NULL
);
7905 mono_metadata_free_mh (header
);
7910 * mono_get_dbnull_object:
7911 * @domain: Domain where the object lives
7913 * Returns the System.DBNull.Value singleton object
7915 * Used as the value for ParameterInfo.DefaultValue
7918 mono_get_dbnull_object (MonoDomain
*domain
)
7922 static MonoClassField
*dbnull_value_field
= NULL
;
7924 if (!dbnull_value_field
) {
7925 MonoClass
*dbnull_klass
;
7926 dbnull_klass
= mono_class_get_dbnull_class ();
7927 dbnull_value_field
= mono_class_get_field_from_name (dbnull_klass
, "Value");
7928 g_assert (dbnull_value_field
);
7930 obj
= mono_field_get_value_object_checked (domain
, dbnull_value_field
, NULL
, &error
);
7931 mono_error_assert_ok (&error
);
7936 get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
)
7938 guint32 param_index
, i
, lastp
, crow
= 0;
7939 guint32 param_cols
[MONO_PARAM_SIZE
], const_cols
[MONO_CONSTANT_SIZE
];
7942 MonoClass
*klass
= method
->klass
;
7943 MonoImage
*image
= klass
->image
;
7944 MonoMethodSignature
*methodsig
= mono_method_signature (method
);
7946 MonoTableInfo
*constt
;
7947 MonoTableInfo
*methodt
;
7948 MonoTableInfo
*paramt
;
7950 if (!methodsig
->param_count
)
7953 mono_class_init (klass
);
7955 if (image_is_dynamic (klass
->image
)) {
7956 MonoReflectionMethodAux
*aux
;
7957 if (method
->is_inflated
)
7958 method
= ((MonoMethodInflated
*)method
)->declaring
;
7959 aux
= (MonoReflectionMethodAux
*)g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
7960 if (aux
&& aux
->param_defaults
) {
7961 memcpy (blobs
, &(aux
->param_defaults
[1]), methodsig
->param_count
* sizeof (char*));
7962 memcpy (types
, &(aux
->param_default_types
[1]), methodsig
->param_count
* sizeof (guint32
));
7967 methodt
= &klass
->image
->tables
[MONO_TABLE_METHOD
];
7968 paramt
= &klass
->image
->tables
[MONO_TABLE_PARAM
];
7969 constt
= &image
->tables
[MONO_TABLE_CONSTANT
];
7971 idx
= mono_method_get_index (method
) - 1;
7972 g_assert (idx
!= -1);
7974 param_index
= mono_metadata_decode_row_col (methodt
, idx
, MONO_METHOD_PARAMLIST
);
7975 if (idx
+ 1 < methodt
->rows
)
7976 lastp
= mono_metadata_decode_row_col (methodt
, idx
+ 1, MONO_METHOD_PARAMLIST
);
7978 lastp
= paramt
->rows
+ 1;
7980 for (i
= param_index
; i
< lastp
; ++i
) {
7983 mono_metadata_decode_row (paramt
, i
- 1, param_cols
, MONO_PARAM_SIZE
);
7984 paramseq
= param_cols
[MONO_PARAM_SEQUENCE
];
7986 if (!(param_cols
[MONO_PARAM_FLAGS
] & PARAM_ATTRIBUTE_HAS_DEFAULT
))
7989 crow
= mono_metadata_get_constant_index (image
, MONO_TOKEN_PARAM_DEF
| i
, crow
+ 1);
7994 mono_metadata_decode_row (constt
, crow
- 1, const_cols
, MONO_CONSTANT_SIZE
);
7995 blobs
[paramseq
- 1] = (char *)mono_metadata_blob_heap (image
, const_cols
[MONO_CONSTANT_VALUE
]);
7996 types
[paramseq
- 1] = const_cols
[MONO_CONSTANT_TYPE
];
8003 mono_get_object_from_blob (MonoDomain
*domain
, MonoType
*type
, const char *blob
, MonoError
*error
)
8008 MonoType
*basetype
= type
;
8010 mono_error_init (error
);
8015 klass
= mono_class_from_mono_type (type
);
8016 if (klass
->valuetype
) {
8017 object
= mono_object_new_checked (domain
, klass
, error
);
8018 return_val_if_nok (error
, NULL
);
8019 retval
= ((gchar
*) object
+ sizeof (MonoObject
));
8020 if (klass
->enumtype
)
8021 basetype
= mono_class_enum_basetype (klass
);
8026 if (!mono_get_constant_value_from_blob (domain
, basetype
->type
, blob
, retval
))
8033 assembly_name_to_aname (MonoAssemblyName
*assembly
, char *p
) {
8036 gboolean quoted
= FALSE
;
8038 memset (assembly
, 0, sizeof (MonoAssemblyName
));
8039 assembly
->culture
= "";
8040 memset (assembly
->public_key_token
, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
8047 while (*p
&& (isalnum (*p
) || *p
== '.' || *p
== '-' || *p
== '_' || *p
== '$' || *p
== '@' || g_ascii_isspace (*p
)))
8058 /* Remove trailing whitespace */
8060 while (*s
&& g_ascii_isspace (*s
))
8063 while (g_ascii_isspace (*p
))
8066 if (*p
== 'V' && g_ascii_strncasecmp (p
, "Version=", 8) == 0) {
8068 assembly
->major
= strtoul (p
, &s
, 10);
8069 if (s
== p
|| *s
!= '.')
8072 assembly
->minor
= strtoul (p
, &s
, 10);
8073 if (s
== p
|| *s
!= '.')
8076 assembly
->build
= strtoul (p
, &s
, 10);
8077 if (s
== p
|| *s
!= '.')
8080 assembly
->revision
= strtoul (p
, &s
, 10);
8084 } else if (*p
== 'C' && g_ascii_strncasecmp (p
, "Culture=", 8) == 0) {
8086 if (g_ascii_strncasecmp (p
, "neutral", 7) == 0) {
8087 assembly
->culture
= "";
8090 assembly
->culture
= p
;
8091 while (*p
&& *p
!= ',') {
8095 } else if (*p
== 'P' && g_ascii_strncasecmp (p
, "PublicKeyToken=", 15) == 0) {
8097 if (strncmp (p
, "null", 4) == 0) {
8102 while (*p
&& *p
!= ',') {
8105 len
= (p
- start
+ 1);
8106 if (len
> MONO_PUBLIC_KEY_TOKEN_LENGTH
)
8107 len
= MONO_PUBLIC_KEY_TOKEN_LENGTH
;
8108 g_strlcpy ((char*)assembly
->public_key_token
, start
, len
);
8111 while (*p
&& *p
!= ',')
8115 while (g_ascii_isspace (*p
) || *p
== ',') {
8129 * mono_reflection_parse_type:
8132 * Parse a type name as accepted by the GetType () method and output the info
8133 * extracted in the info structure.
8134 * the name param will be mangled, so, make a copy before passing it to this function.
8135 * The fields in info will be valid until the memory pointed to by name is valid.
8137 * See also mono_type_get_name () below.
8139 * Returns: 0 on parse error.
8142 _mono_reflection_parse_type (char *name
, char **endptr
, gboolean is_recursed
,
8143 MonoTypeNameParse
*info
)
8145 char *start
, *p
, *w
, *last_point
, *startn
;
8146 int in_modifiers
= 0;
8147 int isbyref
= 0, rank
= 0, isptr
= 0;
8149 start
= p
= w
= name
;
8151 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8152 memset (&info
->assembly
, 0, sizeof (MonoAssemblyName
));
8153 info
->name
= info
->name_space
= NULL
;
8154 info
->nested
= NULL
;
8155 info
->modifiers
= NULL
;
8156 info
->type_arguments
= NULL
;
8158 /* last_point separates the namespace from the name */
8161 while (*p
== ' ') p
++, start
++, w
++, name
++;
8166 *p
= 0; /* NULL terminate the name */
8168 info
->nested
= g_list_append (info
->nested
, startn
);
8169 /* we have parsed the nesting namespace + name */
8173 info
->name_space
= start
;
8175 info
->name
= last_point
+ 1;
8177 info
->name_space
= (char *)"";
8205 info
->name_space
= start
;
8207 info
->name
= last_point
+ 1;
8209 info
->name_space
= (char *)"";
8216 if (isbyref
) /* only one level allowed by the spec */
8220 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (0));
8224 if (isbyref
) /* pointer to ref not okay */
8226 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-1));
8231 if (isbyref
) /* array of ref and generic ref are not okay */
8233 //Decide if it's an array of a generic argument list
8238 if (*p
== ',' || *p
== '*' || *p
== ']') { //array
8246 else if (*p
== '*') /* '*' means unknown lower bound */
8247 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-2));
8254 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (rank
));
8256 if (rank
|| isptr
) /* generic args after array spec or ptr*/ //XXX test
8259 info
->type_arguments
= g_ptr_array_new ();
8261 MonoTypeNameParse
*subinfo
= g_new0 (MonoTypeNameParse
, 1);
8262 gboolean fqname
= FALSE
;
8264 g_ptr_array_add (info
->type_arguments
, subinfo
);
8266 while (*p
== ' ') p
++;
8272 if (!_mono_reflection_parse_type (p
, &p
, TRUE
, subinfo
))
8275 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8276 if (fqname
&& (*p
!= ']')) {
8284 while (*p
&& (*p
!= ']'))
8292 if (g_ascii_isspace (*aname
)) {
8299 !assembly_name_to_aname (&subinfo
->assembly
, aname
))
8301 } else if (fqname
&& (*p
== ']')) {
8323 if (g_ascii_isspace (*p
)) {
8330 return 0; /* missing assembly name */
8331 if (!assembly_name_to_aname (&info
->assembly
, p
))
8337 if (info
->assembly
.name
)
8340 // *w = 0; /* terminate class name */
8342 if (!info
->name
|| !*info
->name
)
8346 /* add other consistency checks */
8352 * mono_identifier_unescape_type_name_chars:
8353 * @identifier: the display name of a mono type
8356 * The name in internal form, that is without escaping backslashes.
8358 * The string is modified in place!
8361 mono_identifier_unescape_type_name_chars(char* identifier
)
8366 for (w
= r
= identifier
; *r
!= 0; r
++)
8384 mono_identifier_unescape_info (MonoTypeNameParse
* info
);
8387 unescape_each_type_argument(void* data
, void* user_data
)
8389 MonoTypeNameParse
* info
= (MonoTypeNameParse
*)data
;
8390 mono_identifier_unescape_info (info
);
8394 unescape_each_nested_name (void* data
, void* user_data
)
8396 char* nested_name
= (char*) data
;
8397 mono_identifier_unescape_type_name_chars(nested_name
);
8401 * mono_identifier_unescape_info:
8403 * @info: a parsed display form of an (optionally assembly qualified) full type name.
8407 * Destructively updates the info by unescaping the identifiers that
8408 * comprise the type namespace, name, nested types (if any) and
8409 * generic type arguments (if any).
8411 * The resulting info has the names in internal form.
8415 mono_identifier_unescape_info (MonoTypeNameParse
*info
)
8419 mono_identifier_unescape_type_name_chars(info
->name_space
);
8420 mono_identifier_unescape_type_name_chars(info
->name
);
8421 // but don't escape info->assembly
8422 if (info
->type_arguments
)
8423 g_ptr_array_foreach(info
->type_arguments
, &unescape_each_type_argument
, NULL
);
8425 g_list_foreach(info
->nested
, &unescape_each_nested_name
, NULL
);
8429 mono_reflection_parse_type (char *name
, MonoTypeNameParse
*info
)
8431 int ok
= _mono_reflection_parse_type (name
, NULL
, FALSE
, info
);
8433 mono_identifier_unescape_info (info
);
8439 _mono_reflection_get_type_from_info (MonoTypeNameParse
*info
, MonoImage
*image
, gboolean ignorecase
, MonoError
*error
)
8441 gboolean type_resolve
= FALSE
;
8443 MonoImage
*rootimage
= image
;
8445 mono_error_init (error
);
8447 if (info
->assembly
.name
) {
8448 MonoAssembly
*assembly
= mono_assembly_loaded (&info
->assembly
);
8449 if (!assembly
&& image
&& image
->assembly
&& mono_assembly_names_equal (&info
->assembly
, &image
->assembly
->aname
))
8451 * This could happen in the AOT compiler case when the search hook is not
8454 assembly
= image
->assembly
;
8456 /* then we must load the assembly ourselve - see #60439 */
8457 assembly
= mono_assembly_load (&info
->assembly
, image
->assembly
->basedir
, NULL
);
8461 image
= assembly
->image
;
8462 } else if (!image
) {
8463 image
= mono_defaults
.corlib
;
8466 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
, error
);
8467 if (type
== NULL
&& !info
->assembly
.name
&& image
!= mono_defaults
.corlib
) {
8468 mono_error_cleanup (error
);
8469 image
= mono_defaults
.corlib
;
8470 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
, error
);
8477 * mono_reflection_get_type_internal:
8479 * Returns: may return NULL on success, sets error on failure.
8482 mono_reflection_get_type_internal (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, MonoError
*error
)
8487 gboolean bounded
= FALSE
;
8489 mono_error_init (error
);
8491 image
= mono_defaults
.corlib
;
8494 rootimage
= mono_defaults
.corlib
;
8497 klass
= mono_class_from_name_case_checked (image
, info
->name_space
, info
->name
, error
);
8499 klass
= mono_class_from_name_checked (image
, info
->name_space
, info
->name
, error
);
8504 for (mod
= info
->nested
; mod
; mod
= mod
->next
) {
8505 gpointer iter
= NULL
;
8509 mono_class_init (parent
);
8511 while ((klass
= mono_class_get_nested_types (parent
, &iter
))) {
8513 char *nested_name
, *nested_nspace
;
8514 gboolean match
= TRUE
;
8516 lastp
= strrchr ((const char *)mod
->data
, '.');
8518 /* Nested classes can have namespaces */
8521 nested_name
= g_strdup (lastp
+ 1);
8522 nspace_len
= lastp
- (char*)mod
->data
;
8523 nested_nspace
= (char *)g_malloc (nspace_len
+ 1);
8524 memcpy (nested_nspace
, mod
->data
, nspace_len
);
8525 nested_nspace
[nspace_len
] = '\0';
8528 nested_name
= (char *)mod
->data
;
8529 nested_nspace
= NULL
;
8532 if (nested_nspace
) {
8534 if (!(klass
->name_space
&& mono_utf8_strcasecmp (klass
->name_space
, nested_nspace
) == 0))
8537 if (!(klass
->name_space
&& strcmp (klass
->name_space
, nested_nspace
) == 0))
8543 if (mono_utf8_strcasecmp (klass
->name
, nested_name
) != 0)
8546 if (strcmp (klass
->name
, nested_name
) != 0)
8551 g_free (nested_name
);
8552 g_free (nested_nspace
);
8564 if (info
->type_arguments
) {
8565 MonoType
**type_args
= g_new0 (MonoType
*, info
->type_arguments
->len
);
8566 MonoReflectionType
*the_type
;
8570 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
8571 MonoTypeNameParse
*subinfo
= (MonoTypeNameParse
*)g_ptr_array_index (info
->type_arguments
, i
);
8573 type_args
[i
] = _mono_reflection_get_type_from_info (subinfo
, rootimage
, ignorecase
, error
);
8574 if (!type_args
[i
]) {
8580 the_type
= mono_type_get_object_checked (mono_domain_get (), &klass
->byval_arg
, error
);
8584 instance
= mono_reflection_bind_generic_parameters (
8585 the_type
, info
->type_arguments
->len
, type_args
, error
);
8591 klass
= mono_class_from_mono_type (instance
);
8594 for (mod
= info
->modifiers
; mod
; mod
= mod
->next
) {
8595 modval
= GPOINTER_TO_UINT (mod
->data
);
8596 if (!modval
) { /* byref: must be last modifier */
8597 return &klass
->this_arg
;
8598 } else if (modval
== -1) {
8599 klass
= mono_ptr_class_get (&klass
->byval_arg
);
8600 } else if (modval
== -2) {
8602 } else { /* array rank */
8603 klass
= mono_bounded_array_class_get (klass
, modval
, bounded
);
8607 return &klass
->byval_arg
;
8611 * mono_reflection_get_type:
8612 * @image: a metadata context
8613 * @info: type description structure
8614 * @ignorecase: flag for case-insensitive string compares
8615 * @type_resolve: whenever type resolve was already tried
8617 * Build a MonoType from the type description in @info.
8622 mono_reflection_get_type (MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
) {
8624 MonoType
*result
= mono_reflection_get_type_with_rootimage (image
, image
, info
, ignorecase
, type_resolve
, &error
);
8625 mono_error_cleanup (&error
);
8630 * mono_reflection_get_type_checked:
8631 * @image: a metadata context
8632 * @info: type description structure
8633 * @ignorecase: flag for case-insensitive string compares
8634 * @type_resolve: whenever type resolve was already tried
8635 * @error: set on error.
8637 * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8641 mono_reflection_get_type_checked (MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
, MonoError
*error
) {
8642 mono_error_init (error
);
8643 return mono_reflection_get_type_with_rootimage (image
, image
, info
, ignorecase
, type_resolve
, error
);
8648 mono_reflection_get_type_internal_dynamic (MonoImage
*rootimage
, MonoAssembly
*assembly
, MonoTypeNameParse
*info
, gboolean ignorecase
, MonoError
*error
)
8650 MonoReflectionAssemblyBuilder
*abuilder
;
8654 mono_error_init (error
);
8655 g_assert (assembly_is_dynamic (assembly
));
8656 abuilder
= (MonoReflectionAssemblyBuilder
*)mono_assembly_get_object_checked (((MonoDynamicAssembly
*)assembly
)->domain
, assembly
, error
);
8660 /* Enumerate all modules */
8663 if (abuilder
->modules
) {
8664 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
8665 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
8666 type
= mono_reflection_get_type_internal (rootimage
, &mb
->dynamic_image
->image
, info
, ignorecase
, error
);
8669 if (!mono_error_ok (error
))
8674 if (!type
&& abuilder
->loaded_modules
) {
8675 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
8676 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
8677 type
= mono_reflection_get_type_internal (rootimage
, mod
->image
, info
, ignorecase
, error
);
8680 if (!mono_error_ok (error
))
8689 mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
, MonoError
*error
)
8692 MonoReflectionAssembly
*assembly
;
8696 mono_error_init (error
);
8698 if (image
&& image_is_dynamic (image
))
8699 type
= mono_reflection_get_type_internal_dynamic (rootimage
, image
->assembly
, info
, ignorecase
, error
);
8701 type
= mono_reflection_get_type_internal (rootimage
, image
, info
, ignorecase
, error
);
8703 return_val_if_nok (error
, NULL
);
8707 if (!mono_domain_has_type_resolve (mono_domain_get ()))
8714 *type_resolve
= TRUE
;
8717 /* Reconstruct the type name */
8718 fullName
= g_string_new ("");
8719 if (info
->name_space
&& (info
->name_space
[0] != '\0'))
8720 g_string_printf (fullName
, "%s.%s", info
->name_space
, info
->name
);
8722 g_string_printf (fullName
, "%s", info
->name
);
8723 for (mod
= info
->nested
; mod
; mod
= mod
->next
)
8724 g_string_append_printf (fullName
, "+%s", (char*)mod
->data
);
8726 assembly
= mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName
->str
, NULL
, error
);
8727 if (!is_ok (error
)) {
8728 g_string_free (fullName
, TRUE
);
8733 if (assembly_is_dynamic (assembly
->assembly
))
8734 type
= mono_reflection_get_type_internal_dynamic (rootimage
, assembly
->assembly
,
8735 info
, ignorecase
, error
);
8737 type
= mono_reflection_get_type_internal (rootimage
, assembly
->assembly
->image
,
8738 info
, ignorecase
, error
);
8740 g_string_free (fullName
, TRUE
);
8741 return_val_if_nok (error
, NULL
);
8746 mono_reflection_free_type_info (MonoTypeNameParse
*info
)
8748 g_list_free (info
->modifiers
);
8749 g_list_free (info
->nested
);
8751 if (info
->type_arguments
) {
8754 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
8755 MonoTypeNameParse
*subinfo
= (MonoTypeNameParse
*)g_ptr_array_index (info
->type_arguments
, i
);
8757 mono_reflection_free_type_info (subinfo
);
8758 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8762 g_ptr_array_free (info
->type_arguments
, TRUE
);
8767 * mono_reflection_type_from_name:
8769 * @image: a metadata context (can be NULL).
8771 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8772 * it defaults to get the type from @image or, if @image is NULL or loading
8773 * from it fails, uses corlib.
8777 mono_reflection_type_from_name (char *name
, MonoImage
*image
)
8780 MonoType
*result
= mono_reflection_type_from_name_checked (name
, image
, &error
);
8781 mono_error_cleanup (&error
);
8786 * mono_reflection_type_from_name_checked:
8788 * @image: a metadata context (can be NULL).
8789 * @error: set on errror.
8791 * Retrieves a MonoType from its @name. If the name is not fully qualified,
8792 * it defaults to get the type from @image or, if @image is NULL or loading
8793 * from it fails, uses corlib. On failure returns NULL and sets @error.
8797 mono_reflection_type_from_name_checked (char *name
, MonoImage
*image
, MonoError
*error
)
8799 MonoType
*type
= NULL
;
8800 MonoTypeNameParse info
;
8803 mono_error_init (error
);
8804 /* Make a copy since parse_type modifies its argument */
8805 tmp
= g_strdup (name
);
8807 /*g_print ("requested type %s\n", str);*/
8808 if (mono_reflection_parse_type (tmp
, &info
)) {
8809 type
= _mono_reflection_get_type_from_info (&info
, image
, FALSE
, error
);
8810 if (!is_ok (error
)) {
8812 mono_reflection_free_type_info (&info
);
8818 mono_reflection_free_type_info (&info
);
8823 * mono_reflection_get_token:
8825 * Return the metadata token of OBJ which should be an object
8826 * representing a metadata element.
8829 mono_reflection_get_token (MonoObject
*obj
)
8832 guint32 result
= mono_reflection_get_token_checked (obj
, &error
);
8833 mono_error_assert_ok (&error
);
8838 * mono_reflection_get_token_checked:
8840 * @error: set on error
8842 * Return the metadata token of @obj which should be an object
8843 * representing a metadata element. On failure sets @error.
8846 mono_reflection_get_token_checked (MonoObject
*obj
, MonoError
*error
)
8851 mono_error_init (error
);
8853 klass
= obj
->vtable
->klass
;
8855 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
8856 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
8858 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
8859 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
8860 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
8862 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
8863 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
8864 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
8866 token
= fb
->table_idx
| MONO_TOKEN_FIELD_DEF
;
8867 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
8868 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
8869 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
8870 } else if (strcmp (klass
->name
, "MonoType") == 0) {
8871 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
8872 return_val_if_nok (error
, 0);
8873 MonoClass
*mc
= mono_class_from_mono_type (type
);
8874 if (!mono_class_init (mc
)) {
8875 mono_error_set_exception_instance (error
, mono_class_get_exception_for_failure (mc
));
8879 token
= mc
->type_token
;
8880 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
8881 strcmp (klass
->name
, "MonoMethod") == 0 ||
8882 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
8883 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
8884 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
8885 if (m
->method
->is_inflated
) {
8886 MonoMethodInflated
*inflated
= (MonoMethodInflated
*) m
->method
;
8887 return inflated
->declaring
->token
;
8889 token
= m
->method
->token
;
8891 } else if (strcmp (klass
->name
, "MonoField") == 0) {
8892 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
8894 if (is_field_on_inst (f
->field
)) {
8895 MonoDynamicGenericClass
*dgclass
= (MonoDynamicGenericClass
*)f
->field
->parent
->generic_class
;
8897 if (f
->field
>= dgclass
->fields
&& f
->field
< dgclass
->fields
+ dgclass
->count_fields
) {
8898 int field_index
= f
->field
- dgclass
->fields
;
8901 g_assert (field_index
>= 0 && field_index
< dgclass
->count_fields
);
8902 obj
= dgclass
->field_objects
[field_index
];
8903 return mono_reflection_get_token_checked (obj
, error
);
8906 token
= mono_class_get_field_token (f
->field
);
8907 } else if (strcmp (klass
->name
, "MonoProperty") == 0) {
8908 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)obj
;
8910 token
= mono_class_get_property_token (p
->property
);
8911 } else if (strcmp (klass
->name
, "MonoEvent") == 0) {
8912 MonoReflectionMonoEvent
*p
= (MonoReflectionMonoEvent
*)obj
;
8914 token
= mono_class_get_event_token (p
->event
);
8915 } else if (strcmp (klass
->name
, "ParameterInfo") == 0 || strcmp (klass
->name
, "MonoParameterInfo") == 0) {
8916 MonoReflectionParameter
*p
= (MonoReflectionParameter
*)obj
;
8917 MonoClass
*member_class
= mono_object_class (p
->MemberImpl
);
8918 g_assert (mono_class_is_reflection_method_or_constructor (member_class
));
8920 token
= mono_method_get_param_token (((MonoReflectionMethod
*)p
->MemberImpl
)->method
, p
->PositionImpl
);
8921 } else if (strcmp (klass
->name
, "Module") == 0 || strcmp (klass
->name
, "MonoModule") == 0) {
8922 MonoReflectionModule
*m
= (MonoReflectionModule
*)obj
;
8925 } else if (strcmp (klass
->name
, "Assembly") == 0 || strcmp (klass
->name
, "MonoAssembly") == 0) {
8926 token
= mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1);
8928 mono_error_set_not_implemented (error
, "MetadataToken is not supported for type '%s.%s'",
8929 klass
->name_space
, klass
->name
);
8937 load_cattr_enum_type (MonoImage
*image
, const char *p
, const char **end
, MonoError
*error
)
8941 int slen
= mono_metadata_decode_value (p
, &p
);
8943 mono_error_init (error
);
8945 n
= (char *)g_memdup (p
, slen
+ 1);
8947 t
= mono_reflection_type_from_name_checked (n
, image
, error
);
8949 char *msg
= g_strdup (mono_error_get_message (error
));
8950 mono_error_cleanup (error
);
8951 /* We don't free n, it's consumed by mono_error */
8952 mono_error_set_type_load_name (error
, n
, NULL
, "Could not load enum type %s while decoding custom attribute: %s", n
, msg
);
8959 return mono_class_from_mono_type (t
);
8963 load_cattr_value (MonoImage
*image
, MonoType
*t
, const char *p
, const char **end
, MonoError
*error
)
8965 int slen
, type
= t
->type
;
8966 MonoClass
*tklass
= t
->data
.klass
;
8968 mono_error_init (error
);
8974 case MONO_TYPE_BOOLEAN
: {
8975 MonoBoolean
*bval
= (MonoBoolean
*)g_malloc (sizeof (MonoBoolean
));
8980 case MONO_TYPE_CHAR
:
8982 case MONO_TYPE_I2
: {
8983 guint16
*val
= (guint16
*)g_malloc (sizeof (guint16
));
8988 #if SIZEOF_VOID_P == 4
8994 case MONO_TYPE_I4
: {
8995 guint32
*val
= (guint32
*)g_malloc (sizeof (guint32
));
9000 #if SIZEOF_VOID_P == 8
9001 case MONO_TYPE_U
: /* error out instead? this should probably not happen */
9005 case MONO_TYPE_I8
: {
9006 guint64
*val
= (guint64
*)g_malloc (sizeof (guint64
));
9011 case MONO_TYPE_R8
: {
9012 double *val
= (double *)g_malloc (sizeof (double));
9017 case MONO_TYPE_VALUETYPE
:
9018 if (t
->data
.klass
->enumtype
) {
9019 type
= mono_class_enum_basetype (t
->data
.klass
)->type
;
9022 MonoClass
*k
= t
->data
.klass
;
9024 if (mono_is_corlib_image (k
->image
) && strcmp (k
->name_space
, "System") == 0 && strcmp (k
->name
, "DateTime") == 0){
9025 guint64
*val
= (guint64
*)g_malloc (sizeof (guint64
));
9031 g_error ("generic valutype %s not handled in custom attr value decoding", t
->data
.klass
->name
);
9034 case MONO_TYPE_STRING
:
9035 if (*p
== (char)0xFF) {
9039 slen
= mono_metadata_decode_value (p
, &p
);
9041 return mono_string_new_len (mono_domain_get (), p
, slen
);
9042 case MONO_TYPE_CLASS
: {
9043 MonoReflectionType
*rt
;
9046 if (*p
== (char)0xFF) {
9051 slen
= mono_metadata_decode_value (p
, &p
);
9052 n
= (char *)g_memdup (p
, slen
+ 1);
9054 t
= mono_reflection_type_from_name_checked (n
, image
, error
);
9056 char *msg
= g_strdup (mono_error_get_message (error
));
9057 mono_error_cleanup (error
);
9058 /* We don't free n, it's consumed by mono_error */
9059 mono_error_set_type_load_name (error
, n
, NULL
, "Could not load type %s while decoding custom attribute: %msg", n
, msg
);
9066 rt
= mono_type_get_object_checked (mono_domain_get (), t
, error
);
9067 if (!mono_error_ok (error
))
9072 case MONO_TYPE_OBJECT
: {
9075 MonoClass
*subc
= NULL
;
9080 } else if (subt
== 0x0E) {
9081 type
= MONO_TYPE_STRING
;
9083 } else if (subt
== 0x1D) {
9084 MonoType simple_type
= {{0}};
9088 type
= MONO_TYPE_SZARRAY
;
9089 if (etype
== 0x50) {
9090 tklass
= mono_defaults
.systemtype_class
;
9091 } else if (etype
== 0x55) {
9092 tklass
= load_cattr_enum_type (image
, p
, &p
, error
);
9093 if (!mono_error_ok (error
))
9097 /* See Partition II, Appendix B3 */
9098 etype
= MONO_TYPE_OBJECT
;
9099 simple_type
.type
= (MonoTypeEnum
)etype
;
9100 tklass
= mono_class_from_mono_type (&simple_type
);
9103 } else if (subt
== 0x55) {
9106 slen
= mono_metadata_decode_value (p
, &p
);
9107 n
= (char *)g_memdup (p
, slen
+ 1);
9109 t
= mono_reflection_type_from_name_checked (n
, image
, error
);
9111 char *msg
= g_strdup (mono_error_get_message (error
));
9112 mono_error_cleanup (error
);
9113 /* We don't free n, it's consumed by mono_error */
9114 mono_error_set_type_load_name (error
, n
, NULL
, "Could not load type %s while decoding custom attribute: %s", n
, msg
);
9120 subc
= mono_class_from_mono_type (t
);
9121 } else if (subt
>= MONO_TYPE_BOOLEAN
&& subt
<= MONO_TYPE_R8
) {
9122 MonoType simple_type
= {{0}};
9123 simple_type
.type
= (MonoTypeEnum
)subt
;
9124 subc
= mono_class_from_mono_type (&simple_type
);
9126 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt
);
9128 val
= load_cattr_value (image
, &subc
->byval_arg
, p
, end
, error
);
9130 if (mono_error_ok (error
)) {
9131 obj
= mono_object_new_checked (mono_domain_get (), subc
, error
);
9132 g_assert (!subc
->has_references
);
9133 if (mono_error_ok (error
))
9134 mono_gc_memmove_atomic ((char*)obj
+ sizeof (MonoObject
), val
, mono_class_value_size (subc
, NULL
));
9140 case MONO_TYPE_SZARRAY
: {
9142 guint32 i
, alen
, basetype
;
9145 if (alen
== 0xffffffff) {
9149 arr
= mono_array_new (mono_domain_get(), tklass
, alen
);
9150 basetype
= tklass
->byval_arg
.type
;
9151 if (basetype
== MONO_TYPE_VALUETYPE
&& tklass
->enumtype
)
9152 basetype
= mono_class_enum_basetype (tklass
)->type
;
9157 case MONO_TYPE_BOOLEAN
:
9158 for (i
= 0; i
< alen
; i
++) {
9159 MonoBoolean val
= *p
++;
9160 mono_array_set (arr
, MonoBoolean
, i
, val
);
9163 case MONO_TYPE_CHAR
:
9166 for (i
= 0; i
< alen
; i
++) {
9167 guint16 val
= read16 (p
);
9168 mono_array_set (arr
, guint16
, i
, val
);
9175 for (i
= 0; i
< alen
; i
++) {
9176 guint32 val
= read32 (p
);
9177 mono_array_set (arr
, guint32
, i
, val
);
9182 for (i
= 0; i
< alen
; i
++) {
9185 mono_array_set (arr
, double, i
, val
);
9191 for (i
= 0; i
< alen
; i
++) {
9192 guint64 val
= read64 (p
);
9193 mono_array_set (arr
, guint64
, i
, val
);
9197 case MONO_TYPE_CLASS
:
9198 case MONO_TYPE_OBJECT
:
9199 case MONO_TYPE_STRING
:
9200 case MONO_TYPE_SZARRAY
:
9201 for (i
= 0; i
< alen
; i
++) {
9202 MonoObject
*item
= (MonoObject
*)load_cattr_value (image
, &tklass
->byval_arg
, p
, &p
, error
);
9203 if (!mono_error_ok (error
))
9205 mono_array_setref (arr
, i
, item
);
9209 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype
);
9215 g_error ("Type 0x%02x not handled in custom attr value decoding", type
);
9221 load_cattr_value_boxed (MonoDomain
*domain
, MonoImage
*image
, MonoType
*t
, const char* p
, const char** end
, MonoError
*error
)
9223 mono_error_init (error
);
9225 gboolean is_ref
= type_is_reference (t
);
9227 void *val
= load_cattr_value (image
, t
, p
, end
, error
);
9228 if (!is_ok (error
)) {
9235 return (MonoObject
*)val
;
9237 MonoObject
*boxed
= mono_value_box_checked (domain
, mono_class_from_mono_type (t
), val
, error
);
9243 create_cattr_typed_arg (MonoType
*t
, MonoObject
*val
, MonoError
*error
)
9245 static MonoMethod
*ctor
;
9247 void *params
[2], *unboxed
;
9249 mono_error_init (error
);
9252 ctor
= mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9254 params
[0] = mono_type_get_object_checked (mono_domain_get (), t
, error
);
9255 return_val_if_nok (error
, NULL
);
9258 retval
= mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error
);
9259 return_val_if_nok (error
, NULL
);
9260 unboxed
= mono_object_unbox (retval
);
9262 mono_runtime_invoke_checked (ctor
, unboxed
, params
, error
);
9263 return_val_if_nok (error
, NULL
);
9269 create_cattr_named_arg (void *minfo
, MonoObject
*typedarg
, MonoError
*error
)
9271 static MonoMethod
*ctor
;
9273 void *unboxed
, *params
[2];
9275 mono_error_init (error
);
9278 ctor
= mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9281 params
[1] = typedarg
;
9282 retval
= mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error
);
9283 return_val_if_nok (error
, NULL
);
9285 unboxed
= mono_object_unbox (retval
);
9287 mono_runtime_invoke_checked (ctor
, unboxed
, params
, error
);
9288 return_val_if_nok (error
, NULL
);
9294 type_is_reference (MonoType
*type
)
9296 switch (type
->type
) {
9297 case MONO_TYPE_BOOLEAN
:
9298 case MONO_TYPE_CHAR
:
9311 case MONO_TYPE_VALUETYPE
:
9319 free_param_data (MonoMethodSignature
*sig
, void **params
) {
9321 for (i
= 0; i
< sig
->param_count
; ++i
) {
9322 if (!type_is_reference (sig
->params
[i
]))
9323 g_free (params
[i
]);
9328 * Find the field index in the metadata FieldDef table.
9331 find_field_index (MonoClass
*klass
, MonoClassField
*field
) {
9334 for (i
= 0; i
< klass
->field
.count
; ++i
) {
9335 if (field
== &klass
->fields
[i
])
9336 return klass
->field
.first
+ 1 + i
;
9342 * Find the property index in the metadata Property table.
9345 find_property_index (MonoClass
*klass
, MonoProperty
*property
) {
9348 for (i
= 0; i
< klass
->ext
->property
.count
; ++i
) {
9349 if (property
== &klass
->ext
->properties
[i
])
9350 return klass
->ext
->property
.first
+ 1 + i
;
9356 * Find the event index in the metadata Event table.
9359 find_event_index (MonoClass
*klass
, MonoEvent
*event
) {
9362 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
9363 if (event
== &klass
->ext
->events
[i
])
9364 return klass
->ext
->event
.first
+ 1 + i
;
9370 create_custom_attr (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
, MonoError
*error
)
9372 const char *p
= (const char*)data
;
9374 guint32 i
, j
, num_named
;
9376 void *params_buf
[32];
9377 void **params
= NULL
;
9378 MonoMethodSignature
*sig
;
9379 MonoObject
*exc
= NULL
;
9381 mono_error_init (error
);
9383 mono_class_init (method
->klass
);
9385 if (!mono_verifier_verify_cattr_content (image
, method
, data
, len
, NULL
)) {
9386 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9391 attr
= mono_object_new_checked (mono_domain_get (), method
->klass
, error
);
9392 if (!mono_error_ok (error
)) return NULL
;
9394 mono_runtime_invoke_checked (method
, attr
, NULL
, error
);
9395 if (!mono_error_ok (error
))
9401 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
9404 /*g_print ("got attr %s\n", method->klass->name);*/
9406 sig
= mono_method_signature (method
);
9407 if (sig
->param_count
< 32) {
9408 params
= params_buf
;
9409 memset (params
, 0, sizeof (void*) * sig
->param_count
);
9411 /* Allocate using GC so it gets GC tracking */
9412 params
= (void **)mono_gc_alloc_fixed (sig
->param_count
* sizeof (void*), MONO_GC_DESCRIPTOR_NULL
, MONO_ROOT_SOURCE_REFLECTION
, "custom attribute parameters");
9417 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
9418 params
[i
] = load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
, error
);
9419 if (!mono_error_ok (error
))
9424 attr
= mono_object_new_checked (mono_domain_get (), method
->klass
, error
);
9425 if (!mono_error_ok (error
)) goto fail
;
9427 mono_runtime_try_invoke (method
, attr
, params
, &exc
, error
);
9428 if (!mono_error_ok (error
))
9433 num_named
= read16 (named
);
9435 for (j
= 0; j
< num_named
; j
++) {
9437 char *name
, named_type
, data_type
;
9438 named_type
= *named
++;
9439 data_type
= *named
++; /* type of data */
9440 if (data_type
== MONO_TYPE_SZARRAY
)
9441 data_type
= *named
++;
9442 if (data_type
== MONO_TYPE_ENUM
) {
9445 type_len
= mono_metadata_decode_blob_size (named
, &named
);
9446 type_name
= (char *)g_malloc (type_len
+ 1);
9447 memcpy (type_name
, named
, type_len
);
9448 type_name
[type_len
] = 0;
9450 /* FIXME: lookup the type and check type consistency */
9453 name_len
= mono_metadata_decode_blob_size (named
, &named
);
9454 name
= (char *)g_malloc (name_len
+ 1);
9455 memcpy (name
, named
, name_len
);
9456 name
[name_len
] = 0;
9458 if (named_type
== 0x53) {
9459 MonoClassField
*field
;
9462 /* how this fail is a blackbox */
9463 field
= mono_class_get_field_from_name (mono_object_class (attr
), name
);
9465 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name
);
9470 val
= load_cattr_value (image
, field
->type
, named
, &named
, error
);
9471 if (!mono_error_ok (error
)) {
9473 if (!type_is_reference (field
->type
))
9478 mono_field_set_value (attr
, field
, val
);
9479 if (!type_is_reference (field
->type
))
9481 } else if (named_type
== 0x54) {
9484 MonoType
*prop_type
;
9486 prop
= mono_class_get_property_from_name (mono_object_class (attr
), name
);
9489 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name
);
9495 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name
);
9500 /* can we have more that 1 arg in a custom attr named property? */
9501 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
9502 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
9504 pparams
[0] = load_cattr_value (image
, prop_type
, named
, &named
, error
);
9505 if (!mono_error_ok (error
)) {
9507 if (!type_is_reference (prop_type
))
9508 g_free (pparams
[0]);
9513 mono_property_set_value (prop
, attr
, pparams
, NULL
);
9514 if (!type_is_reference (prop_type
))
9515 g_free (pparams
[0]);
9520 free_param_data (method
->signature
, params
);
9521 if (params
!= params_buf
)
9522 mono_gc_free_fixed (params
);
9527 free_param_data (method
->signature
, params
);
9528 if (params
!= params_buf
)
9529 mono_gc_free_fixed (params
);
9531 mono_raise_exception ((MonoException
*)exc
);
9536 * mono_reflection_create_custom_attr_data_args:
9538 * Create an array of typed and named arguments from the cattr blob given by DATA.
9539 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9540 * NAMED_ARG_INFO will contain information about the named arguments.
9543 mono_reflection_create_custom_attr_data_args (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
, MonoArray
**typed_args
, MonoArray
**named_args
, CattrNamedArg
**named_arg_info
, MonoError
*error
)
9545 MonoArray
*typedargs
, *namedargs
;
9546 MonoClass
*attrklass
;
9548 const char *p
= (const char*)data
;
9550 guint32 i
, j
, num_named
;
9551 CattrNamedArg
*arginfo
= NULL
;
9555 *named_arg_info
= NULL
;
9557 mono_error_init (error
);
9559 if (!mono_verifier_verify_cattr_content (image
, method
, data
, len
, NULL
)) {
9560 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9564 mono_class_init (method
->klass
);
9566 domain
= mono_domain_get ();
9568 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
9571 typedargs
= mono_array_new (domain
, mono_get_object_class (), mono_method_signature (method
)->param_count
);
9575 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
9578 obj
= load_cattr_value_boxed (domain
, image
, mono_method_signature (method
)->params
[i
], p
, &p
, error
);
9579 return_if_nok (error
);
9580 mono_array_setref (typedargs
, i
, obj
);
9584 num_named
= read16 (named
);
9585 namedargs
= mono_array_new (domain
, mono_get_object_class (), num_named
);
9587 attrklass
= method
->klass
;
9589 arginfo
= g_new0 (CattrNamedArg
, num_named
);
9590 *named_arg_info
= arginfo
;
9592 for (j
= 0; j
< num_named
; j
++) {
9594 char *name
, named_type
, data_type
;
9595 named_type
= *named
++;
9596 data_type
= *named
++; /* type of data */
9597 if (data_type
== MONO_TYPE_SZARRAY
)
9598 data_type
= *named
++;
9599 if (data_type
== MONO_TYPE_ENUM
) {
9602 type_len
= mono_metadata_decode_blob_size (named
, &named
);
9603 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, type_len
, data
+ len
))
9606 type_name
= (char *)g_malloc (type_len
+ 1);
9607 memcpy (type_name
, named
, type_len
);
9608 type_name
[type_len
] = 0;
9610 /* FIXME: lookup the type and check type consistency */
9613 name_len
= mono_metadata_decode_blob_size (named
, &named
);
9614 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, name_len
, data
+ len
))
9616 name
= (char *)g_malloc (name_len
+ 1);
9617 memcpy (name
, named
, name_len
);
9618 name
[name_len
] = 0;
9620 if (named_type
== 0x53) {
9622 MonoClassField
*field
= mono_class_get_field_from_name (attrklass
, name
);
9629 arginfo
[j
].type
= field
->type
;
9630 arginfo
[j
].field
= field
;
9632 obj
= load_cattr_value_boxed (domain
, image
, field
->type
, named
, &named
, error
);
9633 if (!is_ok (error
)) {
9637 mono_array_setref (namedargs
, j
, obj
);
9639 } else if (named_type
== 0x54) {
9641 MonoType
*prop_type
;
9642 MonoProperty
*prop
= mono_class_get_property_from_name (attrklass
, name
);
9644 if (!prop
|| !prop
->set
) {
9649 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
9650 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
9652 arginfo
[j
].type
= prop_type
;
9653 arginfo
[j
].prop
= prop
;
9655 obj
= load_cattr_value_boxed (domain
, image
, prop_type
, named
, &named
, error
);
9656 if (!is_ok (error
)) {
9660 mono_array_setref (namedargs
, j
, obj
);
9665 *typed_args
= typedargs
;
9666 *named_args
= namedargs
;
9669 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9671 *named_arg_info
= NULL
;
9675 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod
*ref_method
, MonoReflectionAssembly
*assembly
, gpointer data
, guint32 len
, MonoArray
**ctor_args
, MonoArray
**named_args
)
9678 MonoArray
*typedargs
, *namedargs
;
9681 CattrNamedArg
*arginfo
= NULL
;
9685 mono_error_init (&error
);
9693 image
= assembly
->assembly
->image
;
9694 method
= ref_method
->method
;
9695 domain
= mono_object_domain (ref_method
);
9697 if (!mono_class_init (method
->klass
))
9698 mono_raise_exception (mono_class_get_exception_for_failure (method
->klass
));
9700 mono_reflection_create_custom_attr_data_args (image
, method
, (const guchar
*)data
, len
, &typedargs
, &namedargs
, &arginfo
, &error
);
9701 if (!mono_error_ok (&error
))
9704 if (mono_loader_get_last_error ()) {
9705 mono_error_set_from_loader_error (&error
);
9709 if (!typedargs
|| !namedargs
)
9712 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
9713 MonoObject
*obj
= mono_array_get (typedargs
, MonoObject
*, i
);
9714 MonoObject
*typedarg
;
9716 typedarg
= create_cattr_typed_arg (mono_method_signature (method
)->params
[i
], obj
, &error
);
9717 if (!is_ok (&error
))
9719 mono_array_setref (typedargs
, i
, typedarg
);
9722 for (i
= 0; i
< mono_array_length (namedargs
); ++i
) {
9723 MonoObject
*obj
= mono_array_get (namedargs
, MonoObject
*, i
);
9724 MonoObject
*typedarg
, *namedarg
, *minfo
;
9726 if (arginfo
[i
].prop
) {
9727 minfo
= (MonoObject
*)mono_property_get_object_checked (domain
, NULL
, arginfo
[i
].prop
, &error
);
9731 minfo
= (MonoObject
*)mono_field_get_object_checked (domain
, NULL
, arginfo
[i
].field
, &error
);
9732 if (!mono_error_ok (&error
))
9736 typedarg
= create_cattr_typed_arg (arginfo
[i
].type
, obj
, &error
);
9737 if (!is_ok (&error
))
9739 namedarg
= create_cattr_named_arg (minfo
, typedarg
, &error
);
9740 if (!is_ok (&error
))
9743 mono_array_setref (namedargs
, i
, namedarg
);
9746 *ctor_args
= typedargs
;
9747 *named_args
= namedargs
;
9750 mono_error_raise_exception (&error
);
9755 create_custom_attr_data (MonoImage
*image
, MonoCustomAttrEntry
*cattr
, MonoError
*error
)
9757 static MonoMethod
*ctor
;
9763 mono_error_init (error
);
9765 g_assert (image
->assembly
);
9768 ctor
= mono_class_get_method_from_name (mono_defaults
.customattribute_data_class
, ".ctor", 4);
9770 domain
= mono_domain_get ();
9771 attr
= mono_object_new_checked (domain
, mono_defaults
.customattribute_data_class
, error
);
9772 return_val_if_nok (error
, NULL
);
9773 params
[0] = mono_method_get_object_checked (domain
, cattr
->ctor
, NULL
, error
);
9774 return_val_if_nok (error
, NULL
);
9775 params
[1] = mono_assembly_get_object_checked (domain
, image
->assembly
, error
);
9776 return_val_if_nok (error
, NULL
);
9777 params
[2] = (gpointer
)&cattr
->data
;
9778 params
[3] = &cattr
->data_size
;
9780 mono_runtime_invoke_checked (ctor
, attr
, params
, error
);
9781 return_val_if_nok (error
, NULL
);
9786 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo
*cinfo
, MonoClass
*attr_klass
, MonoError
*error
)
9792 mono_error_init (error
);
9795 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
9796 if (!attr_klass
|| mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
))
9800 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, n
);
9802 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
9803 if (!cinfo
->attrs
[i
].ctor
) {
9804 /* The cattr type is not finished yet */
9805 /* We should include the type name but cinfo doesn't contain it */
9806 mono_error_set_type_load_name (error
, NULL
, NULL
, "");
9809 if (!attr_klass
|| mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
)) {
9810 attr
= create_custom_attr (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
, error
);
9811 if (!mono_error_ok (error
))
9813 mono_array_setref (result
, n
, attr
);
9821 mono_custom_attrs_construct (MonoCustomAttrInfo
*cinfo
)
9824 MonoArray
*result
= mono_custom_attrs_construct_by_type (cinfo
, NULL
, &error
);
9825 mono_error_assert_ok (&error
); /*FIXME proper error handling*/
9831 mono_custom_attrs_data_construct (MonoCustomAttrInfo
*cinfo
, MonoError
*error
)
9837 mono_error_init (error
);
9838 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, cinfo
->num_attrs
);
9839 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
9840 attr
= create_custom_attr_data (cinfo
->image
, &cinfo
->attrs
[i
], error
);
9841 return_val_if_nok (error
, NULL
);
9842 mono_array_setref (result
, i
, attr
);
9848 * mono_custom_attrs_from_index:
9850 * Returns: NULL if no attributes are found or if a loading error occurs.
9853 mono_custom_attrs_from_index (MonoImage
*image
, guint32 idx
)
9856 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_index_checked (image
, idx
, &error
);
9857 mono_error_cleanup (&error
); /* FIXME a better public API that doesn't swallow the error. */
9861 * mono_custom_attrs_from_index_checked:
9863 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
9866 mono_custom_attrs_from_index_checked (MonoImage
*image
, guint32 idx
, MonoError
*error
)
9868 guint32 mtoken
, i
, len
;
9869 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
9871 MonoCustomAttrInfo
*ainfo
;
9872 GList
*tmp
, *list
= NULL
;
9874 MonoCustomAttrEntry
* attr
;
9876 mono_error_init (error
);
9878 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
9880 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
9884 while (i
< ca
->rows
) {
9885 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
9887 list
= g_list_prepend (list
, GUINT_TO_POINTER (i
));
9890 len
= g_list_length (list
);
9893 ainfo
= (MonoCustomAttrInfo
*)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * len
);
9894 ainfo
->num_attrs
= len
;
9895 ainfo
->image
= image
;
9896 for (i
= len
, tmp
= list
; i
!= 0; --i
, tmp
= tmp
->next
) {
9897 mono_metadata_decode_row (ca
, GPOINTER_TO_UINT (tmp
->data
), cols
, MONO_CUSTOM_ATTR_SIZE
);
9898 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
9899 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
9900 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
9901 mtoken
|= MONO_TOKEN_METHOD_DEF
;
9903 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
9904 mtoken
|= MONO_TOKEN_MEMBER_REF
;
9907 g_error ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
9910 attr
= &ainfo
->attrs
[i
- 1];
9911 attr
->ctor
= mono_get_method_checked (image
, mtoken
, NULL
, NULL
, error
);
9913 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image
->name
, mtoken
, mono_error_get_message (error
));
9919 if (!mono_verifier_verify_cattr_blob (image
, cols
[MONO_CUSTOM_ATTR_VALUE
], NULL
)) {
9920 /*FIXME raising an exception here doesn't make any sense*/
9921 g_warning ("Invalid custom attribute blob on image %s for index %x", image
->name
, idx
);
9926 data
= mono_metadata_blob_heap (image
, cols
[MONO_CUSTOM_ATTR_VALUE
]);
9927 attr
->data_size
= mono_metadata_decode_value (data
, &data
);
9928 attr
->data
= (guchar
*)data
;
9936 mono_custom_attrs_from_method (MonoMethod
*method
)
9939 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_method_checked (method
, &error
);
9940 mono_error_cleanup (&error
); /* FIXME want a better API that doesn't swallow the error */
9945 mono_custom_attrs_from_method_checked (MonoMethod
*method
, MonoError
*error
)
9949 mono_error_init (error
);
9952 * An instantiated method has the same cattrs as the generic method definition.
9954 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9955 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9957 if (method
->is_inflated
)
9958 method
= ((MonoMethodInflated
*) method
)->declaring
;
9960 if (method_is_dynamic (method
) || image_is_dynamic (method
->klass
->image
))
9961 return lookup_custom_attr (method
->klass
->image
, method
);
9964 /* Synthetic methods */
9967 idx
= mono_method_get_index (method
);
9968 idx
<<= MONO_CUSTOM_ATTR_BITS
;
9969 idx
|= MONO_CUSTOM_ATTR_METHODDEF
;
9970 return mono_custom_attrs_from_index_checked (method
->klass
->image
, idx
, error
);
9974 mono_custom_attrs_from_class (MonoClass
*klass
)
9977 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_class_checked (klass
, &error
);
9978 mono_error_cleanup (&error
); /* FIXME want a better API that doesn't swallow the error */
9983 mono_custom_attrs_from_class_checked (MonoClass
*klass
, MonoError
*error
)
9987 mono_error_init (error
);
9989 if (klass
->generic_class
)
9990 klass
= klass
->generic_class
->container_class
;
9992 if (image_is_dynamic (klass
->image
))
9993 return lookup_custom_attr (klass
->image
, klass
);
9995 if (klass
->byval_arg
.type
== MONO_TYPE_VAR
|| klass
->byval_arg
.type
== MONO_TYPE_MVAR
) {
9996 idx
= mono_metadata_token_index (klass
->sizes
.generic_param_token
);
9997 idx
<<= MONO_CUSTOM_ATTR_BITS
;
9998 idx
|= MONO_CUSTOM_ATTR_GENERICPAR
;
10000 idx
= mono_metadata_token_index (klass
->type_token
);
10001 idx
<<= MONO_CUSTOM_ATTR_BITS
;
10002 idx
|= MONO_CUSTOM_ATTR_TYPEDEF
;
10004 return mono_custom_attrs_from_index_checked (klass
->image
, idx
, error
);
10007 MonoCustomAttrInfo
*
10008 mono_custom_attrs_from_assembly (MonoAssembly
*assembly
)
10011 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_assembly_checked (assembly
, &error
);
10012 mono_error_cleanup (&error
); /* FIXME want a better API that doesn't swallow the error */
10016 MonoCustomAttrInfo
*
10017 mono_custom_attrs_from_assembly_checked (MonoAssembly
*assembly
, MonoError
*error
)
10021 mono_error_init (error
);
10023 if (image_is_dynamic (assembly
->image
))
10024 return lookup_custom_attr (assembly
->image
, assembly
);
10025 idx
= 1; /* there is only one assembly */
10026 idx
<<= MONO_CUSTOM_ATTR_BITS
;
10027 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
10028 return mono_custom_attrs_from_index_checked (assembly
->image
, idx
, error
);
10031 static MonoCustomAttrInfo
*
10032 mono_custom_attrs_from_module (MonoImage
*image
, MonoError
*error
)
10036 if (image_is_dynamic (image
))
10037 return lookup_custom_attr (image
, image
);
10038 idx
= 1; /* there is only one module */
10039 idx
<<= MONO_CUSTOM_ATTR_BITS
;
10040 idx
|= MONO_CUSTOM_ATTR_MODULE
;
10041 return mono_custom_attrs_from_index_checked (image
, idx
, error
);
10044 MonoCustomAttrInfo
*
10045 mono_custom_attrs_from_property (MonoClass
*klass
, MonoProperty
*property
)
10048 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_property_checked (klass
, property
, &error
);
10049 mono_error_cleanup (&error
); /* FIXME want a better API that doesn't swallow the error */
10053 MonoCustomAttrInfo
*
10054 mono_custom_attrs_from_property_checked (MonoClass
*klass
, MonoProperty
*property
, MonoError
*error
)
10058 if (image_is_dynamic (klass
->image
)) {
10059 property
= mono_metadata_get_corresponding_property_from_generic_type_definition (property
);
10060 return lookup_custom_attr (klass
->image
, property
);
10062 idx
= find_property_index (klass
, property
);
10063 idx
<<= MONO_CUSTOM_ATTR_BITS
;
10064 idx
|= MONO_CUSTOM_ATTR_PROPERTY
;
10065 return mono_custom_attrs_from_index_checked (klass
->image
, idx
, error
);
10068 MonoCustomAttrInfo
*
10069 mono_custom_attrs_from_event (MonoClass
*klass
, MonoEvent
*event
)
10072 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_event_checked (klass
, event
, &error
);
10073 mono_error_cleanup (&error
); /* FIXME want a better API that doesn't swallow the error */
10077 MonoCustomAttrInfo
*
10078 mono_custom_attrs_from_event_checked (MonoClass
*klass
, MonoEvent
*event
, MonoError
*error
)
10082 if (image_is_dynamic (klass
->image
)) {
10083 event
= mono_metadata_get_corresponding_event_from_generic_type_definition (event
);
10084 return lookup_custom_attr (klass
->image
, event
);
10086 idx
= find_event_index (klass
, event
);
10087 idx
<<= MONO_CUSTOM_ATTR_BITS
;
10088 idx
|= MONO_CUSTOM_ATTR_EVENT
;
10089 return mono_custom_attrs_from_index_checked (klass
->image
, idx
, error
);
10092 MonoCustomAttrInfo
*
10093 mono_custom_attrs_from_field (MonoClass
*klass
, MonoClassField
*field
)
10096 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_field_checked (klass
, field
, &error
);
10097 mono_error_cleanup (&error
); /* FIXME want a better API that doesn't swallow the error */
10101 MonoCustomAttrInfo
*
10102 mono_custom_attrs_from_field_checked (MonoClass
*klass
, MonoClassField
*field
, MonoError
*error
)
10105 mono_error_init (error
);
10107 if (image_is_dynamic (klass
->image
)) {
10108 field
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
);
10109 return lookup_custom_attr (klass
->image
, field
);
10111 idx
= find_field_index (klass
, field
);
10112 idx
<<= MONO_CUSTOM_ATTR_BITS
;
10113 idx
|= MONO_CUSTOM_ATTR_FIELDDEF
;
10114 return mono_custom_attrs_from_index_checked (klass
->image
, idx
, error
);
10118 * mono_custom_attrs_from_param:
10119 * @method: handle to the method that we want to retrieve custom parameter information from
10120 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10122 * The result must be released with mono_custom_attrs_free().
10124 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10126 MonoCustomAttrInfo
*
10127 mono_custom_attrs_from_param (MonoMethod
*method
, guint32 param
)
10130 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_param_checked (method
, param
, &error
);
10131 mono_error_cleanup (&error
); /* FIXME want a better API that doesn't swallow the error */
10136 * mono_custom_attrs_from_param_checked:
10137 * @method: handle to the method that we want to retrieve custom parameter information from
10138 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10139 * @error: set on error
10141 * The result must be released with mono_custom_attrs_free().
10143 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
10145 MonoCustomAttrInfo
*
10146 mono_custom_attrs_from_param_checked (MonoMethod
*method
, guint32 param
, MonoError
*error
)
10149 guint32 i
, idx
, method_index
;
10150 guint32 param_list
, param_last
, param_pos
, found
;
10152 MonoReflectionMethodAux
*aux
;
10154 mono_error_init (error
);
10157 * An instantiated method has the same cattrs as the generic method definition.
10159 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10160 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10162 if (method
->is_inflated
)
10163 method
= ((MonoMethodInflated
*) method
)->declaring
;
10165 if (image_is_dynamic (method
->klass
->image
)) {
10166 MonoCustomAttrInfo
*res
, *ainfo
;
10169 aux
= (MonoReflectionMethodAux
*)g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
10170 if (!aux
|| !aux
->param_cattr
)
10173 /* Need to copy since it will be freed later */
10174 ainfo
= aux
->param_cattr
[param
];
10177 size
= MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * ainfo
->num_attrs
;
10178 res
= (MonoCustomAttrInfo
*)g_malloc0 (size
);
10179 memcpy (res
, ainfo
, size
);
10183 image
= method
->klass
->image
;
10184 method_index
= mono_method_get_index (method
);
10187 ca
= &image
->tables
[MONO_TABLE_METHOD
];
10189 param_list
= mono_metadata_decode_row_col (ca
, method_index
- 1, MONO_METHOD_PARAMLIST
);
10190 if (method_index
== ca
->rows
) {
10191 ca
= &image
->tables
[MONO_TABLE_PARAM
];
10192 param_last
= ca
->rows
+ 1;
10194 param_last
= mono_metadata_decode_row_col (ca
, method_index
, MONO_METHOD_PARAMLIST
);
10195 ca
= &image
->tables
[MONO_TABLE_PARAM
];
10198 for (i
= param_list
; i
< param_last
; ++i
) {
10199 param_pos
= mono_metadata_decode_row_col (ca
, i
- 1, MONO_PARAM_SEQUENCE
);
10200 if (param_pos
== param
) {
10208 idx
<<= MONO_CUSTOM_ATTR_BITS
;
10209 idx
|= MONO_CUSTOM_ATTR_PARAMDEF
;
10210 return mono_custom_attrs_from_index_checked (image
, idx
, error
);
10214 mono_custom_attrs_has_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
10218 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
10219 klass
= ainfo
->attrs
[i
].ctor
->klass
;
10220 if (mono_class_has_parent (klass
, attr_klass
) || (MONO_CLASS_IS_INTERFACE (attr_klass
) && mono_class_is_assignable_from (attr_klass
, klass
)))
10227 mono_custom_attrs_get_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
10230 MonoObject
*res
= mono_custom_attrs_get_attr_checked (ainfo
, attr_klass
, &error
);
10231 g_assert (mono_error_ok (&error
)); /*FIXME proper error handling*/
10236 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
, MonoError
*error
)
10242 mono_error_init (error
);
10245 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
10246 klass
= ainfo
->attrs
[i
].ctor
->klass
;
10247 if (mono_class_has_parent (klass
, attr_klass
)) {
10252 if (attr_index
== -1)
10255 attrs
= mono_custom_attrs_construct_by_type (ainfo
, NULL
, error
);
10256 if (!mono_error_ok (error
))
10258 return mono_array_get (attrs
, MonoObject
*, attr_index
);
10262 * mono_reflection_get_custom_attrs_info:
10263 * @obj: a reflection object handle
10265 * Return the custom attribute info for attributes defined for the
10266 * reflection handle @obj. The objects.
10268 * FIXME this function leaks like a sieve for SRE objects.
10270 MonoCustomAttrInfo
*
10271 mono_reflection_get_custom_attrs_info (MonoObject
*obj
)
10274 MonoCustomAttrInfo
*result
= mono_reflection_get_custom_attrs_info_checked (obj
, &error
);
10275 mono_error_assert_ok (&error
);
10280 * mono_reflection_get_custom_attrs_info_checked:
10281 * @obj: a reflection object handle
10282 * @error: set on error
10284 * Return the custom attribute info for attributes defined for the
10285 * reflection handle @obj. The objects.
10287 * On failure returns NULL and sets @error.
10289 * FIXME this function leaks like a sieve for SRE objects.
10291 MonoCustomAttrInfo
*
10292 mono_reflection_get_custom_attrs_info_checked (MonoObject
*obj
, MonoError
*error
)
10295 MonoCustomAttrInfo
*cinfo
= NULL
;
10297 mono_error_init (error
);
10299 klass
= obj
->vtable
->klass
;
10300 if (klass
== mono_defaults
.monotype_class
) {
10301 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
10302 return_val_if_nok (error
, NULL
);
10303 klass
= mono_class_from_mono_type (type
);
10304 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10305 cinfo
= mono_custom_attrs_from_class_checked (klass
, error
);
10306 return_val_if_nok (error
, NULL
);
10307 } else if (strcmp ("Assembly", klass
->name
) == 0 || strcmp ("MonoAssembly", klass
->name
) == 0) {
10308 MonoReflectionAssembly
*rassembly
= (MonoReflectionAssembly
*)obj
;
10309 cinfo
= mono_custom_attrs_from_assembly_checked (rassembly
->assembly
, error
);
10310 return_val_if_nok (error
, NULL
);
10311 } else if (strcmp ("Module", klass
->name
) == 0 || strcmp ("MonoModule", klass
->name
) == 0) {
10312 MonoReflectionModule
*module
= (MonoReflectionModule
*)obj
;
10313 cinfo
= mono_custom_attrs_from_module (module
->image
, error
);
10314 return_val_if_nok (error
, NULL
);
10315 } else if (strcmp ("MonoProperty", klass
->name
) == 0) {
10316 MonoReflectionProperty
*rprop
= (MonoReflectionProperty
*)obj
;
10317 cinfo
= mono_custom_attrs_from_property_checked (rprop
->property
->parent
, rprop
->property
, error
);
10318 return_val_if_nok (error
, NULL
);
10319 } else if (strcmp ("MonoEvent", klass
->name
) == 0) {
10320 MonoReflectionMonoEvent
*revent
= (MonoReflectionMonoEvent
*)obj
;
10321 cinfo
= mono_custom_attrs_from_event_checked (revent
->event
->parent
, revent
->event
, error
);
10322 return_val_if_nok (error
, NULL
);
10323 } else if (strcmp ("MonoField", klass
->name
) == 0) {
10324 MonoReflectionField
*rfield
= (MonoReflectionField
*)obj
;
10325 cinfo
= mono_custom_attrs_from_field_checked (rfield
->field
->parent
, rfield
->field
, error
);
10326 return_val_if_nok (error
, NULL
);
10327 } else if ((strcmp ("MonoMethod", klass
->name
) == 0) || (strcmp ("MonoCMethod", klass
->name
) == 0)) {
10328 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
10329 cinfo
= mono_custom_attrs_from_method_checked (rmethod
->method
, error
);
10330 return_val_if_nok (error
, NULL
);
10331 } else if ((strcmp ("MonoGenericMethod", klass
->name
) == 0) || (strcmp ("MonoGenericCMethod", klass
->name
) == 0)) {
10332 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
10333 cinfo
= mono_custom_attrs_from_method_checked (rmethod
->method
, error
);
10334 return_val_if_nok (error
, NULL
);
10335 } else if (strcmp ("ParameterInfo", klass
->name
) == 0 || strcmp ("MonoParameterInfo", klass
->name
) == 0) {
10336 MonoReflectionParameter
*param
= (MonoReflectionParameter
*)obj
;
10337 MonoClass
*member_class
= mono_object_class (param
->MemberImpl
);
10338 if (mono_class_is_reflection_method_or_constructor (member_class
)) {
10339 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
10340 cinfo
= mono_custom_attrs_from_param_checked (rmethod
->method
, param
->PositionImpl
+ 1, error
);
10341 return_val_if_nok (error
, NULL
);
10342 } else if (is_sr_mono_property (member_class
)) {
10343 MonoReflectionProperty
*prop
= (MonoReflectionProperty
*)param
->MemberImpl
;
10344 MonoMethod
*method
;
10345 if (!(method
= prop
->property
->get
))
10346 method
= prop
->property
->set
;
10349 cinfo
= mono_custom_attrs_from_param_checked (method
, param
->PositionImpl
+ 1, error
);
10350 return_val_if_nok (error
, NULL
);
10352 #ifndef DISABLE_REFLECTION_EMIT
10353 else if (is_sre_method_on_tb_inst (member_class
)) {/*XXX This is a workaround for Compiler Context*/
10354 MonoMethod
*method
= mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst
*)param
->MemberImpl
, error
);
10355 return_val_if_nok (error
, NULL
);
10356 cinfo
= mono_custom_attrs_from_param_checked (method
, param
->PositionImpl
+ 1, error
);
10357 return_val_if_nok (error
, NULL
);
10358 } else if (is_sre_ctor_on_tb_inst (member_class
)) { /*XX This is a workaround for Compiler Context*/
10359 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)param
->MemberImpl
;
10360 MonoMethod
*method
= NULL
;
10361 if (is_sre_ctor_builder (mono_object_class (c
->cb
)))
10362 method
= ((MonoReflectionCtorBuilder
*)c
->cb
)->mhandle
;
10363 else if (is_sr_mono_cmethod (mono_object_class (c
->cb
)))
10364 method
= ((MonoReflectionMethod
*)c
->cb
)->method
;
10366 g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class
));
10368 cinfo
= mono_custom_attrs_from_param_checked (method
, param
->PositionImpl
+ 1, error
);
10369 return_val_if_nok (error
, NULL
);
10373 char *type_name
= mono_type_get_full_name (member_class
);
10374 mono_error_set_not_supported (error
,
10375 "Custom attributes on a ParamInfo with member %s are not supported",
10377 g_free (type_name
);
10380 } else if (strcmp ("AssemblyBuilder", klass
->name
) == 0) {
10381 MonoReflectionAssemblyBuilder
*assemblyb
= (MonoReflectionAssemblyBuilder
*)obj
;
10382 cinfo
= mono_custom_attrs_from_builders (NULL
, assemblyb
->assembly
.assembly
->image
, assemblyb
->cattrs
);
10383 } else if (strcmp ("TypeBuilder", klass
->name
) == 0) {
10384 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
10385 cinfo
= mono_custom_attrs_from_builders (NULL
, &tb
->module
->dynamic_image
->image
, tb
->cattrs
);
10386 } else if (strcmp ("ModuleBuilder", klass
->name
) == 0) {
10387 MonoReflectionModuleBuilder
*mb
= (MonoReflectionModuleBuilder
*)obj
;
10388 cinfo
= mono_custom_attrs_from_builders (NULL
, &mb
->dynamic_image
->image
, mb
->cattrs
);
10389 } else if (strcmp ("ConstructorBuilder", klass
->name
) == 0) {
10390 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
10391 cinfo
= mono_custom_attrs_from_builders (NULL
, cb
->mhandle
->klass
->image
, cb
->cattrs
);
10392 } else if (strcmp ("MethodBuilder", klass
->name
) == 0) {
10393 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
10394 cinfo
= mono_custom_attrs_from_builders (NULL
, mb
->mhandle
->klass
->image
, mb
->cattrs
);
10395 } else if (strcmp ("FieldBuilder", klass
->name
) == 0) {
10396 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
10397 cinfo
= mono_custom_attrs_from_builders (NULL
, &((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
->image
, fb
->cattrs
);
10398 } else if (strcmp ("MonoGenericClass", klass
->name
) == 0) {
10399 MonoReflectionGenericClass
*gclass
= (MonoReflectionGenericClass
*)obj
;
10400 cinfo
= mono_reflection_get_custom_attrs_info_checked ((MonoObject
*)gclass
->generic_type
, error
);
10401 return_val_if_nok (error
, NULL
);
10402 } else { /* handle other types here... */
10403 g_error ("get custom attrs not yet supported for %s", klass
->name
);
10410 * mono_reflection_get_custom_attrs_by_type:
10411 * @obj: a reflection object handle
10413 * Return an array with all the custom attributes defined of the
10414 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
10415 * of that type are returned. The objects are fully build. Return NULL if a loading error
10419 mono_reflection_get_custom_attrs_by_type (MonoObject
*obj
, MonoClass
*attr_klass
, MonoError
*error
)
10422 MonoCustomAttrInfo
*cinfo
;
10424 mono_error_init (error
);
10426 cinfo
= mono_reflection_get_custom_attrs_info_checked (obj
, error
);
10427 return_val_if_nok (error
, NULL
);
10429 result
= mono_custom_attrs_construct_by_type (cinfo
, attr_klass
, error
);
10432 if (!cinfo
->cached
)
10433 mono_custom_attrs_free (cinfo
);
10435 mono_loader_assert_no_error ();
10436 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, 0);
10443 * mono_reflection_get_custom_attrs:
10444 * @obj: a reflection object handle
10446 * Return an array with all the custom attributes defined of the
10447 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10451 mono_reflection_get_custom_attrs (MonoObject
*obj
)
10455 return mono_reflection_get_custom_attrs_by_type (obj
, NULL
, &error
);
10459 * mono_reflection_get_custom_attrs_data:
10460 * @obj: a reflection obj handle
10462 * Returns an array of System.Reflection.CustomAttributeData,
10463 * which include information about attributes reflected on
10464 * types loaded using the Reflection Only methods
10467 mono_reflection_get_custom_attrs_data (MonoObject
*obj
)
10471 result
= mono_reflection_get_custom_attrs_data_checked (obj
, &error
);
10472 mono_error_cleanup (&error
); /* FIXME new API that doesn't swallow the error */
10477 * mono_reflection_get_custom_attrs_data_checked:
10478 * @obj: a reflection obj handle
10479 * @error: set on error
10481 * Returns an array of System.Reflection.CustomAttributeData,
10482 * which include information about attributes reflected on
10483 * types loaded using the Reflection Only methods
10486 mono_reflection_get_custom_attrs_data_checked (MonoObject
*obj
, MonoError
*error
)
10489 MonoCustomAttrInfo
*cinfo
;
10491 mono_error_init (error
);
10493 cinfo
= mono_reflection_get_custom_attrs_info_checked (obj
, error
);
10494 return_val_if_nok (error
, NULL
);
10496 result
= mono_custom_attrs_data_construct (cinfo
, error
);
10497 return_val_if_nok (error
, NULL
);
10498 if (!cinfo
->cached
)
10499 mono_custom_attrs_free (cinfo
);
10501 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, 0);
10503 if (mono_loader_get_last_error ())
10504 mono_error_set_from_loader_error (error
);
10509 static MonoReflectionType
*
10510 mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
, MonoError
*error
)
10512 static MonoMethod
*method_get_underlying_system_type
= NULL
;
10513 MonoReflectionType
*rt
;
10514 MonoMethod
*usertype_method
;
10516 mono_error_init (error
);
10518 if (!method_get_underlying_system_type
)
10519 method_get_underlying_system_type
= mono_class_get_method_from_name (mono_defaults
.systemtype_class
, "get_UnderlyingSystemType", 0);
10521 usertype_method
= mono_object_get_virtual_method ((MonoObject
*) t
, method_get_underlying_system_type
);
10523 rt
= (MonoReflectionType
*) mono_runtime_invoke_checked (usertype_method
, t
, NULL
, error
);
10530 is_corlib_type (MonoClass
*klass
)
10532 return klass
->image
== mono_defaults
.corlib
;
10535 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10536 static MonoClass *cached_class; \
10537 if (cached_class) \
10538 return cached_class == _class; \
10539 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10540 cached_class = _class; \
10547 #ifndef DISABLE_REFLECTION_EMIT
10549 is_sre_array (MonoClass
*klass
)
10551 check_corlib_type_cached (klass
, "System.Reflection.Emit", "ArrayType");
10555 is_sre_byref (MonoClass
*klass
)
10557 check_corlib_type_cached (klass
, "System.Reflection.Emit", "ByRefType");
10561 is_sre_pointer (MonoClass
*klass
)
10563 check_corlib_type_cached (klass
, "System.Reflection.Emit", "PointerType");
10567 is_sre_generic_instance (MonoClass
*klass
)
10569 check_corlib_type_cached (klass
, "System.Reflection", "MonoGenericClass");
10573 is_sre_type_builder (MonoClass
*klass
)
10575 check_corlib_type_cached (klass
, "System.Reflection.Emit", "TypeBuilder");
10579 is_sre_method_builder (MonoClass
*klass
)
10581 check_corlib_type_cached (klass
, "System.Reflection.Emit", "MethodBuilder");
10585 is_sre_ctor_builder (MonoClass
*klass
)
10587 check_corlib_type_cached (klass
, "System.Reflection.Emit", "ConstructorBuilder");
10591 is_sre_field_builder (MonoClass
*klass
)
10593 check_corlib_type_cached (klass
, "System.Reflection.Emit", "FieldBuilder");
10597 is_sre_method_on_tb_inst (MonoClass
*klass
)
10599 check_corlib_type_cached (klass
, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10603 is_sre_ctor_on_tb_inst (MonoClass
*klass
)
10605 check_corlib_type_cached (klass
, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10609 mono_reflection_type_get_handle (MonoReflectionType
* ref
, MonoError
*error
)
10612 mono_error_init (error
);
10619 if (is_usertype (ref
)) {
10620 ref
= mono_reflection_type_get_underlying_system_type (ref
, error
);
10621 if (ref
== NULL
|| is_usertype (ref
) || !is_ok (error
))
10627 klass
= mono_object_class (ref
);
10629 if (is_sre_array (klass
)) {
10631 MonoReflectionArrayType
*sre_array
= (MonoReflectionArrayType
*)ref
;
10632 MonoType
*base
= mono_reflection_type_get_handle (sre_array
->element_type
, error
);
10633 return_val_if_nok (error
, NULL
);
10635 if (sre_array
->rank
== 0) //single dimentional array
10636 res
= &mono_array_class_get (mono_class_from_mono_type (base
), 1)->byval_arg
;
10638 res
= &mono_bounded_array_class_get (mono_class_from_mono_type (base
), sre_array
->rank
, TRUE
)->byval_arg
;
10639 sre_array
->type
.type
= res
;
10641 } else if (is_sre_byref (klass
)) {
10643 MonoReflectionDerivedType
*sre_byref
= (MonoReflectionDerivedType
*)ref
;
10644 MonoType
*base
= mono_reflection_type_get_handle (sre_byref
->element_type
, error
);
10645 return_val_if_nok (error
, NULL
);
10647 res
= &mono_class_from_mono_type (base
)->this_arg
;
10648 sre_byref
->type
.type
= res
;
10650 } else if (is_sre_pointer (klass
)) {
10652 MonoReflectionDerivedType
*sre_pointer
= (MonoReflectionDerivedType
*)ref
;
10653 MonoType
*base
= mono_reflection_type_get_handle (sre_pointer
->element_type
, error
);
10654 return_val_if_nok (error
, NULL
);
10656 res
= &mono_ptr_class_get (base
)->byval_arg
;
10657 sre_pointer
->type
.type
= res
;
10659 } else if (is_sre_generic_instance (klass
)) {
10660 MonoType
*res
, **types
;
10661 MonoReflectionGenericClass
*gclass
= (MonoReflectionGenericClass
*)ref
;
10664 count
= mono_array_length (gclass
->type_arguments
);
10665 types
= g_new0 (MonoType
*, count
);
10666 for (i
= 0; i
< count
; ++i
) {
10667 MonoReflectionType
*t
= (MonoReflectionType
*)mono_array_get (gclass
->type_arguments
, gpointer
, i
);
10668 types
[i
] = mono_reflection_type_get_handle (t
, error
);
10669 if (!types
[i
] || !is_ok (error
)) {
10675 res
= mono_reflection_bind_generic_parameters (gclass
->generic_type
, count
, types
, error
);
10678 gclass
->type
.type
= res
;
10682 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref
)->byval_arg
));
10687 mono_reflection_create_unmanaged_type (MonoReflectionType
*type
)
10690 mono_reflection_type_get_handle (type
, &error
);
10691 mono_error_set_pending_exception (&error
);
10695 reflection_register_with_runtime (MonoReflectionType
*type
, MonoError
*error
)
10697 MonoDomain
*domain
= mono_object_domain ((MonoObject
*)type
);
10700 mono_error_init (error
);
10702 MonoType
*res
= mono_reflection_type_get_handle (type
, error
);
10704 if (!res
&& is_ok (error
)) {
10705 mono_error_set_argument (error
, NULL
, "Invalid generic instantiation, one or more arguments are not proper user types");
10707 return_val_if_nok (error
, FALSE
);
10709 klass
= mono_class_from_mono_type (res
);
10711 mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10712 mono_domain_lock (domain
);
10714 if (!image_is_dynamic (klass
->image
)) {
10715 mono_class_setup_supertypes (klass
);
10717 if (!domain
->type_hash
)
10718 domain
->type_hash
= mono_g_hash_table_new_type ((GHashFunc
)mono_metadata_type_hash
,
10719 (GCompareFunc
)mono_metadata_type_equal
, MONO_HASH_VALUE_GC
, MONO_ROOT_SOURCE_DOMAIN
, "domain reflection types table");
10720 mono_g_hash_table_insert (domain
->type_hash
, res
, type
);
10722 mono_domain_unlock (domain
);
10723 mono_loader_unlock ();
10729 mono_reflection_register_with_runtime (MonoReflectionType
*type
)
10732 (void) reflection_register_with_runtime (type
, &error
);
10733 mono_error_set_pending_exception (&error
);
10737 * LOCKING: Assumes the loader lock is held.
10739 static MonoMethodSignature
*
10740 parameters_to_signature (MonoImage
*image
, MonoArray
*parameters
, MonoError
*error
) {
10741 MonoMethodSignature
*sig
;
10744 mono_error_init (error
);
10746 count
= parameters
? mono_array_length (parameters
): 0;
10748 sig
= (MonoMethodSignature
*)image_g_malloc0 (image
, MONO_SIZEOF_METHOD_SIGNATURE
+ sizeof (MonoType
*) * count
);
10749 sig
->param_count
= count
;
10750 sig
->sentinelpos
= -1; /* FIXME */
10751 for (i
= 0; i
< count
; ++i
) {
10752 sig
->params
[i
] = mono_type_array_get_and_resolve (parameters
, i
, error
);
10753 if (!is_ok (error
)) {
10754 image_g_free (image
, sig
);
10762 * LOCKING: Assumes the loader lock is held.
10764 static MonoMethodSignature
*
10765 ctor_builder_to_signature (MonoImage
*image
, MonoReflectionCtorBuilder
*ctor
, MonoError
*error
) {
10766 MonoMethodSignature
*sig
;
10768 mono_error_init (error
);
10770 sig
= parameters_to_signature (image
, ctor
->parameters
, error
);
10771 return_val_if_nok (error
, NULL
);
10772 sig
->hasthis
= ctor
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
10773 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
10778 * LOCKING: Assumes the loader lock is held.
10780 static MonoMethodSignature
*
10781 method_builder_to_signature (MonoImage
*image
, MonoReflectionMethodBuilder
*method
, MonoError
*error
) {
10782 MonoMethodSignature
*sig
;
10784 mono_error_init (error
);
10786 sig
= parameters_to_signature (image
, method
->parameters
, error
);
10787 return_val_if_nok (error
, NULL
);
10788 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
10789 if (method
->rtype
) {
10790 sig
->ret
= mono_reflection_type_get_handle ((MonoReflectionType
*)method
->rtype
, error
);
10791 if (!is_ok (error
)) {
10792 image_g_free (image
, sig
);
10796 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
10798 sig
->generic_param_count
= method
->generic_params
? mono_array_length (method
->generic_params
) : 0;
10802 static MonoMethodSignature
*
10803 dynamic_method_to_signature (MonoReflectionDynamicMethod
*method
, MonoError
*error
) {
10804 MonoMethodSignature
*sig
;
10806 mono_error_init (error
);
10808 sig
= parameters_to_signature (NULL
, method
->parameters
, error
);
10809 return_val_if_nok (error
, NULL
);
10810 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
10811 if (method
->rtype
) {
10812 sig
->ret
= mono_reflection_type_get_handle (method
->rtype
, error
);
10813 if (!is_ok (error
)) {
10818 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
10820 sig
->generic_param_count
= 0;
10825 get_prop_name_and_type (MonoObject
*prop
, char **name
, MonoType
**type
, MonoError
*error
)
10827 mono_error_init (error
);
10828 MonoClass
*klass
= mono_object_class (prop
);
10829 if (strcmp (klass
->name
, "PropertyBuilder") == 0) {
10830 MonoReflectionPropertyBuilder
*pb
= (MonoReflectionPropertyBuilder
*)prop
;
10831 *name
= mono_string_to_utf8 (pb
->name
);
10832 *type
= mono_reflection_type_get_handle ((MonoReflectionType
*)pb
->type
, error
);
10834 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)prop
;
10835 *name
= g_strdup (p
->property
->name
);
10836 if (p
->property
->get
)
10837 *type
= mono_method_signature (p
->property
->get
)->ret
;
10839 *type
= mono_method_signature (p
->property
->set
)->params
[mono_method_signature (p
->property
->set
)->param_count
- 1];
10844 get_field_name_and_type (MonoObject
*field
, char **name
, MonoType
**type
, MonoError
*error
)
10846 mono_error_init (error
);
10847 MonoClass
*klass
= mono_object_class (field
);
10848 if (strcmp (klass
->name
, "FieldBuilder") == 0) {
10849 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)field
;
10850 *name
= mono_string_to_utf8 (fb
->name
);
10851 *type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
, error
);
10853 MonoReflectionField
*f
= (MonoReflectionField
*)field
;
10854 *name
= g_strdup (mono_field_get_name (f
->field
));
10855 *type
= f
->field
->type
;
10859 #else /* DISABLE_REFLECTION_EMIT */
10862 mono_reflection_register_with_runtime (MonoReflectionType
*type
)
10864 /* This is empty */
10868 is_sre_type_builder (MonoClass
*klass
)
10874 is_sre_generic_instance (MonoClass
*klass
)
10880 init_type_builder_generics (MonoObject
*type
)
10884 #endif /* !DISABLE_REFLECTION_EMIT */
10888 is_sr_mono_field (MonoClass
*klass
)
10890 check_corlib_type_cached (klass
, "System.Reflection", "MonoField");
10894 is_sr_mono_property (MonoClass
*klass
)
10896 check_corlib_type_cached (klass
, "System.Reflection", "MonoProperty");
10900 is_sr_mono_method (MonoClass
*klass
)
10902 check_corlib_type_cached (klass
, "System.Reflection", "MonoMethod");
10906 is_sr_mono_cmethod (MonoClass
*klass
)
10908 check_corlib_type_cached (klass
, "System.Reflection", "MonoCMethod");
10912 is_sr_mono_generic_method (MonoClass
*klass
)
10914 check_corlib_type_cached (klass
, "System.Reflection", "MonoGenericMethod");
10918 is_sr_mono_generic_cmethod (MonoClass
*klass
)
10920 check_corlib_type_cached (klass
, "System.Reflection", "MonoGenericCMethod");
10924 mono_class_is_reflection_method_or_constructor (MonoClass
*klass
)
10926 return is_sr_mono_method (klass
) || is_sr_mono_cmethod (klass
) || is_sr_mono_generic_method (klass
) || is_sr_mono_generic_cmethod (klass
);
10930 is_usertype (MonoReflectionType
*ref
)
10932 MonoClass
*klass
= mono_object_class (ref
);
10933 return klass
->image
!= mono_defaults
.corlib
|| strcmp ("TypeDelegator", klass
->name
) == 0;
10936 static MonoReflectionType
*
10937 mono_reflection_type_resolve_user_types (MonoReflectionType
*type
, MonoError
*error
)
10939 mono_error_init (error
);
10940 if (!type
|| type
->type
)
10943 if (is_usertype (type
)) {
10944 type
= mono_reflection_type_get_underlying_system_type (type
, error
);
10945 return_val_if_nok (error
, NULL
);
10946 if (is_usertype (type
)) {
10947 mono_error_set_not_supported (error
, "User defined subclasses of System.Type are not yet supported22");
10955 * encode_cattr_value:
10956 * Encode a value in a custom attribute stream of bytes.
10957 * The value to encode is either supplied as an object in argument val
10958 * (valuetypes are boxed), or as a pointer to the data in the
10960 * @type represents the type of the value
10961 * @buffer is the start of the buffer
10962 * @p the current position in the buffer
10963 * @buflen contains the size of the buffer and is used to return the new buffer size
10964 * if this needs to be realloced.
10965 * @retbuffer and @retp return the start and the position of the buffer
10966 * @error set on error.
10969 encode_cattr_value (MonoAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, MonoObject
*arg
, char *argval
, MonoError
*error
)
10971 MonoTypeEnum simple_type
;
10973 mono_error_init (error
);
10974 if ((p
-buffer
) + 10 >= *buflen
) {
10977 newbuf
= (char *)g_realloc (buffer
, *buflen
);
10978 p
= newbuf
+ (p
-buffer
);
10982 argval
= ((char*)arg
+ sizeof (MonoObject
));
10983 simple_type
= type
->type
;
10985 switch (simple_type
) {
10986 case MONO_TYPE_BOOLEAN
:
10991 case MONO_TYPE_CHAR
:
10994 swap_with_size (p
, argval
, 2, 1);
11000 swap_with_size (p
, argval
, 4, 1);
11004 swap_with_size (p
, argval
, 8, 1);
11009 swap_with_size (p
, argval
, 8, 1);
11012 case MONO_TYPE_VALUETYPE
:
11013 if (type
->data
.klass
->enumtype
) {
11014 simple_type
= mono_class_enum_basetype (type
->data
.klass
)->type
;
11017 g_warning ("generic valutype %s not handled in custom attr value decoding", type
->data
.klass
->name
);
11020 case MONO_TYPE_STRING
: {
11027 str
= mono_string_to_utf8 ((MonoString
*)arg
);
11028 slen
= strlen (str
);
11029 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
11033 newbuf
= (char *)g_realloc (buffer
, *buflen
);
11034 p
= newbuf
+ (p
-buffer
);
11037 mono_metadata_encode_value (slen
, p
, &p
);
11038 memcpy (p
, str
, slen
);
11043 case MONO_TYPE_CLASS
: {
11046 MonoType
*arg_type
;
11052 arg_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)arg
, error
);
11053 return_if_nok (error
);
11055 str
= type_get_qualified_name (arg_type
, NULL
);
11056 slen
= strlen (str
);
11057 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
11061 newbuf
= (char *)g_realloc (buffer
, *buflen
);
11062 p
= newbuf
+ (p
-buffer
);
11065 mono_metadata_encode_value (slen
, p
, &p
);
11066 memcpy (p
, str
, slen
);
11071 case MONO_TYPE_SZARRAY
: {
11073 MonoClass
*eclass
, *arg_eclass
;
11076 *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff;
11079 len
= mono_array_length ((MonoArray
*)arg
);
11081 *p
++ = (len
>> 8) & 0xff;
11082 *p
++ = (len
>> 16) & 0xff;
11083 *p
++ = (len
>> 24) & 0xff;
11085 *retbuffer
= buffer
;
11086 eclass
= type
->data
.klass
;
11087 arg_eclass
= mono_object_class (arg
)->element_class
;
11090 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11091 eclass
= mono_defaults
.object_class
;
11093 if (eclass
== mono_defaults
.object_class
&& arg_eclass
->valuetype
) {
11094 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
11095 int elsize
= mono_class_array_element_size (arg_eclass
);
11096 for (i
= 0; i
< len
; ++i
) {
11097 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &arg_eclass
->byval_arg
, NULL
, elptr
, error
);
11098 return_if_nok (error
);
11101 } else if (eclass
->valuetype
&& arg_eclass
->valuetype
) {
11102 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
11103 int elsize
= mono_class_array_element_size (eclass
);
11104 for (i
= 0; i
< len
; ++i
) {
11105 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, NULL
, elptr
, error
);
11106 return_if_nok (error
);
11110 for (i
= 0; i
< len
; ++i
) {
11111 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, mono_array_get ((MonoArray
*)arg
, MonoObject
*, i
), NULL
, error
);
11112 return_if_nok (error
);
11117 case MONO_TYPE_OBJECT
: {
11123 * The parameter type is 'object' but the type of the actual
11124 * argument is not. So we have to add type information to the blob
11125 * too. This is completely undocumented in the spec.
11129 *p
++ = MONO_TYPE_STRING
; // It's same hack as MS uses
11134 klass
= mono_object_class (arg
);
11136 if (mono_object_isinst (arg
, mono_defaults
.systemtype_class
)) {
11139 } else if (klass
->enumtype
) {
11141 } else if (klass
== mono_defaults
.string_class
) {
11142 simple_type
= MONO_TYPE_STRING
;
11145 } else if (klass
->rank
== 1) {
11147 if (klass
->element_class
->byval_arg
.type
== MONO_TYPE_OBJECT
)
11148 /* See Partition II, Appendix B3 */
11151 *p
++ = klass
->element_class
->byval_arg
.type
;
11152 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &klass
->byval_arg
, arg
, NULL
, error
);
11153 return_if_nok (error
);
11155 } else if (klass
->byval_arg
.type
>= MONO_TYPE_BOOLEAN
&& klass
->byval_arg
.type
<= MONO_TYPE_R8
) {
11156 *p
++ = simple_type
= klass
->byval_arg
.type
;
11159 g_error ("unhandled type in custom attr");
11161 str
= type_get_qualified_name (mono_class_get_type(klass
), NULL
);
11162 slen
= strlen (str
);
11163 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
11167 newbuf
= (char *)g_realloc (buffer
, *buflen
);
11168 p
= newbuf
+ (p
-buffer
);
11171 mono_metadata_encode_value (slen
, p
, &p
);
11172 memcpy (p
, str
, slen
);
11175 simple_type
= mono_class_enum_basetype (klass
)->type
;
11179 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type
);
11182 *retbuffer
= buffer
;
11186 encode_field_or_prop_type (MonoType
*type
, char *p
, char **retp
)
11188 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
11189 char *str
= type_get_qualified_name (type
, NULL
);
11190 int slen
= strlen (str
);
11194 * This seems to be optional...
11197 mono_metadata_encode_value (slen
, p
, &p
);
11198 memcpy (p
, str
, slen
);
11201 } else if (type
->type
== MONO_TYPE_OBJECT
) {
11203 } else if (type
->type
== MONO_TYPE_CLASS
) {
11204 /* it should be a type: encode_cattr_value () has the check */
11207 mono_metadata_encode_value (type
->type
, p
, &p
);
11208 if (type
->type
== MONO_TYPE_SZARRAY
)
11209 /* See the examples in Partition VI, Annex B */
11210 encode_field_or_prop_type (&type
->data
.klass
->byval_arg
, p
, &p
);
11216 #ifndef DISABLE_REFLECTION_EMIT
11218 encode_named_val (MonoReflectionAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, char *name
, MonoObject
*value
, MonoError
*error
)
11222 mono_error_init (error
);
11224 /* Preallocate a large enough buffer */
11225 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
11226 char *str
= type_get_qualified_name (type
, NULL
);
11227 len
= strlen (str
);
11229 } else if (type
->type
== MONO_TYPE_SZARRAY
&& type
->data
.klass
->enumtype
) {
11230 char *str
= type_get_qualified_name (&type
->data
.klass
->byval_arg
, NULL
);
11231 len
= strlen (str
);
11236 len
+= strlen (name
);
11238 if ((p
-buffer
) + 20 + len
>= *buflen
) {
11242 newbuf
= (char *)g_realloc (buffer
, *buflen
);
11243 p
= newbuf
+ (p
-buffer
);
11247 encode_field_or_prop_type (type
, p
, &p
);
11249 len
= strlen (name
);
11250 mono_metadata_encode_value (len
, p
, &p
);
11251 memcpy (p
, name
, len
);
11253 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, buflen
, type
, value
, NULL
, error
);
11254 return_if_nok (error
);
11256 *retbuffer
= buffer
;
11260 * mono_reflection_get_custom_attrs_blob:
11261 * @ctor: custom attribute constructor
11262 * @ctorArgs: arguments o the constructor
11268 * Creates the blob of data that needs to be saved in the metadata and that represents
11269 * the custom attributed described by @ctor, @ctorArgs etc.
11270 * Returns: a Byte array representing the blob of data.
11273 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
11276 MonoArray
*result
= mono_reflection_get_custom_attrs_blob_checked (assembly
, ctor
, ctorArgs
, properties
, propValues
, fields
, fieldValues
, &error
);
11277 mono_error_cleanup (&error
); /* FIXME better API that doesn't swallow the error */
11282 * mono_reflection_get_custom_attrs_blob_checked:
11283 * @ctor: custom attribute constructor
11284 * @ctorArgs: arguments o the constructor
11289 * @error: set on error
11291 * Creates the blob of data that needs to be saved in the metadata and that represents
11292 * the custom attributed described by @ctor, @ctorArgs etc.
11293 * Returns: a Byte array representing the blob of data. On failure returns NULL and sets @error.
11296 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
, MonoError
*error
)
11298 MonoArray
*result
= NULL
;
11299 MonoMethodSignature
*sig
;
11304 mono_error_init (error
);
11306 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
11307 /* sig is freed later so allocate it in the heap */
11308 sig
= ctor_builder_to_signature (NULL
, (MonoReflectionCtorBuilder
*)ctor
, error
);
11309 if (!is_ok (error
)) {
11314 sig
= mono_method_signature (((MonoReflectionMethod
*)ctor
)->method
);
11317 g_assert (mono_array_length (ctorArgs
) == sig
->param_count
);
11319 p
= buffer
= (char *)g_malloc (buflen
);
11320 /* write the prolog */
11323 for (i
= 0; i
< sig
->param_count
; ++i
) {
11324 arg
= mono_array_get (ctorArgs
, MonoObject
*, i
);
11325 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, &buflen
, sig
->params
[i
], arg
, NULL
, error
);
11326 if (!is_ok (error
)) goto leave
;
11330 i
+= mono_array_length (properties
);
11332 i
+= mono_array_length (fields
);
11334 *p
++ = (i
>> 8) & 0xff;
11337 for (i
= 0; i
< mono_array_length (properties
); ++i
) {
11341 prop
= (MonoObject
*)mono_array_get (properties
, gpointer
, i
);
11342 get_prop_name_and_type (prop
, &pname
, &ptype
, error
);
11343 if (!is_ok (error
)) goto leave
;
11344 *p
++ = 0x54; /* PROPERTY signature */
11345 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ptype
, pname
, (MonoObject
*)mono_array_get (propValues
, gpointer
, i
), error
);
11347 if (!is_ok (error
)) goto leave
;
11353 for (i
= 0; i
< mono_array_length (fields
); ++i
) {
11357 field
= (MonoObject
*)mono_array_get (fields
, gpointer
, i
);
11358 get_field_name_and_type (field
, &fname
, &ftype
, error
);
11359 if (!is_ok (error
)) goto leave
;
11360 *p
++ = 0x53; /* FIELD signature */
11361 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ftype
, fname
, (MonoObject
*)mono_array_get (fieldValues
, gpointer
, i
), error
);
11363 if (!is_ok (error
)) goto leave
;
11367 g_assert (p
- buffer
<= buflen
);
11368 buflen
= p
- buffer
;
11369 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
11370 p
= mono_array_addr (result
, char, 0);
11371 memcpy (p
, buffer
, buflen
);
11374 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod"))
11380 * reflection_setup_internal_class:
11381 * @tb: a TypeBuilder object
11382 * @error: set on error
11384 * Creates a MonoClass that represents the TypeBuilder.
11385 * This is a trick that lets us simplify a lot of reflection code
11386 * (and will allow us to support Build and Run assemblies easier).
11388 * Returns TRUE on success. On failure, returns FALSE and sets @error.
11391 reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
, MonoError
*error
)
11393 MonoClass
*klass
, *parent
;
11395 mono_error_init (error
);
11396 RESOLVE_TYPE (tb
->parent
, error
);
11397 return_val_if_nok (error
, FALSE
);
11399 mono_loader_lock ();
11402 MonoType
*parent_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
->parent
, error
);
11403 if (!is_ok (error
)) {
11404 mono_loader_unlock ();
11407 /* check so we can compile corlib correctly */
11408 if (strcmp (mono_object_class (tb
->parent
)->name
, "TypeBuilder") == 0) {
11409 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11410 parent
= parent_type
->data
.klass
;
11412 parent
= mono_class_from_mono_type (parent_type
);
11418 /* the type has already being created: it means we just have to change the parent */
11419 if (tb
->type
.type
) {
11420 klass
= mono_class_from_mono_type (tb
->type
.type
);
11421 klass
->parent
= NULL
;
11422 /* fool mono_class_setup_parent */
11423 klass
->supertypes
= NULL
;
11424 mono_class_setup_parent (klass
, parent
);
11425 mono_class_setup_mono_type (klass
);
11426 mono_loader_unlock ();
11430 klass
= (MonoClass
*)mono_image_alloc0 (&tb
->module
->dynamic_image
->image
, sizeof (MonoClass
));
11432 klass
->image
= &tb
->module
->dynamic_image
->image
;
11434 klass
->inited
= 1; /* we lie to the runtime */
11435 klass
->name
= mono_string_to_utf8_image (klass
->image
, tb
->name
, error
);
11436 if (!is_ok (error
))
11438 klass
->name_space
= mono_string_to_utf8_image (klass
->image
, tb
->nspace
, error
);
11439 if (!is_ok (error
))
11441 klass
->type_token
= MONO_TOKEN_TYPE_DEF
| tb
->table_idx
;
11442 klass
->flags
= tb
->attrs
;
11444 mono_profiler_class_event (klass
, MONO_PROFILE_START_LOAD
);
11446 klass
->element_class
= klass
;
11448 if (mono_class_get_ref_info (klass
) == NULL
) {
11450 mono_class_set_ref_info (klass
, tb
);
11452 /* Put into cache so mono_class_get_checked () will find it.
11453 Skip nested types as those should not be available on the global scope. */
11454 if (!tb
->nesting_type
)
11455 mono_image_add_to_name_cache (klass
->image
, klass
->name_space
, klass
->name
, tb
->table_idx
);
11458 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11459 by performing a mono_class_get which does the full resolution.
11461 Working around this semantics would require us to write a lot of code for no clear advantage.
11463 mono_image_append_class_to_reflection_info_set (klass
);
11465 g_assert (mono_class_get_ref_info (klass
) == tb
);
11468 register_dyn_token (tb
->module
->dynamic_image
, MONO_TOKEN_TYPE_DEF
| tb
->table_idx
, (MonoObject
*)tb
);
11470 if (parent
!= NULL
) {
11471 mono_class_setup_parent (klass
, parent
);
11472 } else if (strcmp (klass
->name
, "Object") == 0 && strcmp (klass
->name_space
, "System") == 0) {
11473 const char *old_n
= klass
->name
;
11474 /* trick to get relative numbering right when compiling corlib */
11475 klass
->name
= "BuildingObject";
11476 mono_class_setup_parent (klass
, mono_defaults
.object_class
);
11477 klass
->name
= old_n
;
11480 if ((!strcmp (klass
->name
, "ValueType") && !strcmp (klass
->name_space
, "System")) ||
11481 (!strcmp (klass
->name
, "Object") && !strcmp (klass
->name_space
, "System")) ||
11482 (!strcmp (klass
->name
, "Enum") && !strcmp (klass
->name_space
, "System"))) {
11483 klass
->instance_size
= sizeof (MonoObject
);
11484 klass
->size_inited
= 1;
11485 mono_class_setup_vtable_general (klass
, NULL
, 0, NULL
);
11488 mono_class_setup_mono_type (klass
);
11490 mono_class_setup_supertypes (klass
);
11493 * FIXME: handle interfaces.
11496 tb
->type
.type
= &klass
->byval_arg
;
11498 if (tb
->nesting_type
) {
11499 g_assert (tb
->nesting_type
->type
);
11500 MonoType
*nesting_type
= mono_reflection_type_get_handle (tb
->nesting_type
, error
);
11501 if (!is_ok (error
)) goto failure
;
11502 klass
->nested_in
= mono_class_from_mono_type (nesting_type
);
11505 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11507 mono_profiler_class_loaded (klass
, MONO_PROFILE_OK
);
11509 mono_loader_unlock ();
11513 mono_loader_unlock ();
11518 * mono_reflection_setup_internal_class:
11519 * @tb: a TypeBuilder object
11522 * Creates a MonoClass that represents the TypeBuilder.
11523 * This is a trick that lets us simplify a lot of reflection code
11524 * (and will allow us to support Build and Run assemblies easier).
11528 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
11531 (void) reflection_setup_internal_class (tb
, &error
);
11532 mono_error_set_pending_exception (&error
);
11536 * mono_reflection_setup_generic_class:
11537 * @tb: a TypeBuilder object
11539 * Setup the generic class before adding the first generic parameter.
11542 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
11547 * mono_reflection_create_generic_class:
11548 * @tb: a TypeBuilder object
11550 * Creates the generic class after all generic parameters have been added.
11553 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
11559 klass
= mono_class_from_mono_type (tb
->type
.type
);
11561 count
= tb
->generic_params
? mono_array_length (tb
->generic_params
) : 0;
11563 if (klass
->generic_container
|| (count
== 0))
11566 g_assert (tb
->generic_container
&& (tb
->generic_container
->owner
.klass
== klass
));
11568 klass
->generic_container
= (MonoGenericContainer
*)mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
11570 klass
->generic_container
->owner
.klass
= klass
;
11571 klass
->generic_container
->type_argc
= count
;
11572 klass
->generic_container
->type_params
= (MonoGenericParamFull
*)mono_image_alloc0 (klass
->image
, sizeof (MonoGenericParamFull
) * count
);
11574 klass
->is_generic
= 1;
11576 for (i
= 0; i
< count
; i
++) {
11577 MonoReflectionGenericParam
*gparam
= (MonoReflectionGenericParam
*)mono_array_get (tb
->generic_params
, gpointer
, i
);
11578 MonoType
*param_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)gparam
, &error
);
11579 mono_error_raise_exception (&error
); /* FIXME don't raise here */
11580 MonoGenericParamFull
*param
= (MonoGenericParamFull
*) param_type
->data
.generic_param
;
11581 klass
->generic_container
->type_params
[i
] = *param
;
11582 /*Make sure we are a diferent type instance */
11583 klass
->generic_container
->type_params
[i
].param
.owner
= klass
->generic_container
;
11584 klass
->generic_container
->type_params
[i
].info
.pklass
= NULL
;
11585 klass
->generic_container
->type_params
[i
].info
.flags
= gparam
->attrs
;
11587 g_assert (klass
->generic_container
->type_params
[i
].param
.owner
);
11590 klass
->generic_container
->context
.class_inst
= mono_get_shared_generic_inst (klass
->generic_container
);
11594 * reflection_create_internal_class:
11595 * @tb: a TypeBuilder object
11596 * @error: set on error
11598 * Actually create the MonoClass that is associated with the TypeBuilder.
11599 * On success returns TRUE, on failure returns FALSE and sets @error.
11603 reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
, MonoError
*error
)
11608 mono_error_init (error
);
11609 klass
= mono_class_from_mono_type (tb
->type
.type
);
11611 mono_loader_lock ();
11612 if (klass
->enumtype
&& mono_class_enum_basetype (klass
) == NULL
) {
11613 MonoReflectionFieldBuilder
*fb
;
11615 MonoType
*enum_basetype
;
11617 g_assert (tb
->fields
!= NULL
);
11618 g_assert (mono_array_length (tb
->fields
) >= 1);
11620 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, 0);
11622 MonoType
*field_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
, error
);
11623 if (!is_ok (error
)) {
11624 mono_loader_unlock ();
11627 if (!mono_type_is_valid_enum_basetype (field_type
)) {
11628 mono_loader_unlock ();
11632 enum_basetype
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
, error
);
11633 if (!is_ok (error
)) {
11634 mono_loader_unlock ();
11637 klass
->element_class
= mono_class_from_mono_type (enum_basetype
);
11638 if (!klass
->element_class
)
11639 klass
->element_class
= mono_class_from_mono_type (enum_basetype
);
11642 * get the element_class from the current corlib.
11644 ec
= default_class_from_mono_type (enum_basetype
);
11645 klass
->instance_size
= ec
->instance_size
;
11646 klass
->size_inited
= 1;
11648 * this is almost safe to do with enums and it's needed to be able
11649 * to create objects of the enum type (for use in SetConstant).
11651 /* FIXME: Does this mean enums can't have method overrides ? */
11652 mono_class_setup_vtable_general (klass
, NULL
, 0, NULL
);
11654 mono_loader_unlock ();
11659 * mono_reflection_create_internal_class:
11660 * @tb: a TypeBuilder object
11663 * Actually create the MonoClass that is associated with the TypeBuilder.
11666 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
11669 (void) reflection_create_internal_class (tb
, &error
);
11670 mono_error_set_pending_exception (&error
);
11673 static MonoMarshalSpec
*
11674 mono_marshal_spec_from_builder (MonoImage
*image
, MonoAssembly
*assembly
,
11675 MonoReflectionMarshal
*minfo
, MonoError
*error
)
11677 MonoMarshalSpec
*res
;
11679 mono_error_init (error
);
11681 res
= image_g_new0 (image
, MonoMarshalSpec
, 1);
11682 res
->native
= (MonoMarshalNative
)minfo
->type
;
11684 switch (minfo
->type
) {
11685 case MONO_NATIVE_LPARRAY
:
11686 res
->data
.array_data
.elem_type
= (MonoMarshalNative
)minfo
->eltype
;
11687 if (minfo
->has_size
) {
11688 res
->data
.array_data
.param_num
= minfo
->param_num
;
11689 res
->data
.array_data
.num_elem
= minfo
->count
;
11690 res
->data
.array_data
.elem_mult
= minfo
->param_num
== -1 ? 0 : 1;
11693 res
->data
.array_data
.param_num
= -1;
11694 res
->data
.array_data
.num_elem
= -1;
11695 res
->data
.array_data
.elem_mult
= -1;
11699 case MONO_NATIVE_BYVALTSTR
:
11700 case MONO_NATIVE_BYVALARRAY
:
11701 res
->data
.array_data
.num_elem
= minfo
->count
;
11704 case MONO_NATIVE_CUSTOM
:
11705 if (minfo
->marshaltyperef
) {
11706 MonoType
*marshaltyperef
= mono_reflection_type_get_handle ((MonoReflectionType
*)minfo
->marshaltyperef
, error
);
11707 if (!is_ok (error
)) {
11708 image_g_free (image
, res
);
11711 res
->data
.custom_data
.custom_name
=
11712 type_get_fully_qualified_name (marshaltyperef
);
11714 if (minfo
->mcookie
)
11715 res
->data
.custom_data
.cookie
= mono_string_to_utf8 (minfo
->mcookie
);
11724 #endif /* !DISABLE_REFLECTION_EMIT */
11726 MonoReflectionMarshalAsAttribute
*
11727 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain
*domain
, MonoClass
*klass
,
11728 MonoMarshalSpec
*spec
, MonoError
*error
)
11730 MonoReflectionType
*rt
;
11731 MonoReflectionMarshalAsAttribute
*minfo
;
11734 mono_error_init (error
);
11736 minfo
= (MonoReflectionMarshalAsAttribute
*)mono_object_new_checked (domain
, mono_class_get_marshal_as_attribute_class (), error
);
11739 minfo
->utype
= spec
->native
;
11741 switch (minfo
->utype
) {
11742 case MONO_NATIVE_LPARRAY
:
11743 minfo
->array_subtype
= spec
->data
.array_data
.elem_type
;
11744 minfo
->size_const
= spec
->data
.array_data
.num_elem
;
11745 if (spec
->data
.array_data
.param_num
!= -1)
11746 minfo
->size_param_index
= spec
->data
.array_data
.param_num
;
11749 case MONO_NATIVE_BYVALTSTR
:
11750 case MONO_NATIVE_BYVALARRAY
:
11751 minfo
->size_const
= spec
->data
.array_data
.num_elem
;
11754 case MONO_NATIVE_CUSTOM
:
11755 if (spec
->data
.custom_data
.custom_name
) {
11756 mtype
= mono_reflection_type_from_name_checked (spec
->data
.custom_data
.custom_name
, klass
->image
, error
);
11757 return_val_if_nok (error
, NULL
);
11760 rt
= mono_type_get_object_checked (domain
, mtype
, error
);
11764 MONO_OBJECT_SETREF (minfo
, marshal_type_ref
, rt
);
11767 MONO_OBJECT_SETREF (minfo
, marshal_type
, mono_string_new (domain
, spec
->data
.custom_data
.custom_name
));
11769 if (spec
->data
.custom_data
.cookie
)
11770 MONO_OBJECT_SETREF (minfo
, marshal_cookie
, mono_string_new (domain
, spec
->data
.custom_data
.cookie
));
11780 #ifndef DISABLE_REFLECTION_EMIT
11782 reflection_methodbuilder_to_mono_method (MonoClass
*klass
,
11783 ReflectionMethodBuilder
*rmb
,
11784 MonoMethodSignature
*sig
)
11788 MonoMethodWrapper
*wrapperm
;
11789 MonoMarshalSpec
**specs
;
11790 MonoReflectionMethodAux
*method_aux
;
11795 mono_error_init (&error
);
11797 * Methods created using a MethodBuilder should have their memory allocated
11798 * inside the image mempool, while dynamic methods should have their memory
11801 dynamic
= rmb
->refs
!= NULL
;
11802 image
= dynamic
? NULL
: klass
->image
;
11805 g_assert (!klass
->generic_class
);
11807 mono_loader_lock ();
11809 if ((rmb
->attrs
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
11810 (rmb
->iattrs
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
))
11811 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodPInvoke
, 1);
11813 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodWrapper
, 1);
11815 wrapperm
= (MonoMethodWrapper
*)m
;
11817 m
->dynamic
= dynamic
;
11819 m
->flags
= rmb
->attrs
;
11820 m
->iflags
= rmb
->iattrs
;
11821 m
->name
= mono_string_to_utf8_image_ignore (image
, rmb
->name
);
11823 m
->signature
= sig
;
11824 m
->sre_method
= TRUE
;
11825 m
->skip_visibility
= rmb
->skip_visibility
;
11826 if (rmb
->table_idx
)
11827 m
->token
= MONO_TOKEN_METHOD_DEF
| (*rmb
->table_idx
);
11829 if (m
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) {
11830 if (klass
== mono_defaults
.string_class
&& !strcmp (m
->name
, ".ctor"))
11831 m
->string_ctor
= 1;
11833 m
->signature
->pinvoke
= 1;
11834 } else if (m
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) {
11835 m
->signature
->pinvoke
= 1;
11837 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
11839 method_aux
->dllentry
= rmb
->dllentry
? mono_string_to_utf8_image (image
, rmb
->dllentry
, &error
) : image_strdup (image
, m
->name
);
11840 g_assert (mono_error_ok (&error
));
11841 method_aux
->dll
= mono_string_to_utf8_image (image
, rmb
->dll
, &error
);
11842 g_assert (mono_error_ok (&error
));
11844 ((MonoMethodPInvoke
*)m
)->piflags
= (rmb
->native_cc
<< 8) | (rmb
->charset
? (rmb
->charset
- 1) * 2 : 0) | rmb
->extra_flags
;
11846 if (image_is_dynamic (klass
->image
))
11847 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
11849 mono_loader_unlock ();
11852 } else if (!(m
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) &&
11853 !(m
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
)) {
11854 MonoMethodHeader
*header
;
11856 gint32 max_stack
, i
;
11857 gint32 num_locals
= 0;
11858 gint32 num_clauses
= 0;
11862 code
= mono_array_addr (rmb
->ilgen
->code
, guint8
, 0);
11863 code_size
= rmb
->ilgen
->code_len
;
11864 max_stack
= rmb
->ilgen
->max_stack
;
11865 num_locals
= rmb
->ilgen
->locals
? mono_array_length (rmb
->ilgen
->locals
) : 0;
11866 if (rmb
->ilgen
->ex_handlers
)
11867 num_clauses
= method_count_clauses (rmb
->ilgen
);
11870 code
= mono_array_addr (rmb
->code
, guint8
, 0);
11871 code_size
= mono_array_length (rmb
->code
);
11872 /* we probably need to run a verifier on the code... */
11882 header
= (MonoMethodHeader
*)image_g_malloc0 (image
, MONO_SIZEOF_METHOD_HEADER
+ num_locals
* sizeof (MonoType
*));
11883 header
->code_size
= code_size
;
11884 header
->code
= (const unsigned char *)image_g_malloc (image
, code_size
);
11885 memcpy ((char*)header
->code
, code
, code_size
);
11886 header
->max_stack
= max_stack
;
11887 header
->init_locals
= rmb
->init_locals
;
11888 header
->num_locals
= num_locals
;
11890 for (i
= 0; i
< num_locals
; ++i
) {
11891 MonoReflectionLocalBuilder
*lb
=
11892 mono_array_get (rmb
->ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
11894 header
->locals
[i
] = image_g_new0 (image
, MonoType
, 1);
11895 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)lb
->type
, &error
);
11896 mono_error_assert_ok (&error
);
11897 memcpy (header
->locals
[i
], type
, MONO_SIZEOF_TYPE
);
11900 header
->num_clauses
= num_clauses
;
11902 header
->clauses
= method_encode_clauses (image
, (MonoDynamicImage
*)klass
->image
,
11903 rmb
->ilgen
, num_clauses
, &error
);
11904 mono_error_assert_ok (&error
);
11907 wrapperm
->header
= header
;
11910 if (rmb
->generic_params
) {
11911 int count
= mono_array_length (rmb
->generic_params
);
11912 MonoGenericContainer
*container
= rmb
->generic_container
;
11914 g_assert (container
);
11916 container
->type_argc
= count
;
11917 container
->type_params
= image_g_new0 (image
, MonoGenericParamFull
, count
);
11918 container
->owner
.method
= m
;
11919 container
->is_anonymous
= FALSE
; // Method is now known, container is no longer anonymous
11921 m
->is_generic
= TRUE
;
11922 mono_method_set_generic_container (m
, container
);
11924 for (i
= 0; i
< count
; i
++) {
11925 MonoReflectionGenericParam
*gp
=
11926 mono_array_get (rmb
->generic_params
, MonoReflectionGenericParam
*, i
);
11927 MonoType
*gp_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)gp
, &error
);
11928 mono_error_assert_ok (&error
);
11929 MonoGenericParamFull
*param
= (MonoGenericParamFull
*) gp_type
->data
.generic_param
;
11930 container
->type_params
[i
] = *param
;
11934 * The method signature might have pointers to generic parameters that belong to other methods.
11935 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11936 * generic parameters.
11938 for (i
= 0; i
< m
->signature
->param_count
; ++i
) {
11939 MonoType
*t
= m
->signature
->params
[i
];
11940 if (t
->type
== MONO_TYPE_MVAR
) {
11941 MonoGenericParam
*gparam
= t
->data
.generic_param
;
11942 if (gparam
->num
< count
) {
11943 m
->signature
->params
[i
] = mono_metadata_type_dup (image
, m
->signature
->params
[i
]);
11944 m
->signature
->params
[i
]->data
.generic_param
= mono_generic_container_get_param (container
, gparam
->num
);
11950 if (klass
->generic_container
) {
11951 container
->parent
= klass
->generic_container
;
11952 container
->context
.class_inst
= klass
->generic_container
->context
.class_inst
;
11954 container
->context
.method_inst
= mono_get_shared_generic_inst (container
);
11958 MonoMethodWrapper
*mw
= (MonoMethodWrapper
*)m
;
11962 m
->wrapper_type
= MONO_WRAPPER_DYNAMIC_METHOD
;
11964 mw
->method_data
= data
= image_g_new (image
, gpointer
, rmb
->nrefs
+ 1);
11965 data
[0] = GUINT_TO_POINTER (rmb
->nrefs
);
11966 for (i
= 0; i
< rmb
->nrefs
; ++i
)
11967 data
[i
+ 1] = rmb
->refs
[i
];
11972 /* Parameter info */
11975 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
11976 method_aux
->param_names
= image_g_new0 (image
, char *, mono_method_signature (m
)->param_count
+ 1);
11977 for (i
= 0; i
<= m
->signature
->param_count
; ++i
) {
11978 MonoReflectionParamBuilder
*pb
;
11979 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
11980 if ((i
> 0) && (pb
->attrs
)) {
11981 /* Make a copy since it might point to a shared type structure */
11982 m
->signature
->params
[i
- 1] = mono_metadata_type_dup (klass
->image
, m
->signature
->params
[i
- 1]);
11983 m
->signature
->params
[i
- 1]->attrs
= pb
->attrs
;
11986 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
11987 MonoDynamicImage
*assembly
;
11989 MonoTypeEnum def_type
;
11993 if (!method_aux
->param_defaults
) {
11994 method_aux
->param_defaults
= image_g_new0 (image
, guint8
*, m
->signature
->param_count
+ 1);
11995 method_aux
->param_default_types
= image_g_new0 (image
, guint32
, m
->signature
->param_count
+ 1);
11997 assembly
= (MonoDynamicImage
*)klass
->image
;
11998 idx
= encode_constant (assembly
, pb
->def_value
, &def_type
);
11999 /* Copy the data from the blob since it might get realloc-ed */
12000 p
= assembly
->blob
.data
+ idx
;
12001 len
= mono_metadata_decode_blob_size (p
, &p2
);
12003 method_aux
->param_defaults
[i
] = (uint8_t *)image_g_malloc (image
, len
);
12004 method_aux
->param_default_types
[i
] = def_type
;
12005 memcpy ((gpointer
)method_aux
->param_defaults
[i
], p
, len
);
12009 method_aux
->param_names
[i
] = mono_string_to_utf8_image (image
, pb
->name
, &error
);
12010 g_assert (mono_error_ok (&error
));
12013 if (!method_aux
->param_cattr
)
12014 method_aux
->param_cattr
= image_g_new0 (image
, MonoCustomAttrInfo
*, m
->signature
->param_count
+ 1);
12015 method_aux
->param_cattr
[i
] = mono_custom_attrs_from_builders (image
, klass
->image
, pb
->cattrs
);
12021 /* Parameter marshalling */
12024 for (i
= 0; i
< mono_array_length (rmb
->pinfo
); ++i
) {
12025 MonoReflectionParamBuilder
*pb
;
12026 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
12027 if (pb
->marshal_info
) {
12029 specs
= image_g_new0 (image
, MonoMarshalSpec
*, sig
->param_count
+ 1);
12030 specs
[pb
->position
] =
12031 mono_marshal_spec_from_builder (image
, klass
->image
->assembly
, pb
->marshal_info
, &error
);
12032 if (!is_ok (&error
)) {
12033 mono_loader_unlock ();
12034 image_g_free (image
, specs
);
12035 mono_error_raise_exception (&error
); /* FIXME don't raise here */
12040 if (specs
!= NULL
) {
12042 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
12043 method_aux
->param_marshall
= specs
;
12046 if (image_is_dynamic (klass
->image
) && method_aux
)
12047 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
12049 mono_loader_unlock ();
12055 ctorbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionCtorBuilder
* mb
, MonoError
*error
)
12057 ReflectionMethodBuilder rmb
;
12058 MonoMethodSignature
*sig
;
12060 mono_loader_lock ();
12061 g_assert (klass
->image
!= NULL
);
12062 sig
= ctor_builder_to_signature (klass
->image
, mb
, error
);
12063 mono_loader_unlock ();
12064 return_val_if_nok (error
, NULL
);
12066 if (!reflection_methodbuilder_from_ctor_builder (&rmb
, mb
, error
))
12069 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
12070 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
12072 /* If we are in a generic class, we might be called multiple times from inflate_method */
12073 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
12074 /* ilgen is no longer needed */
12078 return mb
->mhandle
;
12082 methodbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionMethodBuilder
* mb
, MonoError
*error
)
12084 ReflectionMethodBuilder rmb
;
12085 MonoMethodSignature
*sig
;
12087 mono_error_init (error
);
12089 mono_loader_lock ();
12090 g_assert (klass
->image
!= NULL
);
12091 sig
= method_builder_to_signature (klass
->image
, mb
, error
);
12092 mono_loader_unlock ();
12093 return_val_if_nok (error
, NULL
);
12095 if (!reflection_methodbuilder_from_method_builder (&rmb
, mb
, error
))
12098 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
12099 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
12101 /* If we are in a generic class, we might be called multiple times from inflate_method */
12102 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
12103 /* ilgen is no longer needed */
12106 return mb
->mhandle
;
12109 static MonoClassField
*
12110 fieldbuilder_to_mono_class_field (MonoClass
*klass
, MonoReflectionFieldBuilder
* fb
, MonoError
*error
)
12112 MonoClassField
*field
;
12115 mono_error_init (error
);
12117 field
= g_new0 (MonoClassField
, 1);
12119 field
->name
= mono_string_to_utf8_image (klass
->image
, fb
->name
, error
);
12120 mono_error_assert_ok (error
);
12121 if (fb
->attrs
|| fb
->modreq
|| fb
->modopt
) {
12122 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
, error
);
12123 if (!is_ok (error
)) {
12127 field
->type
= mono_metadata_type_dup (NULL
, type
);
12128 field
->type
->attrs
= fb
->attrs
;
12130 g_assert (image_is_dynamic (klass
->image
));
12131 custom
= add_custom_modifiers ((MonoDynamicImage
*)klass
->image
, field
->type
, fb
->modreq
, fb
->modopt
, error
);
12132 g_free (field
->type
);
12133 if (!is_ok (error
)) {
12137 field
->type
= mono_metadata_type_dup (klass
->image
, custom
);
12140 field
->type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
, error
);
12141 if (!is_ok (error
)) {
12146 if (fb
->offset
!= -1)
12147 field
->offset
= fb
->offset
;
12148 field
->parent
= klass
;
12149 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
12151 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12158 * mono_reflection_bind_generic_parameters:
12159 * @type: a managed type object (which should be some kind of generic (instance? definition?))
12160 * @type_args: the number of type arguments to bind
12161 * @types: array of type arguments
12162 * @error: set on error
12164 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12165 * Returns the MonoType* for the resulting type instantiation. On failure returns NULL and sets @error.
12168 mono_reflection_bind_generic_parameters (MonoReflectionType
*type
, int type_argc
, MonoType
**types
, MonoError
*error
)
12171 MonoReflectionTypeBuilder
*tb
= NULL
;
12172 gboolean is_dynamic
= FALSE
;
12173 MonoClass
*geninst
;
12175 mono_error_init (error
);
12177 mono_loader_lock ();
12179 if (is_sre_type_builder (mono_object_class (type
))) {
12180 tb
= (MonoReflectionTypeBuilder
*) type
;
12183 } else if (is_sre_generic_instance (mono_object_class (type
))) {
12184 MonoReflectionGenericClass
*rgi
= (MonoReflectionGenericClass
*) type
;
12185 MonoReflectionType
*gtd
= rgi
->generic_type
;
12187 if (is_sre_type_builder (mono_object_class (gtd
))) {
12188 tb
= (MonoReflectionTypeBuilder
*)gtd
;
12193 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12194 if (tb
&& tb
->generic_container
)
12195 mono_reflection_create_generic_class (tb
);
12197 MonoType
*t
= mono_reflection_type_get_handle (type
, error
);
12198 if (!is_ok (error
)) {
12199 mono_loader_unlock ();
12203 klass
= mono_class_from_mono_type (t
);
12204 if (!klass
->generic_container
) {
12205 mono_loader_unlock ();
12206 mono_error_set_type_load_class (error
, klass
, "Cannot bind generic parameters of a non-generic type");
12210 if (klass
->wastypebuilder
) {
12211 tb
= (MonoReflectionTypeBuilder
*) mono_class_get_ref_info (klass
);
12216 mono_loader_unlock ();
12218 geninst
= mono_class_bind_generic_parameters (klass
, type_argc
, types
, is_dynamic
);
12220 return &geninst
->byval_arg
;
12224 mono_class_bind_generic_parameters (MonoClass
*klass
, int type_argc
, MonoType
**types
, gboolean is_dynamic
)
12226 MonoGenericClass
*gclass
;
12227 MonoGenericInst
*inst
;
12229 g_assert (klass
->generic_container
);
12231 inst
= mono_metadata_get_generic_inst (type_argc
, types
);
12232 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, is_dynamic
);
12234 return mono_generic_class_get_class (gclass
);
12237 MonoReflectionMethod
*
12238 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod
*rmethod
, MonoArray
*types
)
12242 MonoMethod
*method
, *inflated
;
12243 MonoMethodInflated
*imethod
;
12244 MonoGenericContext tmp_context
;
12245 MonoGenericInst
*ginst
;
12246 MonoType
**type_argv
;
12249 /*FIXME but this no longer should happen*/
12250 if (!strcmp (rmethod
->object
.vtable
->klass
->name
, "MethodBuilder")) {
12251 #ifndef DISABLE_REFLECTION_EMIT
12252 MonoReflectionMethodBuilder
*mb
= NULL
;
12256 mb
= (MonoReflectionMethodBuilder
*) rmethod
;
12257 tb
= mono_reflection_type_get_handle ((MonoReflectionType
*)mb
->type
, &error
);
12258 mono_error_raise_exception (&error
); /* FIXME don't raise here */
12259 klass
= mono_class_from_mono_type (tb
);
12261 method
= methodbuilder_to_mono_method (klass
, mb
, &error
);
12263 mono_error_raise_exception (&error
); /* FIXME don't raise here */
12265 g_assert_not_reached ();
12269 method
= rmethod
->method
;
12272 klass
= method
->klass
;
12274 if (method
->is_inflated
)
12275 method
= ((MonoMethodInflated
*) method
)->declaring
;
12277 count
= mono_method_signature (method
)->generic_param_count
;
12278 if (count
!= mono_array_length (types
))
12281 type_argv
= g_new0 (MonoType
*, count
);
12282 for (i
= 0; i
< count
; i
++) {
12283 MonoReflectionType
*garg
= (MonoReflectionType
*)mono_array_get (types
, gpointer
, i
);
12284 type_argv
[i
] = mono_reflection_type_get_handle (garg
, &error
);
12285 if (!is_ok (&error
)) {
12286 g_free (type_argv
);
12287 mono_error_raise_exception (&error
); /* FIXME don't raise here */
12290 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
12291 g_free (type_argv
);
12293 tmp_context
.class_inst
= klass
->generic_class
? klass
->generic_class
->context
.class_inst
: NULL
;
12294 tmp_context
.method_inst
= ginst
;
12296 inflated
= mono_class_inflate_generic_method_checked (method
, &tmp_context
, &error
);
12297 g_assert (mono_error_ok (&error
)); /* FIXME don't swallow the error */
12298 imethod
= (MonoMethodInflated
*) inflated
;
12300 /*FIXME but I think this is no longer necessary*/
12301 if (image_is_dynamic (method
->klass
->image
)) {
12302 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
12304 * This table maps metadata structures representing inflated methods/fields
12305 * to the reflection objects representing their generic definitions.
12307 mono_image_lock ((MonoImage
*)image
);
12308 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, rmethod
);
12309 mono_image_unlock ((MonoImage
*)image
);
12312 if (!mono_verifier_is_method_valid_generic_instantiation (inflated
))
12313 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12315 MonoReflectionMethod
*ret
= mono_method_get_object_checked (mono_object_domain (rmethod
), inflated
, NULL
, &error
);
12316 mono_error_raise_exception (&error
); /* FIXME don't raise here */
12320 #ifndef DISABLE_REFLECTION_EMIT
12322 static MonoMethod
*
12323 inflate_mono_method (MonoClass
*klass
, MonoMethod
*method
, MonoObject
*obj
)
12325 MonoMethodInflated
*imethod
;
12326 MonoGenericContext
*context
;
12330 * With generic code sharing the klass might not be inflated.
12331 * This can happen because classes inflated with their own
12332 * type arguments are "normalized" to the uninflated class.
12334 if (!klass
->generic_class
)
12337 context
= mono_class_get_context (klass
);
12339 if (klass
->method
.count
&& klass
->methods
) {
12340 /* Find the already created inflated method */
12341 for (i
= 0; i
< klass
->method
.count
; ++i
) {
12342 g_assert (klass
->methods
[i
]->is_inflated
);
12343 if (((MonoMethodInflated
*)klass
->methods
[i
])->declaring
== method
)
12346 g_assert (i
< klass
->method
.count
);
12347 imethod
= (MonoMethodInflated
*)klass
->methods
[i
];
12350 imethod
= (MonoMethodInflated
*) mono_class_inflate_generic_method_full_checked (method
, klass
, context
, &error
);
12351 mono_error_assert_ok (&error
);
12354 if (method
->is_generic
&& image_is_dynamic (method
->klass
->image
)) {
12355 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
12357 mono_image_lock ((MonoImage
*)image
);
12358 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, obj
);
12359 mono_image_unlock ((MonoImage
*)image
);
12361 return (MonoMethod
*) imethod
;
12364 static MonoMethod
*
12365 inflate_method (MonoReflectionType
*type
, MonoObject
*obj
, MonoError
*error
)
12367 MonoMethod
*method
;
12370 mono_error_init (error
);
12372 MonoClass
*type_class
= mono_object_class (type
);
12374 if (is_sre_generic_instance (type_class
)) {
12375 MonoReflectionGenericClass
*mgc
= (MonoReflectionGenericClass
*)type
;
12376 MonoType
*generic_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)mgc
->generic_type
, error
);
12377 return_val_if_nok (error
, NULL
);
12378 gklass
= mono_class_from_mono_type (generic_type
);
12379 } else if (is_sre_type_builder (type_class
)) {
12380 MonoType
*t
= mono_reflection_type_get_handle (type
, error
);
12381 return_val_if_nok (error
, NULL
);
12382 gklass
= mono_class_from_mono_type (t
);
12383 } else if (type
->type
) {
12384 gklass
= mono_class_from_mono_type (type
->type
);
12385 gklass
= mono_class_get_generic_type_definition (gklass
);
12387 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type
)));
12390 if (!strcmp (obj
->vtable
->klass
->name
, "MethodBuilder"))
12391 if (((MonoReflectionMethodBuilder
*)obj
)->mhandle
)
12392 method
= ((MonoReflectionMethodBuilder
*)obj
)->mhandle
;
12394 method
= methodbuilder_to_mono_method (gklass
, (MonoReflectionMethodBuilder
*) obj
, error
);
12398 else if (!strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder")) {
12399 method
= ctorbuilder_to_mono_method (gklass
, (MonoReflectionCtorBuilder
*) obj
, error
);
12402 } else if (!strcmp (obj
->vtable
->klass
->name
, "MonoMethod") || !strcmp (obj
->vtable
->klass
->name
, "MonoCMethod"))
12403 method
= ((MonoReflectionMethod
*) obj
)->method
;
12405 method
= NULL
; /* prevent compiler warning */
12406 g_error ("can't handle type %s", obj
->vtable
->klass
->name
);
12409 MonoType
*t
= mono_reflection_type_get_handle (type
, error
);
12410 return_val_if_nok (error
, NULL
);
12411 return inflate_mono_method (mono_class_from_mono_type (t
), method
, obj
);
12414 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12416 reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*fields
, MonoError
*error
)
12418 MonoGenericClass
*gclass
;
12419 MonoDynamicGenericClass
*dgclass
;
12420 MonoClass
*klass
, *gklass
;
12424 mono_error_init (error
);
12426 gtype
= mono_reflection_type_get_handle ((MonoReflectionType
*)type
, error
);
12427 return_val_if_nok (error
, FALSE
);
12428 klass
= mono_class_from_mono_type (gtype
);
12429 g_assert (gtype
->type
== MONO_TYPE_GENERICINST
);
12430 gclass
= gtype
->data
.generic_class
;
12432 if (!gclass
->is_dynamic
)
12435 dgclass
= (MonoDynamicGenericClass
*) gclass
;
12437 if (dgclass
->initialized
)
12440 gklass
= gclass
->container_class
;
12441 mono_class_init (gklass
);
12443 dgclass
->count_fields
= fields
? mono_array_length (fields
) : 0;
12445 dgclass
->fields
= mono_image_set_new0 (gclass
->owner
, MonoClassField
, dgclass
->count_fields
);
12446 dgclass
->field_objects
= mono_image_set_new0 (gclass
->owner
, MonoObject
*, dgclass
->count_fields
);
12447 dgclass
->field_generic_types
= mono_image_set_new0 (gclass
->owner
, MonoType
*, dgclass
->count_fields
);
12449 for (i
= 0; i
< dgclass
->count_fields
; i
++) {
12450 MonoObject
*obj
= (MonoObject
*)mono_array_get (fields
, gpointer
, i
);
12451 MonoClassField
*field
, *inflated_field
= NULL
;
12453 if (!strcmp (obj
->vtable
->klass
->name
, "FieldBuilder")) {
12454 inflated_field
= field
= fieldbuilder_to_mono_class_field (klass
, (MonoReflectionFieldBuilder
*) obj
, error
);
12455 return_val_if_nok (error
, FALSE
);
12456 } else if (!strcmp (obj
->vtable
->klass
->name
, "MonoField"))
12457 field
= ((MonoReflectionField
*) obj
)->field
;
12459 field
= NULL
; /* prevent compiler warning */
12460 g_assert_not_reached ();
12463 dgclass
->fields
[i
] = *field
;
12464 dgclass
->fields
[i
].parent
= klass
;
12465 dgclass
->fields
[i
].type
= mono_class_inflate_generic_type_checked (
12466 field
->type
, mono_generic_class_get_context ((MonoGenericClass
*) dgclass
), error
);
12467 mono_error_assert_ok (error
); /* FIXME don't swallow the error */
12468 dgclass
->field_generic_types
[i
] = field
->type
;
12469 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass
->field_objects
[i
], MONO_ROOT_SOURCE_REFLECTION
, "dynamic generic class field object");
12470 dgclass
->field_objects
[i
] = obj
;
12472 if (inflated_field
) {
12473 g_free (inflated_field
);
12475 dgclass
->fields
[i
].name
= mono_image_set_strdup (gclass
->owner
, dgclass
->fields
[i
].name
);
12479 dgclass
->initialized
= TRUE
;
12484 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*fields
)
12487 (void) reflection_generic_class_initialize (type
, fields
, &error
);
12488 mono_error_set_pending_exception (&error
);
12492 mono_reflection_free_dynamic_generic_class (MonoGenericClass
*gclass
)
12494 MonoDynamicGenericClass
*dgclass
;
12497 g_assert (gclass
->is_dynamic
);
12499 dgclass
= (MonoDynamicGenericClass
*)gclass
;
12501 for (i
= 0; i
< dgclass
->count_fields
; ++i
) {
12502 MonoClassField
*field
= dgclass
->fields
+ i
;
12503 mono_metadata_free_type (field
->type
);
12504 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass
->field_objects
[i
]);
12509 * fix_partial_generic_class:
12510 * @klass: a generic instantiation MonoClass
12511 * @error: set on error
12513 * Assumes that the generic container of @klass has its vtable
12514 * initialized, and updates the parent class, insterfaces, methods and
12515 * fields of @klass by inflating the types using the generic context.
12517 * On success returns TRUE, on failure returns FALSE and sets @error.
12521 fix_partial_generic_class (MonoClass
*klass
, MonoError
*error
)
12523 MonoClass
*gklass
= klass
->generic_class
->container_class
;
12524 MonoDynamicGenericClass
*dgclass
;
12527 mono_error_init (error
);
12529 if (klass
->wastypebuilder
)
12532 dgclass
= (MonoDynamicGenericClass
*) klass
->generic_class
;
12533 if (klass
->parent
!= gklass
->parent
) {
12534 MonoType
*parent_type
= mono_class_inflate_generic_type_checked (&gklass
->parent
->byval_arg
, &klass
->generic_class
->context
, error
);
12535 if (mono_error_ok (error
)) {
12536 MonoClass
*parent
= mono_class_from_mono_type (parent_type
);
12537 mono_metadata_free_type (parent_type
);
12538 if (parent
!= klass
->parent
) {
12539 /*fool mono_class_setup_parent*/
12540 klass
->supertypes
= NULL
;
12541 mono_class_setup_parent (klass
, parent
);
12544 if (gklass
->wastypebuilder
)
12545 klass
->wastypebuilder
= TRUE
;
12550 if (!dgclass
->initialized
)
12553 if (klass
->method
.count
!= gklass
->method
.count
) {
12554 klass
->method
.count
= gklass
->method
.count
;
12555 klass
->methods
= (MonoMethod
**)mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * (klass
->method
.count
+ 1));
12557 for (i
= 0; i
< klass
->method
.count
; i
++) {
12558 klass
->methods
[i
] = mono_class_inflate_generic_method_full_checked (
12559 gklass
->methods
[i
], klass
, mono_class_get_context (klass
), error
);
12560 mono_error_assert_ok (error
);
12564 if (klass
->interface_count
&& klass
->interface_count
!= gklass
->interface_count
) {
12565 klass
->interface_count
= gklass
->interface_count
;
12566 klass
->interfaces
= (MonoClass
**)mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * gklass
->interface_count
);
12567 klass
->interfaces_packed
= NULL
; /*make setup_interface_offsets happy*/
12569 for (i
= 0; i
< gklass
->interface_count
; ++i
) {
12570 MonoType
*iface_type
= mono_class_inflate_generic_type_checked (&gklass
->interfaces
[i
]->byval_arg
, mono_class_get_context (klass
), error
);
12571 return_val_if_nok (error
, FALSE
);
12573 klass
->interfaces
[i
] = mono_class_from_mono_type (iface_type
);
12574 mono_metadata_free_type (iface_type
);
12576 if (!ensure_runtime_vtable (klass
->interfaces
[i
], error
))
12579 klass
->interfaces_inited
= 1;
12582 if (klass
->field
.count
!= gklass
->field
.count
) {
12583 klass
->field
.count
= gklass
->field
.count
;
12584 klass
->fields
= image_g_new0 (klass
->image
, MonoClassField
, klass
->field
.count
);
12586 for (i
= 0; i
< klass
->field
.count
; i
++) {
12587 klass
->fields
[i
] = gklass
->fields
[i
];
12588 klass
->fields
[i
].parent
= klass
;
12589 klass
->fields
[i
].type
= mono_class_inflate_generic_type_checked (gklass
->fields
[i
].type
, mono_class_get_context (klass
), error
);
12590 return_val_if_nok (error
, FALSE
);
12594 /*We can only finish with this klass once it's parent has as well*/
12595 if (gklass
->wastypebuilder
)
12596 klass
->wastypebuilder
= TRUE
;
12601 * ensure_generic_class_runtime_vtable:
12602 * @klass a generic class
12603 * @error set on error
12605 * Ensures that the generic container of @klass has a vtable and
12606 * returns TRUE on success. On error returns FALSE and sets @error.
12609 ensure_generic_class_runtime_vtable (MonoClass
*klass
, MonoError
*error
)
12611 MonoClass
*gklass
= klass
->generic_class
->container_class
;
12613 mono_error_init (error
);
12615 if (!ensure_runtime_vtable (gklass
, error
))
12618 return fix_partial_generic_class (klass
, error
);
12622 * ensure_runtime_vtable:
12624 * @error set on error
12626 * Ensures that @klass has a vtable and returns TRUE on success. On
12627 * error returns FALSE and sets @error.
12630 ensure_runtime_vtable (MonoClass
*klass
, MonoError
*error
)
12632 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mono_class_get_ref_info (klass
);
12635 mono_error_init (error
);
12637 if (!image_is_dynamic (klass
->image
) || (!tb
&& !klass
->generic_class
) || klass
->wastypebuilder
)
12640 if (!ensure_runtime_vtable (klass
->parent
, error
))
12644 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
12645 num
+= tb
->num_methods
;
12646 klass
->method
.count
= num
;
12647 klass
->methods
= (MonoMethod
**)mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * num
);
12648 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
12649 for (i
= 0; i
< num
; ++i
) {
12650 MonoMethod
*ctor
= ctorbuilder_to_mono_method (klass
, mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
), error
);
12653 klass
->methods
[i
] = ctor
;
12655 num
= tb
->num_methods
;
12657 for (i
= 0; i
< num
; ++i
) {
12658 MonoMethod
*meth
= methodbuilder_to_mono_method (klass
, mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
), error
);
12661 klass
->methods
[j
++] = meth
;
12664 if (tb
->interfaces
) {
12665 klass
->interface_count
= mono_array_length (tb
->interfaces
);
12666 klass
->interfaces
= (MonoClass
**)mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * klass
->interface_count
);
12667 for (i
= 0; i
< klass
->interface_count
; ++i
) {
12668 MonoType
*iface
= mono_type_array_get_and_resolve (tb
->interfaces
, i
, error
);
12669 return_val_if_nok (error
, FALSE
);
12670 klass
->interfaces
[i
] = mono_class_from_mono_type (iface
);
12671 if (!ensure_runtime_vtable (klass
->interfaces
[i
], error
))
12674 klass
->interfaces_inited
= 1;
12676 } else if (klass
->generic_class
){
12677 if (!ensure_generic_class_runtime_vtable (klass
, error
)) {
12678 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
12683 if (klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
12685 for (i
= 0; i
< klass
->method
.count
; ++i
) {
12686 MonoMethod
*im
= klass
->methods
[i
];
12687 if (!(im
->flags
& METHOD_ATTRIBUTE_STATIC
))
12688 im
->slot
= slot_num
++;
12691 klass
->interfaces_packed
= NULL
; /*make setup_interface_offsets happy*/
12692 mono_class_setup_interface_offsets (klass
);
12693 mono_class_setup_interface_id (klass
);
12697 * The generic vtable is needed even if image->run is not set since some
12698 * runtime code like ves_icall_Type_GetMethodsByName depends on
12699 * method->slot being defined.
12703 * tb->methods could not be freed since it is used for determining
12704 * overrides during dynamic vtable construction.
12711 mono_reflection_method_get_handle (MonoObject
*method
, MonoError
*error
)
12713 mono_error_init (error
);
12714 MonoClass
*klass
= mono_object_class (method
);
12715 if (is_sr_mono_method (klass
) || is_sr_mono_generic_method (klass
)) {
12716 MonoReflectionMethod
*sr_method
= (MonoReflectionMethod
*)method
;
12717 return sr_method
->method
;
12719 if (is_sre_method_builder (klass
)) {
12720 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)method
;
12721 return mb
->mhandle
;
12723 if (is_sre_method_on_tb_inst (klass
)) {
12724 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)method
;
12725 MonoMethod
*result
;
12726 /*FIXME move this to a proper method and unify with resolve_object*/
12727 if (m
->method_args
) {
12728 result
= mono_reflection_method_on_tb_inst_get_handle (m
, error
);
12730 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)m
->inst
, error
);
12731 return_val_if_nok (error
, NULL
);
12732 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
12733 MonoMethod
*mono_method
;
12735 if (is_sre_method_builder (mono_object_class (m
->mb
)))
12736 mono_method
= ((MonoReflectionMethodBuilder
*)m
->mb
)->mhandle
;
12737 else if (is_sr_mono_method (mono_object_class (m
->mb
)))
12738 mono_method
= ((MonoReflectionMethod
*)m
->mb
)->method
;
12740 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m
->mb
)));
12742 result
= inflate_mono_method (inflated_klass
, mono_method
, (MonoObject
*)m
->mb
);
12747 g_error ("Can't handle methods of type %s:%s", klass
->name_space
, klass
->name
);
12752 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
, MonoError
*error
)
12754 MonoReflectionTypeBuilder
*tb
;
12756 MonoReflectionMethod
*m
;
12758 mono_error_init (error
);
12760 *num_overrides
= 0;
12762 g_assert (image_is_dynamic (klass
->image
));
12764 if (!mono_class_get_ref_info (klass
))
12767 g_assert (strcmp (((MonoObject
*)mono_class_get_ref_info (klass
))->vtable
->klass
->name
, "TypeBuilder") == 0);
12769 tb
= (MonoReflectionTypeBuilder
*)mono_class_get_ref_info (klass
);
12773 for (i
= 0; i
< tb
->num_methods
; ++i
) {
12774 MonoReflectionMethodBuilder
*mb
=
12775 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
12776 if (mb
->override_methods
)
12777 onum
+= mono_array_length (mb
->override_methods
);
12782 *overrides
= g_new0 (MonoMethod
*, onum
* 2);
12785 for (i
= 0; i
< tb
->num_methods
; ++i
) {
12786 MonoReflectionMethodBuilder
*mb
=
12787 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
12788 if (mb
->override_methods
) {
12789 for (j
= 0; j
< mono_array_length (mb
->override_methods
); ++j
) {
12790 m
= mono_array_get (mb
->override_methods
, MonoReflectionMethod
*, j
);
12792 (*overrides
) [onum
* 2] = mono_reflection_method_get_handle ((MonoObject
*)m
, error
);
12793 return_if_nok (error
);
12794 (*overrides
) [onum
* 2 + 1] = mb
->mhandle
;
12796 g_assert (mb
->mhandle
);
12804 *num_overrides
= onum
;
12808 typebuilder_setup_fields (MonoClass
*klass
, MonoError
*error
)
12810 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mono_class_get_ref_info (klass
);
12811 MonoReflectionFieldBuilder
*fb
;
12812 MonoClassField
*field
;
12813 MonoImage
*image
= klass
->image
;
12814 const char *p
, *p2
;
12816 guint32 len
, idx
, real_size
= 0;
12818 klass
->field
.count
= tb
->num_fields
;
12819 klass
->field
.first
= 0;
12821 mono_error_init (error
);
12823 if (tb
->class_size
) {
12824 if ((tb
->packing_size
& 0xffffff00) != 0) {
12825 char *err_msg
= g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass
->name
, tb
->packing_size
);
12826 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, err_msg
);
12829 klass
->packing_size
= tb
->packing_size
;
12830 real_size
= klass
->instance_size
+ tb
->class_size
;
12833 if (!klass
->field
.count
) {
12834 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
12838 klass
->fields
= image_g_new0 (image
, MonoClassField
, klass
->field
.count
);
12839 mono_class_alloc_ext (klass
);
12840 klass
->ext
->field_def_values
= image_g_new0 (image
, MonoFieldDefaultValue
, klass
->field
.count
);
12842 This is, guess what, a hack.
12843 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12844 On the static path no field class is resolved, only types are built. This is the right thing to do
12846 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12848 klass
->size_inited
= 1;
12850 for (i
= 0; i
< klass
->field
.count
; ++i
) {
12851 MonoArray
*rva_data
;
12852 fb
= (MonoReflectionFieldBuilder
*)mono_array_get (tb
->fields
, gpointer
, i
);
12853 field
= &klass
->fields
[i
];
12854 field
->name
= mono_string_to_utf8_image (image
, fb
->name
, error
);
12855 if (!mono_error_ok (error
))
12858 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
, error
);
12859 return_if_nok (error
);
12860 field
->type
= mono_metadata_type_dup (klass
->image
, type
);
12861 field
->type
->attrs
= fb
->attrs
;
12863 field
->type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
, error
);
12864 return_if_nok (error
);
12867 if ((fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) && (rva_data
= fb
->rva_data
)) {
12868 char *base
= mono_array_addr (rva_data
, char, 0);
12869 size_t size
= mono_array_length (rva_data
);
12870 char *data
= (char *)mono_image_alloc (klass
->image
, size
);
12871 memcpy (data
, base
, size
);
12872 klass
->ext
->field_def_values
[i
].data
= data
;
12874 if (fb
->offset
!= -1)
12875 field
->offset
= fb
->offset
;
12876 field
->parent
= klass
;
12877 fb
->handle
= field
;
12878 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
12880 if (klass
->enumtype
&& !(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
12881 klass
->cast_class
= klass
->element_class
= mono_class_from_mono_type (field
->type
);
12883 if (fb
->def_value
) {
12884 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)klass
->image
;
12885 field
->type
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
12886 idx
= encode_constant (assembly
, fb
->def_value
, &klass
->ext
->field_def_values
[i
].def_type
);
12887 /* Copy the data from the blob since it might get realloc-ed */
12888 p
= assembly
->blob
.data
+ idx
;
12889 len
= mono_metadata_decode_blob_size (p
, &p2
);
12891 klass
->ext
->field_def_values
[i
].data
= (const char *)mono_image_alloc (image
, len
);
12892 memcpy ((gpointer
)klass
->ext
->field_def_values
[i
].data
, p
, len
);
12896 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
12897 mono_class_layout_fields (klass
);
12901 typebuilder_setup_properties (MonoClass
*klass
, MonoError
*error
)
12903 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mono_class_get_ref_info (klass
);
12904 MonoReflectionPropertyBuilder
*pb
;
12905 MonoImage
*image
= klass
->image
;
12906 MonoProperty
*properties
;
12909 mono_error_init (error
);
12912 klass
->ext
= image_g_new0 (image
, MonoClassExt
, 1);
12914 klass
->ext
->property
.count
= tb
->properties
? mono_array_length (tb
->properties
) : 0;
12915 klass
->ext
->property
.first
= 0;
12917 properties
= image_g_new0 (image
, MonoProperty
, klass
->ext
->property
.count
);
12918 klass
->ext
->properties
= properties
;
12919 for (i
= 0; i
< klass
->ext
->property
.count
; ++i
) {
12920 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
12921 properties
[i
].parent
= klass
;
12922 properties
[i
].attrs
= pb
->attrs
;
12923 properties
[i
].name
= mono_string_to_utf8_image (image
, pb
->name
, error
);
12924 if (!mono_error_ok (error
))
12926 if (pb
->get_method
)
12927 properties
[i
].get
= pb
->get_method
->mhandle
;
12928 if (pb
->set_method
)
12929 properties
[i
].set
= pb
->set_method
->mhandle
;
12931 mono_save_custom_attrs (klass
->image
, &properties
[i
], pb
->cattrs
);
12932 if (pb
->def_value
) {
12934 const char *p
, *p2
;
12935 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)klass
->image
;
12936 if (!klass
->ext
->prop_def_values
)
12937 klass
->ext
->prop_def_values
= image_g_new0 (image
, MonoFieldDefaultValue
, klass
->ext
->property
.count
);
12938 properties
[i
].attrs
|= PROPERTY_ATTRIBUTE_HAS_DEFAULT
;
12939 idx
= encode_constant (assembly
, pb
->def_value
, &klass
->ext
->prop_def_values
[i
].def_type
);
12940 /* Copy the data from the blob since it might get realloc-ed */
12941 p
= assembly
->blob
.data
+ idx
;
12942 len
= mono_metadata_decode_blob_size (p
, &p2
);
12944 klass
->ext
->prop_def_values
[i
].data
= (const char *)mono_image_alloc (image
, len
);
12945 memcpy ((gpointer
)klass
->ext
->prop_def_values
[i
].data
, p
, len
);
12950 static MonoReflectionEvent
*
12951 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
, MonoError
*error
)
12953 mono_error_init (error
);
12955 MonoEvent
*event
= g_new0 (MonoEvent
, 1);
12958 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
, error
);
12959 if (!is_ok (error
)) {
12963 klass
= mono_class_from_mono_type (type
);
12965 event
->parent
= klass
;
12966 event
->attrs
= eb
->attrs
;
12967 event
->name
= mono_string_to_utf8 (eb
->name
);
12968 if (eb
->add_method
)
12969 event
->add
= eb
->add_method
->mhandle
;
12970 if (eb
->remove_method
)
12971 event
->remove
= eb
->remove_method
->mhandle
;
12972 if (eb
->raise_method
)
12973 event
->raise
= eb
->raise_method
->mhandle
;
12975 #ifndef MONO_SMALL_CONFIG
12976 if (eb
->other_methods
) {
12978 event
->other
= g_new0 (MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
12979 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
12980 MonoReflectionMethodBuilder
*mb
=
12981 mono_array_get (eb
->other_methods
,
12982 MonoReflectionMethodBuilder
*, j
);
12983 event
->other
[j
] = mb
->mhandle
;
12988 MonoReflectionEvent
*ev_obj
= mono_event_get_object_checked (mono_object_domain (tb
), klass
, event
, error
);
12989 if (!is_ok (error
)) {
12990 #ifndef MONO_SMALL_CONFIG
12991 g_free (event
->other
);
12999 MonoReflectionEvent
*
13000 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
13003 MonoReflectionEvent
*result
= reflection_event_builder_get_event_info (tb
, eb
, &error
);
13004 mono_error_set_pending_exception (&error
);
13009 typebuilder_setup_events (MonoClass
*klass
, MonoError
*error
)
13011 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mono_class_get_ref_info (klass
);
13012 MonoReflectionEventBuilder
*eb
;
13013 MonoImage
*image
= klass
->image
;
13017 mono_error_init (error
);
13020 klass
->ext
= image_g_new0 (image
, MonoClassExt
, 1);
13022 klass
->ext
->event
.count
= tb
->events
? mono_array_length (tb
->events
) : 0;
13023 klass
->ext
->event
.first
= 0;
13025 events
= image_g_new0 (image
, MonoEvent
, klass
->ext
->event
.count
);
13026 klass
->ext
->events
= events
;
13027 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
13028 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
13029 events
[i
].parent
= klass
;
13030 events
[i
].attrs
= eb
->attrs
;
13031 events
[i
].name
= mono_string_to_utf8_image (image
, eb
->name
, error
);
13032 if (!mono_error_ok (error
))
13034 if (eb
->add_method
)
13035 events
[i
].add
= eb
->add_method
->mhandle
;
13036 if (eb
->remove_method
)
13037 events
[i
].remove
= eb
->remove_method
->mhandle
;
13038 if (eb
->raise_method
)
13039 events
[i
].raise
= eb
->raise_method
->mhandle
;
13041 #ifndef MONO_SMALL_CONFIG
13042 if (eb
->other_methods
) {
13044 events
[i
].other
= image_g_new0 (image
, MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
13045 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
13046 MonoReflectionMethodBuilder
*mb
=
13047 mono_array_get (eb
->other_methods
,
13048 MonoReflectionMethodBuilder
*, j
);
13049 events
[i
].other
[j
] = mb
->mhandle
;
13053 mono_save_custom_attrs (klass
->image
, &events
[i
], eb
->cattrs
);
13057 struct remove_instantiations_user_data
13064 remove_instantiations_of_and_ensure_contents (gpointer key
,
13066 gpointer user_data
)
13068 struct remove_instantiations_user_data
*data
= (struct remove_instantiations_user_data
*)user_data
;
13069 MonoType
*type
= (MonoType
*)key
;
13070 MonoClass
*klass
= data
->klass
;
13071 gboolean already_failed
= !is_ok (data
->error
);
13073 MonoError
*error
= already_failed
? &lerror
: data
->error
;
13075 if ((type
->type
== MONO_TYPE_GENERICINST
) && (type
->data
.generic_class
->container_class
== klass
)) {
13076 MonoClass
*inst_klass
= mono_class_from_mono_type (type
);
13077 //Ensure it's safe to use it.
13078 if (!fix_partial_generic_class (inst_klass
, error
)) {
13079 mono_class_set_failure (inst_klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
13080 // Marked the class with failure, but since some other instantiation already failed,
13081 // just report that one, and swallow the error from this one.
13082 if (already_failed
)
13083 mono_error_cleanup (error
);
13091 check_array_for_usertypes (MonoArray
*arr
, MonoError
*error
)
13093 mono_error_init (error
);
13099 for (i
= 0; i
< mono_array_length (arr
); ++i
) {
13100 RESOLVE_ARRAY_TYPE_ELEMENT (arr
, i
, error
);
13101 if (!mono_error_ok (error
))
13106 MonoReflectionType
*
13107 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
13111 MonoDomain
* domain
;
13112 MonoReflectionType
* res
;
13115 mono_error_init (&error
);
13117 domain
= mono_object_domain (tb
);
13118 klass
= mono_class_from_mono_type (tb
->type
.type
);
13121 * Check for user defined Type subclasses.
13123 RESOLVE_TYPE (tb
->parent
, &error
);
13124 if (!is_ok (&error
))
13125 goto failure_unlocked
;
13126 check_array_for_usertypes (tb
->interfaces
, &error
);
13127 if (!is_ok (&error
))
13128 goto failure_unlocked
;
13130 for (i
= 0; i
< mono_array_length (tb
->fields
); ++i
) {
13131 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)mono_array_get (tb
->fields
, gpointer
, i
);
13133 RESOLVE_TYPE (fb
->type
, &error
);
13134 if (!is_ok (&error
))
13135 goto failure_unlocked
;
13136 check_array_for_usertypes (fb
->modreq
, &error
);
13137 if (!is_ok (&error
))
13138 goto failure_unlocked
;
13139 check_array_for_usertypes (fb
->modopt
, &error
);
13140 if (!is_ok (&error
))
13141 goto failure_unlocked
;
13142 if (fb
->marshal_info
&& fb
->marshal_info
->marshaltyperef
) {
13143 RESOLVE_TYPE (fb
->marshal_info
->marshaltyperef
, &error
);
13144 if (!is_ok (&error
))
13145 goto failure_unlocked
;
13151 for (i
= 0; i
< mono_array_length (tb
->methods
); ++i
) {
13152 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)mono_array_get (tb
->methods
, gpointer
, i
);
13154 RESOLVE_TYPE (mb
->rtype
, &error
);
13155 if (!is_ok (&error
))
13156 goto failure_unlocked
;
13157 check_array_for_usertypes (mb
->return_modreq
, &error
);
13158 if (!is_ok (&error
))
13159 goto failure_unlocked
;
13160 check_array_for_usertypes (mb
->return_modopt
, &error
);
13161 if (!is_ok (&error
))
13162 goto failure_unlocked
;
13163 check_array_for_usertypes (mb
->parameters
, &error
);
13164 if (!is_ok (&error
))
13165 goto failure_unlocked
;
13166 if (mb
->param_modreq
)
13167 for (j
= 0; j
< mono_array_length (mb
->param_modreq
); ++j
) {
13168 check_array_for_usertypes (mono_array_get (mb
->param_modreq
, MonoArray
*, j
), &error
);
13169 if (!is_ok (&error
))
13170 goto failure_unlocked
;
13172 if (mb
->param_modopt
)
13173 for (j
= 0; j
< mono_array_length (mb
->param_modopt
); ++j
) {
13174 check_array_for_usertypes (mono_array_get (mb
->param_modopt
, MonoArray
*, j
), &error
);
13175 if (!is_ok (&error
))
13176 goto failure_unlocked
;
13182 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
13183 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)mono_array_get (tb
->ctors
, gpointer
, i
);
13185 check_array_for_usertypes (mb
->parameters
, &error
);
13186 if (!is_ok (&error
))
13187 goto failure_unlocked
;
13188 if (mb
->param_modreq
)
13189 for (j
= 0; j
< mono_array_length (mb
->param_modreq
); ++j
) {
13190 check_array_for_usertypes (mono_array_get (mb
->param_modreq
, MonoArray
*, j
), &error
);
13191 if (!is_ok (&error
))
13192 goto failure_unlocked
;
13194 if (mb
->param_modopt
)
13195 for (j
= 0; j
< mono_array_length (mb
->param_modopt
); ++j
) {
13196 check_array_for_usertypes (mono_array_get (mb
->param_modopt
, MonoArray
*, j
), &error
);
13197 if (!is_ok (&error
))
13198 goto failure_unlocked
;
13204 mono_save_custom_attrs (klass
->image
, klass
, tb
->cattrs
);
13207 * we need to lock the domain because the lock will be taken inside
13208 * So, we need to keep the locking order correct.
13210 mono_loader_lock ();
13211 mono_domain_lock (domain
);
13212 if (klass
->wastypebuilder
) {
13213 mono_domain_unlock (domain
);
13214 mono_loader_unlock ();
13216 res
= mono_type_get_object_checked (mono_object_domain (tb
), &klass
->byval_arg
, &error
);
13217 mono_error_set_pending_exception (&error
);
13222 * Fields to set in klass:
13223 * the various flags: delegate/unicode/contextbound etc.
13225 klass
->flags
= tb
->attrs
;
13226 klass
->has_cctor
= 1;
13227 klass
->has_finalize
= 1;
13228 klass
->has_finalize_inited
= 1;
13230 mono_class_setup_parent (klass
, klass
->parent
);
13231 /* fool mono_class_setup_supertypes */
13232 klass
->supertypes
= NULL
;
13233 mono_class_setup_supertypes (klass
);
13234 mono_class_setup_mono_type (klass
);
13237 if (!((MonoDynamicImage
*)klass
->image
)->run
) {
13238 if (klass
->generic_container
) {
13239 /* FIXME: The code below can't handle generic classes */
13240 klass
->wastypebuilder
= TRUE
;
13241 mono_loader_unlock ();
13242 mono_domain_unlock (domain
);
13244 res
= mono_type_get_object_checked (mono_object_domain (tb
), &klass
->byval_arg
, &error
);
13245 mono_error_set_pending_exception (&error
);
13252 /* enums are done right away */
13253 if (!klass
->enumtype
)
13254 if (!ensure_runtime_vtable (klass
, &error
))
13257 if (tb
->subtypes
) {
13258 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
13259 MonoReflectionTypeBuilder
*subtb
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
13260 mono_class_alloc_ext (klass
);
13261 MonoType
*subtype
= mono_reflection_type_get_handle ((MonoReflectionType
*)subtb
, &error
);
13262 if (!is_ok (&error
)) goto failure
;
13263 klass
->ext
->nested_classes
= g_list_prepend_image (klass
->image
, klass
->ext
->nested_classes
, mono_class_from_mono_type (subtype
));
13267 klass
->nested_classes_inited
= TRUE
;
13269 /* fields and object layout */
13270 if (klass
->parent
) {
13271 if (!klass
->parent
->size_inited
)
13272 mono_class_init (klass
->parent
);
13273 klass
->instance_size
= klass
->parent
->instance_size
;
13274 klass
->sizes
.class_size
= 0;
13275 klass
->min_align
= klass
->parent
->min_align
;
13276 /* if the type has no fields we won't call the field_setup
13277 * routine which sets up klass->has_references.
13279 klass
->has_references
|= klass
->parent
->has_references
;
13281 klass
->instance_size
= sizeof (MonoObject
);
13282 klass
->min_align
= 1;
13285 /* FIXME: handle packing_size and instance_size */
13286 typebuilder_setup_fields (klass
, &error
);
13287 if (!mono_error_ok (&error
))
13289 typebuilder_setup_properties (klass
, &error
);
13290 if (!mono_error_ok (&error
))
13293 typebuilder_setup_events (klass
, &error
);
13294 if (!mono_error_ok (&error
))
13297 klass
->wastypebuilder
= TRUE
;
13300 * If we are a generic TypeBuilder, there might be instantiations in the type cache
13301 * which have type System.Reflection.MonoGenericClass, but after the type is created,
13302 * we want to return normal System.MonoType objects, so clear these out from the cache.
13304 * Together with this we must ensure the contents of all instances to match the created type.
13306 if (domain
->type_hash
&& klass
->generic_container
) {
13307 struct remove_instantiations_user_data data
;
13308 data
.klass
= klass
;
13309 data
.error
= &error
;
13310 mono_error_assert_ok (&error
);
13311 mono_g_hash_table_foreach_remove (domain
->type_hash
, remove_instantiations_of_and_ensure_contents
, &data
);
13312 if (!is_ok (&error
))
13316 mono_domain_unlock (domain
);
13317 mono_loader_unlock ();
13319 if (klass
->enumtype
&& !mono_class_is_valid_enum (klass
)) {
13320 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
13321 mono_error_set_type_load_class (&error
, klass
, "Not a valid enumeration");
13322 goto failure_unlocked
;
13325 res
= mono_type_get_object_checked (mono_object_domain (tb
), &klass
->byval_arg
, &error
);
13326 if (!is_ok (&error
))
13327 goto failure_unlocked
;
13329 g_assert (res
!= (MonoReflectionType
*)tb
);
13334 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
13335 klass
->wastypebuilder
= TRUE
;
13336 mono_domain_unlock (domain
);
13337 mono_loader_unlock ();
13339 mono_error_set_pending_exception (&error
);
13344 reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
, MonoError
*error
)
13346 MonoGenericParamFull
*param
;
13350 mono_error_init (error
);
13352 image
= &gparam
->tbuilder
->module
->dynamic_image
->image
;
13354 param
= mono_image_new0 (image
, MonoGenericParamFull
, 1);
13356 param
->info
.name
= mono_string_to_utf8_image (image
, gparam
->name
, error
);
13357 mono_error_assert_ok (error
);
13358 param
->param
.num
= gparam
->index
;
13360 if (gparam
->mbuilder
) {
13361 if (!gparam
->mbuilder
->generic_container
) {
13362 MonoType
*tb
= mono_reflection_type_get_handle ((MonoReflectionType
*)gparam
->mbuilder
->type
, error
);
13363 return_val_if_nok (error
, FALSE
);
13365 MonoClass
*klass
= mono_class_from_mono_type (tb
);
13366 gparam
->mbuilder
->generic_container
= (MonoGenericContainer
*)mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
13367 gparam
->mbuilder
->generic_container
->is_method
= TRUE
;
13369 * Cannot set owner.method, since the MonoMethod is not created yet.
13370 * Set the image field instead, so type_in_image () works.
13372 gparam
->mbuilder
->generic_container
->is_anonymous
= TRUE
;
13373 gparam
->mbuilder
->generic_container
->owner
.image
= klass
->image
;
13375 param
->param
.owner
= gparam
->mbuilder
->generic_container
;
13376 } else if (gparam
->tbuilder
) {
13377 if (!gparam
->tbuilder
->generic_container
) {
13378 MonoType
*tb
= mono_reflection_type_get_handle ((MonoReflectionType
*)gparam
->tbuilder
, error
);
13379 return_val_if_nok (error
, FALSE
);
13380 MonoClass
*klass
= mono_class_from_mono_type (tb
);
13381 gparam
->tbuilder
->generic_container
= (MonoGenericContainer
*)mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
13382 gparam
->tbuilder
->generic_container
->owner
.klass
= klass
;
13384 param
->param
.owner
= gparam
->tbuilder
->generic_container
;
13387 pklass
= mono_class_from_generic_parameter_internal ((MonoGenericParam
*) param
);
13389 gparam
->type
.type
= &pklass
->byval_arg
;
13391 mono_class_set_ref_info (pklass
, gparam
);
13392 mono_image_append_class_to_reflection_info_set (pklass
);
13398 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
13401 (void) reflection_initialize_generic_parameter (gparam
, &error
);
13402 mono_error_set_pending_exception (&error
);
13407 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
13410 MonoReflectionModuleBuilder
*module
= sig
->module
;
13411 MonoDynamicImage
*assembly
= module
!= NULL
? module
->dynamic_image
: NULL
;
13412 guint32 na
= sig
->arguments
? mono_array_length (sig
->arguments
) : 0;
13417 check_array_for_usertypes (sig
->arguments
, &error
);
13418 mono_error_raise_exception (&error
); /* FIXME: don't raise here */
13420 sigbuffer_init (&buf
, 32);
13422 sigbuffer_add_value (&buf
, 0x07);
13423 sigbuffer_add_value (&buf
, na
);
13424 if (assembly
!= NULL
){
13425 for (i
= 0; i
< na
; ++i
) {
13426 MonoReflectionType
*type
= mono_array_get (sig
->arguments
, MonoReflectionType
*, i
);
13427 encode_reflection_type (assembly
, type
, &buf
, &error
);
13428 if (!is_ok (&error
)) goto fail
;
13432 buflen
= buf
.p
- buf
.buf
;
13433 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
13434 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
13435 sigbuffer_free (&buf
);
13438 sigbuffer_free (&buf
);
13439 mono_error_raise_exception (&error
); /* FIXME don't raise here */
13444 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
13447 MonoDynamicImage
*assembly
= sig
->module
->dynamic_image
;
13448 guint32 na
= sig
->arguments
? mono_array_length (sig
->arguments
) : 0;
13453 check_array_for_usertypes (sig
->arguments
, &error
);
13454 mono_error_raise_exception (&error
); /* FIXME: don't raise here */
13456 sigbuffer_init (&buf
, 32);
13458 sigbuffer_add_value (&buf
, 0x06);
13459 for (i
= 0; i
< na
; ++i
) {
13460 MonoReflectionType
*type
= mono_array_get (sig
->arguments
, MonoReflectionType
*, i
);
13461 encode_reflection_type (assembly
, type
, &buf
, &error
);
13462 if (!is_ok (&error
))
13466 buflen
= buf
.p
- buf
.buf
;
13467 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
13468 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
13469 sigbuffer_free (&buf
);
13473 sigbuffer_free (&buf
);
13474 mono_error_raise_exception (&error
); /* FIXME don't raise here */
13479 MonoMethod
*handle
;
13480 MonoDomain
*domain
;
13481 } DynamicMethodReleaseData
;
13484 * The runtime automatically clean up those after finalization.
13486 static MonoReferenceQueue
*dynamic_method_queue
;
13489 free_dynamic_method (void *dynamic_method
)
13491 DynamicMethodReleaseData
*data
= (DynamicMethodReleaseData
*)dynamic_method
;
13492 MonoDomain
*domain
= data
->domain
;
13493 MonoMethod
*method
= data
->handle
;
13496 mono_domain_lock (domain
);
13497 dis_link
= (guint32
)(size_t)g_hash_table_lookup (domain
->method_to_dyn_method
, method
);
13498 g_hash_table_remove (domain
->method_to_dyn_method
, method
);
13499 mono_domain_unlock (domain
);
13500 g_assert (dis_link
);
13501 mono_gchandle_free (dis_link
);
13503 mono_runtime_free_method (domain
, method
);
13508 reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
, MonoError
*error
)
13510 MonoReferenceQueue
*queue
;
13511 MonoMethod
*handle
;
13512 DynamicMethodReleaseData
*release_data
;
13513 ReflectionMethodBuilder rmb
;
13514 MonoMethodSignature
*sig
;
13516 MonoDomain
*domain
;
13520 mono_error_init (error
);
13522 if (mono_runtime_is_shutting_down ()) {
13523 mono_error_set_generic_error (error
, "System", "InvalidOperationException", "");
13527 if (!(queue
= dynamic_method_queue
)) {
13528 mono_loader_lock ();
13529 if (!(queue
= dynamic_method_queue
))
13530 queue
= dynamic_method_queue
= mono_gc_reference_queue_new (free_dynamic_method
);
13531 mono_loader_unlock ();
13534 sig
= dynamic_method_to_signature (mb
, error
);
13535 return_val_if_nok (error
, FALSE
);
13537 reflection_methodbuilder_from_dynamic_method (&rmb
, mb
);
13540 * Resolve references.
13543 * Every second entry in the refs array is reserved for storing handle_class,
13544 * which is needed by the ldtoken implementation in the JIT.
13546 rmb
.nrefs
= mb
->nrefs
;
13547 rmb
.refs
= g_new0 (gpointer
, mb
->nrefs
+ 1);
13548 for (i
= 0; i
< mb
->nrefs
; i
+= 2) {
13549 MonoClass
*handle_class
;
13551 MonoObject
*obj
= mono_array_get (mb
->refs
, MonoObject
*, i
);
13553 if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
13554 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
13556 * The referenced DynamicMethod should already be created by the managed
13557 * code, except in the case of circular references. In that case, we store
13558 * method in the refs array, and fix it up later when the referenced
13559 * DynamicMethod is created.
13561 if (method
->mhandle
) {
13562 ref
= method
->mhandle
;
13564 /* FIXME: GC object stored in unmanaged memory */
13567 /* FIXME: GC object stored in unmanaged memory */
13568 method
->referenced_by
= g_slist_append (method
->referenced_by
, mb
);
13570 handle_class
= mono_defaults
.methodhandle_class
;
13572 MonoException
*ex
= NULL
;
13573 ref
= resolve_object (mb
->module
->image
, obj
, &handle_class
, NULL
, error
);
13574 if (!is_ok (error
)) {
13579 ex
= mono_get_exception_type_load (NULL
, NULL
);
13580 else if (mono_security_core_clr_enabled ())
13581 ex
= mono_security_core_clr_ensure_dynamic_method_resolved_object (ref
, handle_class
);
13585 mono_error_set_exception_instance (error
, ex
);
13590 rmb
.refs
[i
] = ref
; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13591 rmb
.refs
[i
+ 1] = handle_class
;
13595 MonoType
*owner_type
= mono_reflection_type_get_handle ((MonoReflectionType
*)mb
->owner
, error
);
13596 if (!is_ok (error
)) {
13600 klass
= mono_class_from_mono_type (owner_type
);
13602 klass
= mono_defaults
.object_class
;
13605 mb
->mhandle
= handle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
13606 release_data
= g_new (DynamicMethodReleaseData
, 1);
13607 release_data
->handle
= handle
;
13608 release_data
->domain
= mono_object_get_domain ((MonoObject
*)mb
);
13609 if (!mono_gc_reference_queue_add (queue
, (MonoObject
*)mb
, release_data
))
13610 g_free (release_data
);
13612 /* Fix up refs entries pointing at us */
13613 for (l
= mb
->referenced_by
; l
; l
= l
->next
) {
13614 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)l
->data
;
13615 MonoMethodWrapper
*wrapper
= (MonoMethodWrapper
*)method
->mhandle
;
13618 g_assert (method
->mhandle
);
13620 data
= (gpointer
*)wrapper
->method_data
;
13621 for (i
= 0; i
< GPOINTER_TO_UINT (data
[0]); i
+= 2) {
13622 if ((data
[i
+ 1] == mb
) && (data
[i
+ 1 + 1] == mono_defaults
.methodhandle_class
))
13623 data
[i
+ 1] = mb
->mhandle
;
13626 g_slist_free (mb
->referenced_by
);
13630 /* ilgen is no longer needed */
13633 domain
= mono_domain_get ();
13634 mono_domain_lock (domain
);
13635 if (!domain
->method_to_dyn_method
)
13636 domain
->method_to_dyn_method
= g_hash_table_new (NULL
, NULL
);
13637 g_hash_table_insert (domain
->method_to_dyn_method
, handle
, (gpointer
)(size_t)mono_gchandle_new_weakref ((MonoObject
*)mb
, TRUE
));
13638 mono_domain_unlock (domain
);
13644 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
13647 (void) reflection_create_dynamic_method (mb
, &error
);
13648 mono_error_set_pending_exception (&error
);
13651 #endif /* DISABLE_REFLECTION_EMIT */
13655 * mono_reflection_is_valid_dynamic_token:
13657 * Returns TRUE if token is valid.
13661 mono_reflection_is_valid_dynamic_token (MonoDynamicImage
*image
, guint32 token
)
13663 return lookup_dyn_token (image
, token
) != NULL
;
13666 MonoMethodSignature
*
13667 mono_reflection_lookup_signature (MonoImage
*image
, MonoMethod
*method
, guint32 token
, MonoError
*error
)
13669 MonoMethodSignature
*sig
;
13670 g_assert (image_is_dynamic (image
));
13672 mono_error_init (error
);
13674 sig
= (MonoMethodSignature
*)g_hash_table_lookup (((MonoDynamicImage
*)image
)->vararg_aux_hash
, GUINT_TO_POINTER (token
));
13678 return mono_method_signature_checked (method
, error
);
13681 #ifndef DISABLE_REFLECTION_EMIT
13684 * mono_reflection_lookup_dynamic_token:
13686 * Finish the Builder object pointed to by TOKEN and return the corresponding
13687 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
13688 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13691 * LOCKING: Take the loader lock
13694 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
13697 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)image
;
13701 obj
= lookup_dyn_token (assembly
, token
);
13704 g_error ("Could not find required dynamic token 0x%08x", token
);
13710 handle_class
= &klass
;
13711 gpointer result
= resolve_object (image
, obj
, handle_class
, context
, &error
);
13712 mono_error_raise_exception (&error
); /* FIXME don't raise here */
13717 * ensure_complete_type:
13719 * Ensure that KLASS is completed if it is a dynamic type, or references
13723 ensure_complete_type (MonoClass
*klass
, MonoError
*error
)
13725 mono_error_init (error
);
13727 if (image_is_dynamic (klass
->image
) && !klass
->wastypebuilder
&& mono_class_get_ref_info (klass
)) {
13728 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mono_class_get_ref_info (klass
);
13730 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL
, (MonoObject
*)tb
, error
);
13731 return_if_nok (error
);
13733 // Asserting here could break a lot of code
13734 //g_assert (klass->wastypebuilder);
13737 if (klass
->generic_class
) {
13738 MonoGenericInst
*inst
= klass
->generic_class
->context
.class_inst
;
13741 for (i
= 0; i
< inst
->type_argc
; ++i
) {
13742 ensure_complete_type (mono_class_from_mono_type (inst
->type_argv
[i
]), error
);
13743 return_if_nok (error
);
13749 resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
, MonoError
*error
)
13751 gpointer result
= NULL
;
13753 mono_error_init (error
);
13755 if (strcmp (obj
->vtable
->klass
->name
, "String") == 0) {
13756 result
= mono_string_intern_checked ((MonoString
*)obj
, error
);
13757 return_val_if_nok (error
, NULL
);
13758 *handle_class
= mono_defaults
.string_class
;
13760 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoType") == 0) {
13761 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
13762 return_val_if_nok (error
, NULL
);
13763 MonoClass
*mc
= mono_class_from_mono_type (type
);
13764 if (!mono_class_init (mc
)) {
13765 mono_error_set_exception_instance (error
, mono_class_get_exception_for_failure (mc
));
13770 MonoType
*inflated
= mono_class_inflate_generic_type_checked (type
, context
, error
);
13771 return_val_if_nok (error
, NULL
);
13773 result
= mono_class_from_mono_type (inflated
);
13774 mono_metadata_free_type (inflated
);
13776 result
= mono_class_from_mono_type (type
);
13778 *handle_class
= mono_defaults
.typehandle_class
;
13780 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoMethod") == 0 ||
13781 strcmp (obj
->vtable
->klass
->name
, "MonoCMethod") == 0 ||
13782 strcmp (obj
->vtable
->klass
->name
, "MonoGenericCMethod") == 0 ||
13783 strcmp (obj
->vtable
->klass
->name
, "MonoGenericMethod") == 0) {
13784 result
= ((MonoReflectionMethod
*)obj
)->method
;
13786 result
= mono_class_inflate_generic_method_checked ((MonoMethod
*)result
, context
, error
);
13787 mono_error_assert_ok (error
);
13789 *handle_class
= mono_defaults
.methodhandle_class
;
13791 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodBuilder") == 0) {
13792 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
13793 result
= mb
->mhandle
;
13795 /* Type is not yet created */
13796 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
13798 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL
, (MonoObject
*)tb
, error
);
13799 return_val_if_nok (error
, NULL
);
13802 * Hopefully this has been filled in by calling CreateType() on the
13806 * TODO: This won't work if the application finishes another
13807 * TypeBuilder instance instead of this one.
13809 result
= mb
->mhandle
;
13812 result
= mono_class_inflate_generic_method_checked ((MonoMethod
*)result
, context
, error
);
13813 mono_error_assert_ok (error
);
13815 *handle_class
= mono_defaults
.methodhandle_class
;
13816 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder") == 0) {
13817 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
13819 result
= cb
->mhandle
;
13821 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)cb
->type
;
13823 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL
, (MonoObject
*)tb
, error
);
13824 return_val_if_nok (error
, NULL
);
13825 result
= cb
->mhandle
;
13828 result
= mono_class_inflate_generic_method_checked ((MonoMethod
*)result
, context
, error
);
13829 mono_error_assert_ok (error
);
13831 *handle_class
= mono_defaults
.methodhandle_class
;
13832 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoField") == 0) {
13833 MonoClassField
*field
= ((MonoReflectionField
*)obj
)->field
;
13835 ensure_complete_type (field
->parent
, error
);
13836 return_val_if_nok (error
, NULL
);
13839 MonoType
*inflated
= mono_class_inflate_generic_type_checked (&field
->parent
->byval_arg
, context
, error
);
13840 return_val_if_nok (error
, NULL
);
13842 MonoClass
*klass
= mono_class_from_mono_type (inflated
);
13843 MonoClassField
*inflated_field
;
13844 gpointer iter
= NULL
;
13845 mono_metadata_free_type (inflated
);
13846 while ((inflated_field
= mono_class_get_fields (klass
, &iter
))) {
13847 if (!strcmp (field
->name
, inflated_field
->name
))
13850 g_assert (inflated_field
&& !strcmp (field
->name
, inflated_field
->name
));
13851 result
= inflated_field
;
13855 *handle_class
= mono_defaults
.fieldhandle_class
;
13857 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldBuilder") == 0) {
13858 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
13859 result
= fb
->handle
;
13862 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
13864 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL
, (MonoObject
*)tb
, error
);
13865 return_val_if_nok (error
, NULL
);
13866 result
= fb
->handle
;
13869 if (fb
->handle
&& fb
->handle
->parent
->generic_container
) {
13870 MonoClass
*klass
= fb
->handle
->parent
;
13871 MonoType
*type
= mono_class_inflate_generic_type_checked (&klass
->byval_arg
, context
, error
);
13872 return_val_if_nok (error
, NULL
);
13874 MonoClass
*inflated
= mono_class_from_mono_type (type
);
13876 result
= mono_class_get_field_from_name (inflated
, mono_field_get_name (fb
->handle
));
13878 mono_metadata_free_type (type
);
13880 *handle_class
= mono_defaults
.fieldhandle_class
;
13881 } else if (strcmp (obj
->vtable
->klass
->name
, "TypeBuilder") == 0) {
13882 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
13883 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
, error
);
13884 return_val_if_nok (error
, NULL
);
13887 klass
= type
->data
.klass
;
13888 if (klass
->wastypebuilder
) {
13889 /* Already created */
13893 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL
, (MonoObject
*)tb
, error
);
13894 return_val_if_nok (error
, NULL
);
13895 result
= type
->data
.klass
;
13898 *handle_class
= mono_defaults
.typehandle_class
;
13899 } else if (strcmp (obj
->vtable
->klass
->name
, "SignatureHelper") == 0) {
13900 MonoReflectionSigHelper
*helper
= (MonoReflectionSigHelper
*)obj
;
13901 MonoMethodSignature
*sig
;
13904 if (helper
->arguments
)
13905 nargs
= mono_array_length (helper
->arguments
);
13909 sig
= mono_metadata_signature_alloc (image
, nargs
);
13910 sig
->explicit_this
= helper
->call_conv
& 64 ? 1 : 0;
13911 sig
->hasthis
= helper
->call_conv
& 32 ? 1 : 0;
13913 if (helper
->unmanaged_call_conv
) { /* unmanaged */
13914 sig
->call_convention
= helper
->unmanaged_call_conv
- 1;
13915 sig
->pinvoke
= TRUE
;
13916 } else if (helper
->call_conv
& 0x02) {
13917 sig
->call_convention
= MONO_CALL_VARARG
;
13919 sig
->call_convention
= MONO_CALL_DEFAULT
;
13922 sig
->param_count
= nargs
;
13923 /* TODO: Copy type ? */
13924 sig
->ret
= helper
->return_type
->type
;
13925 for (i
= 0; i
< nargs
; ++i
) {
13926 sig
->params
[i
] = mono_type_array_get_and_resolve (helper
->arguments
, i
, error
);
13927 if (!is_ok (error
)) {
13928 image_g_free (image
, sig
);
13934 *handle_class
= NULL
;
13935 } else if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
13936 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
13937 /* Already created by the managed code */
13938 g_assert (method
->mhandle
);
13939 result
= method
->mhandle
;
13940 *handle_class
= mono_defaults
.methodhandle_class
;
13941 } else if (strcmp (obj
->vtable
->klass
->name
, "GenericTypeParameterBuilder") == 0) {
13942 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
13943 return_val_if_nok (error
, NULL
);
13944 type
= mono_class_inflate_generic_type_checked (type
, context
, error
);
13945 return_val_if_nok (error
, NULL
);
13947 result
= mono_class_from_mono_type (type
);
13948 *handle_class
= mono_defaults
.typehandle_class
;
13950 mono_metadata_free_type (type
);
13951 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoGenericClass") == 0) {
13952 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
13953 return_val_if_nok (error
, NULL
);
13954 type
= mono_class_inflate_generic_type_checked (type
, context
, error
);
13955 return_val_if_nok (error
, NULL
);
13957 result
= mono_class_from_mono_type (type
);
13958 *handle_class
= mono_defaults
.typehandle_class
;
13960 mono_metadata_free_type (type
);
13961 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldOnTypeBuilderInst") == 0) {
13962 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
13963 MonoClass
*inflated
;
13965 MonoClassField
*field
;
13967 if (is_sre_field_builder (mono_object_class (f
->fb
)))
13968 field
= ((MonoReflectionFieldBuilder
*)f
->fb
)->handle
;
13969 else if (is_sr_mono_field (mono_object_class (f
->fb
)))
13970 field
= ((MonoReflectionField
*)f
->fb
)->field
;
13972 g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f
->fb
)));
13974 MonoType
*finst
= mono_reflection_type_get_handle ((MonoReflectionType
*)f
->inst
, error
);
13975 return_val_if_nok (error
, NULL
);
13976 type
= mono_class_inflate_generic_type_checked (finst
, context
, error
);
13977 return_val_if_nok (error
, NULL
);
13979 inflated
= mono_class_from_mono_type (type
);
13981 result
= field
= mono_class_get_field_from_name (inflated
, mono_field_get_name (field
));
13982 ensure_complete_type (field
->parent
, error
);
13983 if (!is_ok (error
)) {
13984 mono_metadata_free_type (type
);
13989 mono_metadata_free_type (type
);
13990 *handle_class
= mono_defaults
.fieldhandle_class
;
13991 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
13992 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
13993 MonoType
*cinst
= mono_reflection_type_get_handle ((MonoReflectionType
*)c
->inst
, error
);
13994 return_val_if_nok (error
, NULL
);
13995 MonoType
*type
= mono_class_inflate_generic_type_checked (cinst
, context
, error
);
13996 return_val_if_nok (error
, NULL
);
13998 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
13999 MonoMethod
*method
;
14001 if (is_sre_ctor_builder (mono_object_class (c
->cb
)))
14002 method
= ((MonoReflectionCtorBuilder
*)c
->cb
)->mhandle
;
14003 else if (is_sr_mono_cmethod (mono_object_class (c
->cb
)))
14004 method
= ((MonoReflectionMethod
*)c
->cb
)->method
;
14006 g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c
->cb
)));
14008 result
= inflate_mono_method (inflated_klass
, method
, (MonoObject
*)c
->cb
);
14009 *handle_class
= mono_defaults
.methodhandle_class
;
14010 mono_metadata_free_type (type
);
14011 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodOnTypeBuilderInst") == 0) {
14012 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
14013 if (m
->method_args
) {
14014 result
= mono_reflection_method_on_tb_inst_get_handle (m
, error
);
14015 return_val_if_nok (error
, NULL
);
14017 result
= mono_class_inflate_generic_method_checked ((MonoMethod
*)result
, context
, error
);
14018 mono_error_assert_ok (error
);
14021 MonoType
*minst
= mono_reflection_type_get_handle ((MonoReflectionType
*)m
->inst
, error
);
14022 return_val_if_nok (error
, NULL
);
14023 MonoType
*type
= mono_class_inflate_generic_type_checked (minst
, context
, error
);
14024 return_val_if_nok (error
, NULL
);
14026 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
14027 MonoMethod
*method
;
14029 if (is_sre_method_builder (mono_object_class (m
->mb
)))
14030 method
= ((MonoReflectionMethodBuilder
*)m
->mb
)->mhandle
;
14031 else if (is_sr_mono_method (mono_object_class (m
->mb
)))
14032 method
= ((MonoReflectionMethod
*)m
->mb
)->method
;
14034 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m
->mb
)));
14036 result
= inflate_mono_method (inflated_klass
, method
, (MonoObject
*)m
->mb
);
14037 mono_metadata_free_type (type
);
14039 *handle_class
= mono_defaults
.methodhandle_class
;
14040 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoArrayMethod") == 0) {
14041 MonoReflectionArrayMethod
*m
= (MonoReflectionArrayMethod
*)obj
;
14044 MonoMethod
*method
;
14048 mtype
= mono_reflection_type_get_handle (m
->parent
, error
);
14049 return_val_if_nok (error
, NULL
);
14050 klass
= mono_class_from_mono_type (mtype
);
14052 /* Find the method */
14054 name
= mono_string_to_utf8 (m
->name
);
14056 while ((method
= mono_class_get_methods (klass
, &iter
))) {
14057 if (!strcmp (method
->name
, name
))
14064 // FIXME: Check parameters/return value etc. match
14067 *handle_class
= mono_defaults
.methodhandle_class
;
14068 } else if (is_sre_array (mono_object_get_class(obj
)) ||
14069 is_sre_byref (mono_object_get_class(obj
)) ||
14070 is_sre_pointer (mono_object_get_class(obj
))) {
14071 MonoReflectionType
*ref_type
= (MonoReflectionType
*)obj
;
14072 MonoType
*type
= mono_reflection_type_get_handle (ref_type
, error
);
14073 return_val_if_nok (error
, NULL
);
14076 MonoType
*inflated
= mono_class_inflate_generic_type_checked (type
, context
, error
);
14077 return_val_if_nok (error
, NULL
);
14079 result
= mono_class_from_mono_type (inflated
);
14080 mono_metadata_free_type (inflated
);
14082 result
= mono_class_from_mono_type (type
);
14084 *handle_class
= mono_defaults
.typehandle_class
;
14086 g_print ("%s\n", obj
->vtable
->klass
->name
);
14087 g_assert_not_reached ();
14092 #else /* DISABLE_REFLECTION_EMIT */
14095 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
14097 g_assert_not_reached ();
14102 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
14104 g_assert_not_reached ();
14108 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
14110 g_assert_not_reached ();
14114 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
14116 g_assert_not_reached ();
14120 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
14122 g_assert_not_reached ();
14126 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
14128 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14132 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
14134 g_assert_not_reached ();
14138 mono_image_set_wrappers_type (MonoReflectionModuleBuilder
*moduleb
, MonoReflectionType
*type
)
14140 g_assert_not_reached ();
14143 MonoReflectionModule
*
14144 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
, MonoError
*error
)
14146 g_assert_not_reached ();
14151 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
14153 g_assert_not_reached ();
14158 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
, MonoError
*error
)
14160 g_assert_not_reached ();
14165 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
14166 gboolean create_open_instance
, gboolean register_token
, MonoError
*error
)
14168 g_assert_not_reached ();
14173 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
14178 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*fields
)
14180 g_assert_not_reached ();
14184 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
, MonoError
*error
)
14186 mono_error_init (error
);
14188 *num_overrides
= 0;
14191 MonoReflectionEvent
*
14192 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
14194 g_assert_not_reached ();
14198 MonoReflectionType
*
14199 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
14201 g_assert_not_reached ();
14206 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
14208 g_assert_not_reached ();
14212 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
14214 g_assert_not_reached ();
14219 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
14221 g_assert_not_reached ();
14226 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
14231 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
14237 mono_reflection_type_get_handle (MonoReflectionType
* ref
, MonoError
*error
)
14239 mono_error_init (error
);
14246 mono_reflection_free_dynamic_generic_class (MonoGenericClass
*gclass
)
14248 g_assert_not_reached ();
14251 #endif /* DISABLE_REFLECTION_EMIT */
14253 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14254 const static guint32 declsec_flags_map
[] = {
14255 0x00000000, /* empty */
14256 MONO_DECLSEC_FLAG_REQUEST
, /* SECURITY_ACTION_REQUEST (x01) */
14257 MONO_DECLSEC_FLAG_DEMAND
, /* SECURITY_ACTION_DEMAND (x02) */
14258 MONO_DECLSEC_FLAG_ASSERT
, /* SECURITY_ACTION_ASSERT (x03) */
14259 MONO_DECLSEC_FLAG_DENY
, /* SECURITY_ACTION_DENY (x04) */
14260 MONO_DECLSEC_FLAG_PERMITONLY
, /* SECURITY_ACTION_PERMITONLY (x05) */
14261 MONO_DECLSEC_FLAG_LINKDEMAND
, /* SECURITY_ACTION_LINKDEMAND (x06) */
14262 MONO_DECLSEC_FLAG_INHERITANCEDEMAND
, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
14263 MONO_DECLSEC_FLAG_REQUEST_MINIMUM
, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
14264 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL
, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
14265 MONO_DECLSEC_FLAG_REQUEST_REFUSE
, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
14266 MONO_DECLSEC_FLAG_PREJIT_GRANT
, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
14267 MONO_DECLSEC_FLAG_PREJIT_DENY
, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
14268 MONO_DECLSEC_FLAG_NONCAS_DEMAND
, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
14269 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
14270 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
14271 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
14272 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
14273 MONO_DECLSEC_FLAG_DEMAND_CHOICE
, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
14277 * Returns flags that includes all available security action associated to the handle.
14278 * @token: metadata token (either for a class or a method)
14279 * @image: image where resides the metadata.
14282 mono_declsec_get_flags (MonoImage
*image
, guint32 token
)
14284 int index
= mono_metadata_declsec_from_index (image
, token
);
14285 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
14286 guint32 result
= 0;
14290 /* HasSecurity can be present for other, not specially encoded, attributes,
14291 e.g. SuppressUnmanagedCodeSecurityAttribute */
14295 for (i
= index
; i
< t
->rows
; i
++) {
14296 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
14298 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
14299 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
14302 action
= cols
[MONO_DECL_SECURITY_ACTION
];
14303 if ((action
>= MONO_DECLSEC_ACTION_MIN
) && (action
<= MONO_DECLSEC_ACTION_MAX
)) {
14304 result
|= declsec_flags_map
[action
];
14306 g_assert_not_reached ();
14313 * Get the security actions (in the form of flags) associated with the specified method.
14315 * @method: The method for which we want the declarative security flags.
14316 * Return the declarative security flags for the method (only).
14318 * Note: To keep MonoMethod size down we do not cache the declarative security flags
14319 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
14322 mono_declsec_flags_from_method (MonoMethod
*method
)
14324 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
14325 /* FIXME: No cache (for the moment) */
14326 guint32 idx
= mono_method_get_index (method
);
14327 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
14328 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
14329 return mono_declsec_get_flags (method
->klass
->image
, idx
);
14335 * Get the security actions (in the form of flags) associated with the specified class.
14337 * @klass: The class for which we want the declarative security flags.
14338 * Return the declarative security flags for the class.
14340 * Note: We cache the flags inside the MonoClass structure as this will get
14341 * called very often (at least for each method).
14344 mono_declsec_flags_from_class (MonoClass
*klass
)
14346 if (klass
->flags
& TYPE_ATTRIBUTE_HAS_SECURITY
) {
14347 if (!klass
->ext
|| !klass
->ext
->declsec_flags
) {
14350 idx
= mono_metadata_token_index (klass
->type_token
);
14351 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
14352 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
14353 mono_loader_lock ();
14354 mono_class_alloc_ext (klass
);
14355 mono_loader_unlock ();
14356 /* we cache the flags on classes */
14357 klass
->ext
->declsec_flags
= mono_declsec_get_flags (klass
->image
, idx
);
14359 return klass
->ext
->declsec_flags
;
14365 * Get the security actions (in the form of flags) associated with the specified assembly.
14367 * @assembly: The assembly for which we want the declarative security flags.
14368 * Return the declarative security flags for the assembly.
14371 mono_declsec_flags_from_assembly (MonoAssembly
*assembly
)
14373 guint32 idx
= 1; /* there is only one assembly */
14374 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
14375 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
14376 return mono_declsec_get_flags (assembly
->image
, idx
);
14381 * Fill actions for the specific index (which may either be an encoded class token or
14382 * an encoded method token) from the metadata image.
14383 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14386 fill_actions_from_index (MonoImage
*image
, guint32 token
, MonoDeclSecurityActions
* actions
,
14387 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
14389 MonoBoolean result
= FALSE
;
14391 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
14392 int index
= mono_metadata_declsec_from_index (image
, token
);
14395 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
14396 for (i
= index
; i
< t
->rows
; i
++) {
14397 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
14399 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
14402 /* if present only replace (class) permissions with method permissions */
14403 /* if empty accept either class or method permissions */
14404 if (cols
[MONO_DECL_SECURITY_ACTION
] == id_std
) {
14405 if (!actions
->demand
.blob
) {
14406 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
14407 actions
->demand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
14408 actions
->demand
.blob
= (char*) (blob
+ 2);
14409 actions
->demand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
14412 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_noncas
) {
14413 if (!actions
->noncasdemand
.blob
) {
14414 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
14415 actions
->noncasdemand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
14416 actions
->noncasdemand
.blob
= (char*) (blob
+ 2);
14417 actions
->noncasdemand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
14420 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_choice
) {
14421 if (!actions
->demandchoice
.blob
) {
14422 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
14423 actions
->demandchoice
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
14424 actions
->demandchoice
.blob
= (char*) (blob
+ 2);
14425 actions
->demandchoice
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
14435 mono_declsec_get_class_demands_params (MonoClass
*klass
, MonoDeclSecurityActions
* demands
,
14436 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
14438 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
14439 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
14440 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
14441 return fill_actions_from_index (klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
14445 mono_declsec_get_method_demands_params (MonoMethod
*method
, MonoDeclSecurityActions
* demands
,
14446 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
14448 guint32 idx
= mono_method_get_index (method
);
14449 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
14450 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
14451 return fill_actions_from_index (method
->klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
14455 * Collect all actions (that requires to generate code in mini) assigned for
14456 * the specified method.
14457 * Note: Don't use the content of actions if the function return FALSE.
14460 mono_declsec_get_demands (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
14462 guint32 mask
= MONO_DECLSEC_FLAG_DEMAND
| MONO_DECLSEC_FLAG_NONCAS_DEMAND
|
14463 MONO_DECLSEC_FLAG_DEMAND_CHOICE
;
14464 MonoBoolean result
= FALSE
;
14467 /* quick exit if no declarative security is present in the metadata */
14468 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
14471 /* we want the original as the wrapper is "free" of the security informations */
14472 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
14473 method
= mono_marshal_method_from_wrapper (method
);
14478 /* First we look for method-level attributes */
14479 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
14480 mono_class_init (method
->klass
);
14481 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
14483 result
= mono_declsec_get_method_demands_params (method
, demands
,
14484 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
14487 /* Here we use (or create) the class declarative cache to look for demands */
14488 flags
= mono_declsec_flags_from_class (method
->klass
);
14489 if (flags
& mask
) {
14491 mono_class_init (method
->klass
);
14492 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
14494 result
|= mono_declsec_get_class_demands_params (method
->klass
, demands
,
14495 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
14498 /* The boolean return value is used as a shortcut in case nothing needs to
14499 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14505 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14507 * Note: Don't use the content of actions if the function return FALSE.
14510 mono_declsec_get_linkdemands (MonoMethod
*method
, MonoDeclSecurityActions
* klass
, MonoDeclSecurityActions
*cmethod
)
14512 MonoBoolean result
= FALSE
;
14515 /* quick exit if no declarative security is present in the metadata */
14516 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
14519 /* we want the original as the wrapper is "free" of the security informations */
14520 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
14521 method
= mono_marshal_method_from_wrapper (method
);
14526 /* results are independant - zeroize both */
14527 memset (cmethod
, 0, sizeof (MonoDeclSecurityActions
));
14528 memset (klass
, 0, sizeof (MonoDeclSecurityActions
));
14530 /* First we look for method-level attributes */
14531 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
14532 mono_class_init (method
->klass
);
14534 result
= mono_declsec_get_method_demands_params (method
, cmethod
,
14535 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
14538 /* Here we use (or create) the class declarative cache to look for demands */
14539 flags
= mono_declsec_flags_from_class (method
->klass
);
14540 if (flags
& (MONO_DECLSEC_FLAG_LINKDEMAND
| MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
| MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
)) {
14541 mono_class_init (method
->klass
);
14543 result
|= mono_declsec_get_class_demands_params (method
->klass
, klass
,
14544 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
14551 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14553 * @klass The inherited class - this is the class that provides the security check (attributes)
14555 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14557 * Note: Don't use the content of actions if the function return FALSE.
14560 mono_declsec_get_inheritdemands_class (MonoClass
*klass
, MonoDeclSecurityActions
* demands
)
14562 MonoBoolean result
= FALSE
;
14565 /* quick exit if no declarative security is present in the metadata */
14566 if (!klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
14569 /* Here we use (or create) the class declarative cache to look for demands */
14570 flags
= mono_declsec_flags_from_class (klass
);
14571 if (flags
& (MONO_DECLSEC_FLAG_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
)) {
14572 mono_class_init (klass
);
14573 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
14575 result
|= mono_declsec_get_class_demands_params (klass
, demands
,
14576 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
14583 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14585 * Note: Don't use the content of actions if the function return FALSE.
14588 mono_declsec_get_inheritdemands_method (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
14590 /* quick exit if no declarative security is present in the metadata */
14591 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
14594 /* we want the original as the wrapper is "free" of the security informations */
14595 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
14596 method
= mono_marshal_method_from_wrapper (method
);
14601 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
14602 mono_class_init (method
->klass
);
14603 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
14605 return mono_declsec_get_method_demands_params (method
, demands
,
14606 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
14613 get_declsec_action (MonoImage
*image
, guint32 token
, guint32 action
, MonoDeclSecurityEntry
*entry
)
14615 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
14619 int index
= mono_metadata_declsec_from_index (image
, token
);
14623 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
14624 for (i
= index
; i
< t
->rows
; i
++) {
14625 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
14627 /* shortcut - index are ordered */
14628 if (token
!= cols
[MONO_DECL_SECURITY_PARENT
])
14631 if (cols
[MONO_DECL_SECURITY_ACTION
] == action
) {
14632 const char *metadata
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
14633 entry
->blob
= (char*) (metadata
+ 2);
14634 entry
->size
= mono_metadata_decode_blob_size (metadata
, &metadata
);
14643 mono_declsec_get_method_action (MonoMethod
*method
, guint32 action
, MonoDeclSecurityEntry
*entry
)
14645 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
14646 guint32 idx
= mono_method_get_index (method
);
14647 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
14648 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
14649 return get_declsec_action (method
->klass
->image
, idx
, action
, entry
);
14655 mono_declsec_get_class_action (MonoClass
*klass
, guint32 action
, MonoDeclSecurityEntry
*entry
)
14658 guint32 flags
= mono_declsec_flags_from_class (klass
);
14659 if (declsec_flags_map
[action
] & flags
) {
14660 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
14661 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
14662 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
14663 return get_declsec_action (klass
->image
, idx
, action
, entry
);
14669 mono_declsec_get_assembly_action (MonoAssembly
*assembly
, guint32 action
, MonoDeclSecurityEntry
*entry
)
14671 guint32 idx
= 1; /* there is only one assembly */
14672 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
14673 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
14675 return get_declsec_action (assembly
->image
, idx
, action
, entry
);
14679 mono_reflection_call_is_assignable_to (MonoClass
*klass
, MonoClass
*oklass
, MonoError
*error
)
14681 MonoObject
*res
, *exc
;
14683 static MonoMethod
*method
= NULL
;
14685 mono_error_init (error
);
14687 if (method
== NULL
) {
14688 method
= mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14693 * The result of mono_type_get_object_checked () might be a System.MonoType but we
14694 * need a TypeBuilder so use mono_class_get_ref_info (klass).
14696 g_assert (mono_class_get_ref_info (klass
));
14697 g_assert (!strcmp (((MonoObject
*)(mono_class_get_ref_info (klass
)))->vtable
->klass
->name
, "TypeBuilder"));
14699 params
[0] = mono_type_get_object_checked (mono_domain_get (), &oklass
->byval_arg
, error
);
14700 return_val_if_nok (error
, FALSE
);
14702 res
= mono_runtime_try_invoke (method
, (MonoObject
*)(mono_class_get_ref_info (klass
)), params
, &exc
, error
);
14704 if (exc
|| !mono_error_ok (error
)) {
14705 mono_error_cleanup (error
);
14708 return *(MonoBoolean
*)mono_object_unbox (res
);
14712 * mono_reflection_type_get_type:
14713 * @reftype: the System.Type object
14715 * Returns the MonoType* associated with the C# System.Type object @reftype.
14718 mono_reflection_type_get_type (MonoReflectionType
*reftype
)
14720 g_assert (reftype
);
14723 MonoType
*result
= mono_reflection_type_get_handle (reftype
, &error
);
14724 mono_error_assert_ok (&error
);
14729 * mono_reflection_assembly_get_assembly:
14730 * @refassembly: the System.Reflection.Assembly object
14732 * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14735 mono_reflection_assembly_get_assembly (MonoReflectionAssembly
*refassembly
)
14737 g_assert (refassembly
);
14739 return refassembly
->assembly
;