3 * Routines for encoding SRE builders into a
4 * MonoDynamicImage and generating tokens.
8 * Paolo Molaro (lupus@ximian.com)
10 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 * Copyright 2011 Rodrigo Kumpera
13 * Copyright 2016 Microsoft
15 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include "mono/metadata/dynamic-image-internals.h"
21 #include "mono/metadata/dynamic-stream-internals.h"
22 #include "mono/metadata/object-internals.h"
23 #include "mono/metadata/reflection-internals.h"
24 #include "mono/metadata/sre-internals.h"
25 #include "mono/metadata/tabledefs.h"
26 #include "mono/metadata/tokentype.h"
27 #include "mono/utils/checked-build.h"
35 static guint32
create_typespec (MonoDynamicImage
*assembly
, MonoType
*type
);
36 static void encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
);
37 static guint32
mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
);
40 mono_image_add_stream_data (MonoDynamicStream
*stream
, const char *data
, guint32 len
)
42 return mono_dynstream_add_data (stream
, data
, len
);
46 alloc_table (MonoDynamicTable
*table
, guint nrows
)
48 mono_dynimage_alloc_table (table
, nrows
);
52 sigbuffer_init (SigBuffer
*buf
, int size
)
54 MONO_REQ_GC_NEUTRAL_MODE
;
56 buf
->buf
= (char *)g_malloc (size
);
58 buf
->end
= buf
->buf
+ size
;
62 sigbuffer_make_room (SigBuffer
*buf
, int size
)
64 MONO_REQ_GC_NEUTRAL_MODE
;
66 if (buf
->end
- buf
->p
< size
) {
67 int new_size
= buf
->end
- buf
->buf
+ size
+ 32;
68 char *p
= (char *)g_realloc (buf
->buf
, new_size
);
69 size
= buf
->p
- buf
->buf
;
72 buf
->end
= buf
->buf
+ new_size
;
77 sigbuffer_add_value (SigBuffer
*buf
, guint32 val
)
79 MONO_REQ_GC_NEUTRAL_MODE
;
81 sigbuffer_make_room (buf
, 6);
82 mono_metadata_encode_value (val
, buf
->p
, &buf
->p
);
86 sigbuffer_add_byte (SigBuffer
*buf
, guint8 val
)
88 MONO_REQ_GC_NEUTRAL_MODE
;
90 sigbuffer_make_room (buf
, 1);
96 sigbuffer_add_mem (SigBuffer
*buf
, char *p
, guint32 size
)
98 MONO_REQ_GC_NEUTRAL_MODE
;
100 sigbuffer_make_room (buf
, size
);
101 memcpy (buf
->p
, p
, size
);
106 sigbuffer_free (SigBuffer
*buf
)
108 MONO_REQ_GC_NEUTRAL_MODE
;
114 sigbuffer_add_to_blob_cached (MonoDynamicImage
*assembly
, SigBuffer
*buf
)
116 MONO_REQ_GC_NEUTRAL_MODE
;
120 guint32 size
= buf
->p
- buf
->buf
;
122 g_assert (size
<= (buf
->end
- buf
->buf
));
123 mono_metadata_encode_value (size
, b
, &b
);
124 return mono_dynamic_image_add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, buf
->buf
, size
);
129 encode_generic_class (MonoDynamicImage
*assembly
, MonoGenericClass
*gclass
, SigBuffer
*buf
)
131 MONO_REQ_GC_NEUTRAL_MODE
;
134 MonoGenericInst
*class_inst
;
139 class_inst
= gclass
->context
.class_inst
;
141 sigbuffer_add_value (buf
, MONO_TYPE_GENERICINST
);
142 klass
= gclass
->container_class
;
143 sigbuffer_add_value (buf
, m_class_get_byval_arg (klass
)->type
);
144 sigbuffer_add_value (buf
, mono_dynimage_encode_typedef_or_ref_full (assembly
, m_class_get_byval_arg (klass
), FALSE
));
146 sigbuffer_add_value (buf
, class_inst
->type_argc
);
147 for (i
= 0; i
< class_inst
->type_argc
; ++i
)
148 encode_type (assembly
, class_inst
->type_argv
[i
], buf
);
153 encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
)
155 MONO_REQ_GC_NEUTRAL_MODE
;
158 g_assert_not_reached ();
163 sigbuffer_add_value (buf
, MONO_TYPE_BYREF
);
167 case MONO_TYPE_BOOLEAN
:
181 case MONO_TYPE_STRING
:
182 case MONO_TYPE_OBJECT
:
183 case MONO_TYPE_TYPEDBYREF
:
184 sigbuffer_add_value (buf
, type
->type
);
187 sigbuffer_add_value (buf
, type
->type
);
188 encode_type (assembly
, type
->data
.type
, buf
);
190 case MONO_TYPE_SZARRAY
:
191 sigbuffer_add_value (buf
, type
->type
);
192 encode_type (assembly
, m_class_get_byval_arg (type
->data
.klass
), buf
);
194 case MONO_TYPE_VALUETYPE
:
195 case MONO_TYPE_CLASS
: {
196 MonoClass
*k
= mono_class_from_mono_type (type
);
198 if (mono_class_is_gtd (k
)) {
199 MonoGenericClass
*gclass
= mono_metadata_lookup_generic_class (k
, mono_class_get_generic_container (k
)->context
.class_inst
, TRUE
);
200 encode_generic_class (assembly
, gclass
, buf
);
203 * Make sure we use the correct type.
205 sigbuffer_add_value (buf
, m_class_get_byval_arg (k
)->type
);
207 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
208 * otherwise two typerefs could point to the same type, leading to
209 * verification errors.
211 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, m_class_get_byval_arg (k
)));
215 case MONO_TYPE_ARRAY
:
216 sigbuffer_add_value (buf
, type
->type
);
217 encode_type (assembly
, m_class_get_byval_arg (type
->data
.array
->eklass
), buf
);
218 sigbuffer_add_value (buf
, type
->data
.array
->rank
);
219 sigbuffer_add_value (buf
, 0); /* FIXME: set to 0 for now */
220 sigbuffer_add_value (buf
, 0);
222 case MONO_TYPE_GENERICINST
:
223 encode_generic_class (assembly
, type
->data
.generic_class
, buf
);
227 sigbuffer_add_value (buf
, type
->type
);
228 sigbuffer_add_value (buf
, mono_type_get_generic_param_num (type
));
231 g_error ("need to encode type %x", type
->type
);
236 encode_reflection_type (MonoDynamicImage
*assembly
, MonoReflectionTypeHandle type
, SigBuffer
*buf
, MonoError
*error
)
238 MONO_REQ_GC_UNSAFE_MODE
;
243 sigbuffer_add_value (buf
, MONO_TYPE_VOID
);
247 MonoType
*t
= mono_reflection_type_handle_mono_type (type
, error
);
248 return_if_nok (error
);
249 encode_type (assembly
, t
, buf
);
253 encode_reflection_type_raw (MonoDynamicImage
*assembly
, MonoReflectionType
* type_raw
, SigBuffer
*buf
, MonoError
*error
)
255 HANDLE_FUNCTION_ENTER (); /* FIXME callers of encode_reflection_type_raw should use handles */
257 MONO_HANDLE_DCL (MonoReflectionType
, type
);
258 encode_reflection_type (assembly
, type
, buf
, error
);
259 HANDLE_FUNCTION_RETURN ();
264 encode_custom_modifiers (MonoDynamicImage
*assembly
, MonoArrayHandle modreq
, MonoArrayHandle modopt
, SigBuffer
*buf
, MonoError
*error
)
266 HANDLE_FUNCTION_ENTER ();
267 MONO_REQ_GC_UNSAFE_MODE
;
273 if (!MONO_HANDLE_IS_NULL (modreq
)) {
274 for (i
= 0; i
< mono_array_handle_length (modreq
); ++i
) {
275 MonoType
*mod
= mono_type_array_get_and_resolve (modreq
, i
, error
);
276 goto_if_nok (error
, leave
);
277 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_REQD
);
278 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
));
281 if (!MONO_HANDLE_IS_NULL (modopt
)) {
282 for (i
= 0; i
< mono_array_handle_length (modopt
); ++i
) {
283 MonoType
*mod
= mono_type_array_get_and_resolve (modopt
, i
, error
);
284 goto_if_nok (error
, leave
);
285 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_OPT
);
286 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
));
290 HANDLE_FUNCTION_RETURN ();
294 encode_custom_modifiers_raw (MonoDynamicImage
*assembly
, MonoArray
*modreq_raw
, MonoArray
*modopt_raw
, SigBuffer
*buf
, MonoError
*error
)
296 HANDLE_FUNCTION_ENTER (); /* FIXME callers of encode_custom_modifiers_raw should use handles */
298 MONO_HANDLE_DCL (MonoArray
, modreq
);
299 MONO_HANDLE_DCL (MonoArray
, modopt
);
300 encode_custom_modifiers (assembly
, modreq
, modopt
, buf
, error
);
301 HANDLE_FUNCTION_RETURN ();
305 #ifndef DISABLE_REFLECTION_EMIT
307 mono_dynimage_encode_method_signature (MonoDynamicImage
*assembly
, MonoMethodSignature
*sig
)
309 MONO_REQ_GC_UNSAFE_MODE
;
313 guint32 nparams
= sig
->param_count
;
319 sigbuffer_init (&buf
, 32);
321 * FIXME: vararg, explicit_this, differenc call_conv values...
323 idx
= sig
->call_convention
;
325 idx
|= 0x20; /* hasthis */
326 if (sig
->generic_param_count
)
327 idx
|= 0x10; /* generic */
328 sigbuffer_add_byte (&buf
, idx
);
329 if (sig
->generic_param_count
)
330 sigbuffer_add_value (&buf
, sig
->generic_param_count
);
331 sigbuffer_add_value (&buf
, nparams
);
332 encode_type (assembly
, sig
->ret
, &buf
);
333 for (i
= 0; i
< nparams
; ++i
) {
334 if (i
== sig
->sentinelpos
)
335 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
336 encode_type (assembly
, sig
->params
[i
], &buf
);
338 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
339 sigbuffer_free (&buf
);
342 #else /* DISABLE_REFLECTION_EMIT */
344 mono_dynimage_encode_method_signature (MonoDynamicImage
*assembly
, MonoMethodSignature
*sig
)
346 g_assert_not_reached ();
352 mono_dynimage_encode_method_builder_signature (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
, MonoError
*error
)
354 MONO_REQ_GC_UNSAFE_MODE
;
359 * FIXME: reuse code from method_encode_signature().
363 guint32 nparams
= mb
->parameters
? mono_array_length (mb
->parameters
): 0;
364 guint32 ngparams
= mb
->generic_params
? mono_array_length (mb
->generic_params
): 0;
365 guint32 notypes
= mb
->opt_types
? mono_array_length (mb
->opt_types
): 0;
368 sigbuffer_init (&buf
, 32);
369 /* LAMESPEC: all the call conv spec is foobared */
370 idx
= mb
->call_conv
& 0x60; /* has-this, explicit-this */
371 if (mb
->call_conv
& 2)
372 idx
|= 0x5; /* vararg */
373 if (!(mb
->attrs
& METHOD_ATTRIBUTE_STATIC
))
374 idx
|= 0x20; /* hasthis */
376 idx
|= 0x10; /* generic */
377 sigbuffer_add_byte (&buf
, idx
);
379 sigbuffer_add_value (&buf
, ngparams
);
380 sigbuffer_add_value (&buf
, nparams
+ notypes
);
381 encode_custom_modifiers_raw (assembly
, mb
->return_modreq
, mb
->return_modopt
, &buf
, error
);
382 goto_if_nok (error
, leave
);
383 encode_reflection_type_raw (assembly
, mb
->rtype
, &buf
, error
);
384 goto_if_nok (error
, leave
);
385 for (i
= 0; i
< nparams
; ++i
) {
386 MonoArray
*modreq
= NULL
;
387 MonoArray
*modopt
= NULL
;
388 MonoReflectionType
*pt
;
390 if (mb
->param_modreq
&& (i
< mono_array_length (mb
->param_modreq
)))
391 modreq
= mono_array_get (mb
->param_modreq
, MonoArray
*, i
);
392 if (mb
->param_modopt
&& (i
< mono_array_length (mb
->param_modopt
)))
393 modopt
= mono_array_get (mb
->param_modopt
, MonoArray
*, i
);
394 encode_custom_modifiers_raw (assembly
, modreq
, modopt
, &buf
, error
);
395 goto_if_nok (error
, leave
);
396 pt
= mono_array_get (mb
->parameters
, MonoReflectionType
*, i
);
397 encode_reflection_type_raw (assembly
, pt
, &buf
, error
);
398 goto_if_nok (error
, leave
);
401 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
402 for (i
= 0; i
< notypes
; ++i
) {
403 MonoReflectionType
*pt
;
405 pt
= mono_array_get (mb
->opt_types
, MonoReflectionType
*, i
);
406 encode_reflection_type_raw (assembly
, pt
, &buf
, error
);
407 goto_if_nok (error
, leave
);
410 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
412 sigbuffer_free (&buf
);
417 mono_dynimage_encode_locals (MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
, MonoError
*error
)
419 MONO_REQ_GC_UNSAFE_MODE
;
423 MonoDynamicTable
*table
;
425 guint32 idx
, sig_idx
;
426 guint nl
= mono_array_length (ilgen
->locals
);
430 sigbuffer_init (&buf
, 32);
431 sigbuffer_add_value (&buf
, 0x07);
432 sigbuffer_add_value (&buf
, nl
);
433 for (i
= 0; i
< nl
; ++i
) {
434 MonoReflectionLocalBuilder
*lb
= mono_array_get (ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
437 sigbuffer_add_value (&buf
, MONO_TYPE_PINNED
);
439 encode_reflection_type_raw (assembly
, (MonoReflectionType
*)lb
->type
, &buf
, error
);
440 if (!is_ok (error
)) {
441 sigbuffer_free (&buf
);
445 sig_idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
446 sigbuffer_free (&buf
);
448 if (assembly
->standalonesig_cache
== NULL
)
449 assembly
->standalonesig_cache
= g_hash_table_new (NULL
, NULL
);
450 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
)));
454 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
455 idx
= table
->next_idx
++;
457 alloc_table (table
, table
->rows
);
458 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
460 values
[MONO_STAND_ALONE_SIGNATURE
] = sig_idx
;
462 g_hash_table_insert (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
), GUINT_TO_POINTER (idx
));
469 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
470 * dest may be misaligned.
473 swap_with_size (char *dest
, const char* val
, int len
, int nelem
) {
474 MONO_REQ_GC_NEUTRAL_MODE
;
475 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
478 for (elem
= 0; elem
< nelem
; ++elem
) {
504 g_assert_not_reached ();
510 memcpy (dest
, val
, len
* nelem
);
516 mono_dynimage_encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, MonoTypeEnum
*ret_type
)
518 MONO_REQ_GC_UNSAFE_MODE
;
524 guint32 idx
= 0, len
= 0, dummy
= 0;
526 buf
= (char *)g_malloc (64);
528 *ret_type
= MONO_TYPE_CLASS
;
530 box_val
= (char*)&dummy
;
532 box_val
= ((char*)val
) + sizeof (MonoObject
);
533 *ret_type
= m_class_get_byval_arg (val
->vtable
->klass
)->type
;
537 case MONO_TYPE_BOOLEAN
:
559 case MONO_TYPE_VALUETYPE
: {
560 MonoClass
*klass
= val
->vtable
->klass
;
562 if (m_class_is_enumtype (klass
)) {
563 *ret_type
= mono_class_enum_basetype (klass
)->type
;
565 } else if (mono_is_corlib_image (m_class_get_image (klass
)) && strcmp (m_class_get_name_space (klass
), "System") == 0 && strcmp (m_class_get_name (klass
), "DateTime") == 0) {
568 g_error ("we can't encode valuetypes, we should have never reached this line");
571 case MONO_TYPE_CLASS
:
573 case MONO_TYPE_STRING
: {
574 MonoString
*str
= (MonoString
*)val
;
575 /* there is no signature */
576 len
= str
->length
* 2;
577 mono_metadata_encode_value (len
, b
, &b
);
578 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
580 char *swapped
= g_malloc (2 * mono_string_length (str
));
581 const char *p
= (const char*)mono_string_chars (str
);
583 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
584 idx
= mono_dynamic_image_add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
588 idx
= mono_dynamic_image_add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
594 case MONO_TYPE_GENERICINST
:
595 *ret_type
= m_class_get_byval_arg (mono_class_get_generic_class (val
->vtable
->klass
)->container_class
)->type
;
598 g_error ("we don't encode constant type 0x%02x yet", *ret_type
);
601 /* there is no signature */
602 mono_metadata_encode_value (len
, b
, &b
);
603 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
604 idx
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
605 swap_with_size (blob_size
, box_val
, len
, 1);
606 mono_image_add_stream_data (&assembly
->blob
, blob_size
, len
);
608 idx
= mono_dynamic_image_add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, box_val
, len
);
616 mono_dynimage_encode_field_signature (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
, MonoError
*error
)
618 MONO_REQ_GC_UNSAFE_MODE
;
624 guint32 typespec
= 0;
628 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
, error
);
629 return_val_if_nok (error
, 0);
630 klass
= mono_class_from_mono_type (type
);
632 sigbuffer_init (&buf
, 32);
634 sigbuffer_add_value (&buf
, 0x06);
635 encode_custom_modifiers_raw (assembly
, fb
->modreq
, fb
->modopt
, &buf
, error
);
636 goto_if_nok (error
, fail
);
637 /* encode custom attributes before the type */
639 if (mono_class_is_gtd (klass
))
640 typespec
= create_typespec (assembly
, type
);
643 MonoGenericClass
*gclass
;
644 gclass
= mono_metadata_lookup_generic_class (klass
, mono_class_get_generic_container (klass
)->context
.class_inst
, TRUE
);
645 encode_generic_class (assembly
, gclass
, &buf
);
647 encode_type (assembly
, type
, &buf
);
649 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
650 sigbuffer_free (&buf
);
653 sigbuffer_free (&buf
);
657 #ifndef DISABLE_REFLECTION_EMIT
658 /*field_image is the image to which the eventual custom mods have been encoded against*/
660 mono_dynimage_encode_fieldref_signature (MonoDynamicImage
*assembly
, MonoImage
*field_image
, MonoType
*type
)
662 MONO_REQ_GC_NEUTRAL_MODE
;
665 guint32 idx
, i
, token
;
670 sigbuffer_init (&buf
, 32);
672 sigbuffer_add_value (&buf
, 0x06);
673 /* encode custom attributes before the type */
674 if (type
->has_cmods
) {
675 MonoCustomModContainer
*cmods
= mono_type_get_cmods (type
);
676 for (i
= 0; i
< cmods
->count
; ++i
) {
679 MonoClass
*klass
= mono_class_get_checked (field_image
, cmods
->modifiers
[i
].token
, error
);
680 g_assert (mono_error_ok (error
)); /* FIXME don't swallow the error */
682 token
= mono_image_typedef_or_ref (assembly
, m_class_get_byval_arg (klass
));
684 token
= cmods
->modifiers
[i
].token
;
687 if (cmods
->modifiers
[i
].required
)
688 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_REQD
);
690 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_OPT
);
692 sigbuffer_add_value (&buf
, token
);
695 encode_type (assembly
, type
, &buf
);
696 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
697 sigbuffer_free (&buf
);
700 #else /* DISABLE_REFLECTION_EMIT */
702 mono_dynimage_encode_fieldref_signature (MonoDynamicImage
*assembly
, MonoImage
*field_image
, MonoType
*type
)
704 g_assert_not_reached ();
707 #endif /* DISABLE_REFLECTION_EMIT */
710 create_typespec (MonoDynamicImage
*assembly
, MonoType
*type
)
712 MONO_REQ_GC_NEUTRAL_MODE
;
714 MonoDynamicTable
*table
;
719 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, type
))))
722 sigbuffer_init (&buf
, 32);
723 switch (type
->type
) {
724 case MONO_TYPE_FNPTR
:
726 case MONO_TYPE_SZARRAY
:
727 case MONO_TYPE_ARRAY
:
730 case MONO_TYPE_GENERICINST
:
731 encode_type (assembly
, type
, &buf
);
733 case MONO_TYPE_CLASS
:
734 case MONO_TYPE_VALUETYPE
: {
735 MonoClass
*k
= mono_class_from_mono_type (type
);
736 if (!k
|| !mono_class_is_gtd (k
)) {
737 sigbuffer_free (&buf
);
740 encode_type (assembly
, type
, &buf
);
744 sigbuffer_free (&buf
);
748 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
749 if (assembly
->save
) {
750 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
751 alloc_table (table
, table
->rows
+ 1);
752 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
753 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
755 sigbuffer_free (&buf
);
757 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
758 g_hash_table_insert (assembly
->typespec
, type
, GUINT_TO_POINTER(token
));
764 mono_dynimage_encode_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
)
766 MONO_REQ_GC_UNSAFE_MODE
;
767 HANDLE_FUNCTION_ENTER ();
769 MonoDynamicTable
*table
;
771 guint32 token
, scope
, enclosing
;
774 /* if the type requires a typespec, we must try that first*/
775 if (try_typespec
&& (token
= create_typespec (assembly
, type
)))
777 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typeref
, type
));
780 klass
= mono_class_from_mono_type (type
);
782 MonoReflectionTypeBuilderHandle tb
= MONO_HANDLE_CAST (MonoReflectionTypeBuilder
, mono_class_get_ref_info (klass
));
784 * If it's in the same module and not a generic type parameter:
786 if ((m_class_get_image (klass
) == &assembly
->image
) && (type
->type
!= MONO_TYPE_VAR
) &&
787 (type
->type
!= MONO_TYPE_MVAR
)) {
788 token
= MONO_TYPEDEFORREF_TYPEDEF
| (MONO_HANDLE_GETVAL (tb
, table_idx
) << MONO_TYPEDEFORREF_BITS
);
789 /* This function is called multiple times from sre and sre-save, so same object is okay */
790 mono_dynamic_image_register_token (assembly
, token
, MONO_HANDLE_CAST (MonoObject
, tb
), MONO_DYN_IMAGE_TOK_SAME_OK
);
794 if (m_class_get_nested_in (klass
)) {
795 enclosing
= mono_dynimage_encode_typedef_or_ref_full (assembly
, m_class_get_byval_arg (m_class_get_nested_in (klass
)), FALSE
);
796 /* get the typeref idx of the enclosing type */
797 enclosing
>>= MONO_TYPEDEFORREF_BITS
;
798 scope
= (enclosing
<< MONO_RESOLUTION_SCOPE_BITS
) | MONO_RESOLUTION_SCOPE_TYPEREF
;
800 scope
= mono_reflection_resolution_scope_from_image (assembly
, m_class_get_image (klass
));
802 table
= &assembly
->tables
[MONO_TABLE_TYPEREF
];
803 if (assembly
->save
) {
804 alloc_table (table
, table
->rows
+ 1);
805 values
= table
->values
+ table
->next_idx
* MONO_TYPEREF_SIZE
;
806 values
[MONO_TYPEREF_SCOPE
] = scope
;
807 values
[MONO_TYPEREF_NAME
] = mono_dynstream_insert_string (&assembly
->sheap
, m_class_get_name (klass
));
808 values
[MONO_TYPEREF_NAMESPACE
] = mono_dynstream_insert_string (&assembly
->sheap
, m_class_get_name_space (klass
));
810 token
= MONO_TYPEDEFORREF_TYPEREF
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
); /* typeref */
811 g_hash_table_insert (assembly
->typeref
, type
, GUINT_TO_POINTER(token
));
815 if (!MONO_HANDLE_IS_NULL (tb
)) {
816 /* This function is called multiple times from sre and sre-save, so same object is okay */
817 mono_dynamic_image_register_token (assembly
, token
, MONO_HANDLE_CAST (MonoObject
, tb
), MONO_DYN_IMAGE_TOK_SAME_OK
);
821 HANDLE_FUNCTION_RETURN_VAL (token
);
825 * Despite the name, we handle also TypeSpec (with the above helper).
828 mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
)
830 return mono_dynimage_encode_typedef_or_ref_full (assembly
, type
, TRUE
);
834 mono_dynimage_encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
)
838 guint32 nparams
= context
->method_inst
->type_argc
;
844 sigbuffer_init (&buf
, 32);
846 * FIXME: vararg, explicit_this, differenc call_conv values...
848 sigbuffer_add_value (&buf
, 0xa); /* FIXME FIXME FIXME */
849 sigbuffer_add_value (&buf
, nparams
);
851 for (i
= 0; i
< nparams
; i
++)
852 encode_type (assembly
, context
->method_inst
->type_argv
[i
], &buf
);
854 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
855 sigbuffer_free (&buf
);
859 #ifndef DISABLE_REFLECTION_EMIT
861 encode_sighelper_arg (MonoDynamicImage
*assembly
, int i
, MonoArrayHandle helper_arguments
, MonoArrayHandle helper_modreqs
, MonoArrayHandle helper_modopts
, SigBuffer
* buf
, MonoError
*error
)
863 HANDLE_FUNCTION_ENTER();
865 MonoArrayHandle modreqs
= MONO_HANDLE_NEW (MonoArray
, NULL
);
866 MonoArrayHandle modopts
= MONO_HANDLE_NEW (MonoArray
, NULL
);
868 if (!MONO_HANDLE_IS_NULL (helper_modreqs
) && (i
< mono_array_handle_length (helper_modreqs
)))
869 MONO_HANDLE_ARRAY_GETREF (modreqs
, helper_modreqs
, i
);
870 if (!MONO_HANDLE_IS_NULL (helper_modopts
) && (i
< mono_array_handle_length (helper_modopts
)))
871 MONO_HANDLE_ARRAY_GETREF (modopts
, helper_modopts
, i
);
873 encode_custom_modifiers (assembly
, modreqs
, modopts
, buf
, error
);
874 goto_if_nok (error
, leave
);
875 MonoReflectionTypeHandle pt
= MONO_HANDLE_NEW (MonoReflectionType
, NULL
);
876 MONO_HANDLE_ARRAY_GETREF (pt
, helper_arguments
, i
);
877 encode_reflection_type (assembly
, pt
, buf
, error
);
878 goto_if_nok (error
, leave
);
880 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
884 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage
*assembly
, MonoReflectionSigHelperHandle helper
, MonoError
*error
)
895 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
896 g_assert (MONO_HANDLE_GETVAL (helper
, type
) == 2);
898 MonoArrayHandle arguments
= MONO_HANDLE_NEW_GET (MonoArray
, helper
, arguments
);
899 if (!MONO_HANDLE_IS_NULL (arguments
))
900 nargs
= mono_array_handle_length (arguments
);
904 sigbuffer_init (&buf
, 32);
906 /* Encode calling convention */
907 /* Change Any to Standard */
908 if ((MONO_HANDLE_GETVAL (helper
, call_conv
) & 0x03) == 0x03)
909 MONO_HANDLE_SETVAL (helper
, call_conv
, guint32
, 0x01);
910 /* explicit_this implies has_this */
911 if (MONO_HANDLE_GETVAL (helper
, call_conv
) & 0x40)
912 MONO_HANDLE_SETVAL (helper
, call_conv
, guint32
, MONO_HANDLE_GETVAL (helper
, call_conv
) & 0x20);
914 if (MONO_HANDLE_GETVAL (helper
, call_conv
) == 0) { /* Unmanaged */
915 idx
= MONO_HANDLE_GETVAL (helper
, unmanaged_call_conv
) - 1;
918 idx
= MONO_HANDLE_GETVAL (helper
, call_conv
) & 0x60; /* has_this + explicit_this */
919 if (MONO_HANDLE_GETVAL (helper
, call_conv
) & 0x02) /* varargs */
923 sigbuffer_add_byte (&buf
, idx
);
924 sigbuffer_add_value (&buf
, nargs
);
925 encode_reflection_type (assembly
, MONO_HANDLE_NEW_GET (MonoReflectionType
, helper
, return_type
), &buf
, error
);
926 goto_if_nok (error
, fail
);
927 MonoArrayHandle modreqs
= MONO_HANDLE_NEW_GET (MonoArray
, helper
, modreqs
);
928 MonoArrayHandle modopts
= MONO_HANDLE_NEW_GET (MonoArray
, helper
, modopts
);
929 for (i
= 0; i
< nargs
; ++i
) {
930 if (!encode_sighelper_arg (assembly
, i
, arguments
, modreqs
, modopts
, &buf
, error
))
933 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
934 sigbuffer_free (&buf
);
938 sigbuffer_free (&buf
);
941 #else /* DISABLE_REFLECTION_EMIT */
943 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage
*assembly
, MonoReflectionSigHelperHandle helper
, MonoError
*error
)
945 g_assert_not_reached ();
948 #endif /* DISABLE_REFLECTION_EMIT */
951 encode_reflection_types (MonoDynamicImage
*assembly
, MonoArrayHandle sig_arguments
, int i
, SigBuffer
*buf
, MonoError
*error
)
953 HANDLE_FUNCTION_ENTER ();
955 MonoReflectionTypeHandle type
= MONO_HANDLE_NEW (MonoReflectionType
, NULL
);
956 MONO_HANDLE_ARRAY_GETREF (type
, sig_arguments
, i
);
957 encode_reflection_type (assembly
, type
, buf
, error
);
958 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
961 static MonoArrayHandle
962 reflection_sighelper_get_signature_local (MonoReflectionSigHelperHandle sig
, MonoError
*error
)
964 MonoReflectionModuleBuilderHandle module
= MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder
, sig
, module
);
965 MonoDynamicImage
*assembly
= MONO_HANDLE_IS_NULL (module
) ? NULL
: MONO_HANDLE_GETVAL (module
, dynamic_image
);
966 MonoArrayHandle sig_arguments
= MONO_HANDLE_NEW_GET (MonoArray
, sig
, arguments
);
967 guint32 na
= MONO_HANDLE_IS_NULL (sig_arguments
) ? 0 : mono_array_handle_length (sig_arguments
);
973 sigbuffer_init (&buf
, 32);
975 sigbuffer_add_value (&buf
, 0x07);
976 sigbuffer_add_value (&buf
, na
);
977 if (assembly
!= NULL
){
978 for (i
= 0; i
< na
; ++i
) {
979 if (!encode_reflection_types (assembly
, sig_arguments
, i
, &buf
, error
))
984 buflen
= buf
.p
- buf
.buf
;
985 MonoArrayHandle result
= mono_array_new_handle (mono_domain_get (), mono_defaults
.byte_class
, buflen
, error
);
986 goto_if_nok (error
, fail
);
988 void *base
= MONO_ARRAY_HANDLE_PIN (result
, char, 0, &gchandle
);
989 memcpy (base
, buf
.buf
, buflen
);
990 sigbuffer_free (&buf
);
991 mono_gchandle_free (gchandle
);
994 sigbuffer_free (&buf
);
995 return MONO_HANDLE_CAST (MonoArray
, NULL_HANDLE
);
998 static MonoArrayHandle
999 reflection_sighelper_get_signature_field (MonoReflectionSigHelperHandle sig
, MonoError
*error
)
1001 MonoReflectionModuleBuilderHandle module
= MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder
, sig
, module
);
1002 MonoDynamicImage
*assembly
= MONO_HANDLE_GETVAL (module
, dynamic_image
);
1003 MonoArrayHandle sig_arguments
= MONO_HANDLE_NEW_GET (MonoArray
, sig
, arguments
);
1004 guint32 na
= MONO_HANDLE_IS_NULL (sig_arguments
) ? 0 : mono_array_handle_length (sig_arguments
);
1010 sigbuffer_init (&buf
, 32);
1012 sigbuffer_add_value (&buf
, 0x06);
1013 for (i
= 0; i
< na
; ++i
) {
1014 if (! encode_reflection_types (assembly
, sig_arguments
, i
, &buf
, error
))
1018 buflen
= buf
.p
- buf
.buf
;
1019 MonoArrayHandle result
= mono_array_new_handle (mono_domain_get (), mono_defaults
.byte_class
, buflen
, error
);
1020 goto_if_nok (error
, fail
);
1022 void *base
= MONO_ARRAY_HANDLE_PIN (result
, char, 0, &gchandle
);
1023 memcpy (base
, buf
.buf
, buflen
);
1024 sigbuffer_free (&buf
);
1025 mono_gchandle_free (gchandle
);
1029 sigbuffer_free (&buf
);
1030 return MONO_HANDLE_CAST (MonoArray
, NULL_HANDLE
);
1034 type_get_fully_qualified_name (MonoType
*type
)
1036 MONO_REQ_GC_NEUTRAL_MODE
;
1038 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1041 #ifndef DISABLE_REFLECTION_EMIT_SAVE
1043 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
, MonoError
*error
)
1045 MONO_REQ_GC_UNSAFE_MODE
;
1053 sigbuffer_init (&buf
, 32);
1055 sigbuffer_add_value (&buf
, minfo
->type
);
1057 switch (minfo
->type
) {
1058 case MONO_NATIVE_BYVALTSTR
:
1059 case MONO_NATIVE_BYVALARRAY
:
1060 sigbuffer_add_value (&buf
, minfo
->count
);
1062 case MONO_NATIVE_LPARRAY
:
1063 if (minfo
->eltype
|| minfo
->has_size
) {
1064 sigbuffer_add_value (&buf
, minfo
->eltype
);
1065 if (minfo
->has_size
) {
1066 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? minfo
->param_num
: 0);
1067 sigbuffer_add_value (&buf
, minfo
->count
!= -1? minfo
->count
: 0);
1069 /* LAMESPEC: ElemMult is undocumented */
1070 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? 1: 0);
1074 case MONO_NATIVE_SAFEARRAY
:
1076 sigbuffer_add_value (&buf
, minfo
->eltype
);
1078 case MONO_NATIVE_CUSTOM
:
1080 str
= mono_string_to_utf8_checked (minfo
->guid
, error
);
1081 if (!is_ok (error
)) {
1082 sigbuffer_free (&buf
);
1086 sigbuffer_add_value (&buf
, len
);
1087 sigbuffer_add_mem (&buf
, str
, len
);
1090 sigbuffer_add_value (&buf
, 0);
1092 /* native type name */
1093 sigbuffer_add_value (&buf
, 0);
1094 /* custom marshaler type name */
1095 if (minfo
->marshaltype
|| minfo
->marshaltyperef
) {
1096 if (minfo
->marshaltyperef
) {
1097 MonoType
*marshaltype
= mono_reflection_type_get_handle ((MonoReflectionType
*)minfo
->marshaltyperef
, error
);
1098 if (!is_ok (error
)) {
1099 sigbuffer_free (&buf
);
1102 str
= type_get_fully_qualified_name (marshaltype
);
1104 str
= mono_string_to_utf8_checked (minfo
->marshaltype
, error
);
1105 if (!is_ok (error
)) {
1106 sigbuffer_free (&buf
);
1111 sigbuffer_add_value (&buf
, len
);
1112 sigbuffer_add_mem (&buf
, str
, len
);
1115 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1116 sigbuffer_add_value (&buf
, 0);
1118 if (minfo
->mcookie
) {
1119 str
= mono_string_to_utf8_checked (minfo
->mcookie
, error
);
1120 if (!is_ok (error
)) {
1121 sigbuffer_free (&buf
);
1125 sigbuffer_add_value (&buf
, len
);
1126 sigbuffer_add_mem (&buf
, str
, len
);
1129 sigbuffer_add_value (&buf
, 0);
1135 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1136 sigbuffer_free (&buf
);
1141 mono_dynimage_save_encode_property_signature (MonoDynamicImage
*assembly
, MonoReflectionPropertyBuilder
*fb
, MonoError
*error
)
1143 MONO_REQ_GC_UNSAFE_MODE
;
1148 guint32 nparams
= 0;
1149 MonoReflectionMethodBuilder
*mb
= fb
->get_method
;
1150 MonoReflectionMethodBuilder
*smb
= fb
->set_method
;
1153 if (mb
&& mb
->parameters
)
1154 nparams
= mono_array_length (mb
->parameters
);
1155 if (!mb
&& smb
&& smb
->parameters
)
1156 nparams
= mono_array_length (smb
->parameters
) - 1;
1157 sigbuffer_init (&buf
, 32);
1158 if (fb
->call_conv
& 0x20)
1159 sigbuffer_add_byte (&buf
, 0x28);
1161 sigbuffer_add_byte (&buf
, 0x08);
1162 sigbuffer_add_value (&buf
, nparams
);
1164 encode_reflection_type_raw (assembly
, (MonoReflectionType
*)mb
->rtype
, &buf
, error
);
1167 for (i
= 0; i
< nparams
; ++i
) {
1168 MonoReflectionType
*pt
= mono_array_get (mb
->parameters
, MonoReflectionType
*, i
);
1169 encode_reflection_type_raw (assembly
, pt
, &buf
, error
);
1173 } else if (smb
&& smb
->parameters
) {
1174 /* the property type is the last param */
1175 encode_reflection_type_raw (assembly
, mono_array_get (smb
->parameters
, MonoReflectionType
*, nparams
), &buf
, error
);
1179 for (i
= 0; i
< nparams
; ++i
) {
1180 MonoReflectionType
*pt
= mono_array_get (smb
->parameters
, MonoReflectionType
*, i
);
1181 encode_reflection_type_raw (assembly
, pt
, &buf
, error
);
1186 encode_reflection_type_raw (assembly
, (MonoReflectionType
*)fb
->type
, &buf
, error
);
1191 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1192 sigbuffer_free (&buf
);
1195 sigbuffer_free (&buf
);
1200 #else /*DISABLE_REFLECTION_EMIT_SAVE*/
1202 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
, MonoError
*error
)
1204 g_assert_not_reached ();
1209 mono_dynimage_save_encode_property_signature (MonoDynamicImage
*assembly
, MonoReflectionPropertyBuilder
*fb
, MonoError
*error
)
1211 g_assert_not_reached ();
1214 #endif /*DISABLE_REFLECTION_EMIT_SAVE*/
1216 #ifndef DISABLE_REFLECTION_EMIT
1218 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelperHandle sig
, MonoError
*error
)
1221 return reflection_sighelper_get_signature_local (sig
, error
);
1225 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelperHandle sig
, MonoError
*error
)
1228 return reflection_sighelper_get_signature_field (sig
, error
);
1230 #else /* DISABLE_REFLECTION_EMIT */
1232 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelperHandle sig
, MonoError
*error
)
1235 g_assert_not_reached ();
1236 return MONO_HANDLE_CAST (MonoArray
, NULL_HANDLE
);
1240 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelperHandle sig
, MonoError
*error
)
1243 g_assert_not_reached ();
1244 return MONO_HANDLE_CAST (MonoArray
, NULL_HANDLE
);
1247 #endif /* DISABLE_REFLECTION_EMIT */