Only set the attached flag when a client attaches (#3490)
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: System.Type icalls and related reflection queries.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
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
10  * Copyright 2016 Microsoft
11  *
12  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
13  */
14 #include <config.h>
15 #include "mono/utils/mono-membar.h"
16 #include "mono/metadata/reflection-internals.h"
17 #include "mono/metadata/tabledefs.h"
18 #include "mono/metadata/metadata-internals.h"
19 #include <mono/metadata/profiler-private.h>
20 #include "mono/metadata/class-internals.h"
21 #include "mono/metadata/gc-internals.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <mono/metadata/reflection-cache.h>
30 #include <mono/metadata/sre-internals.h>
31 #include <stdio.h>
32 #include <glib.h>
33 #include <errno.h>
34 #include <time.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "image.h"
38 #include "cil-coff.h"
39 #include "mono-endian.h"
40 #include <mono/metadata/gc-internals.h>
41 #include <mono/metadata/mempool-internals.h>
42 #include <mono/metadata/security-core-clr.h>
43 #include <mono/metadata/debug-helpers.h>
44 #include <mono/metadata/verify-internals.h>
45 #include <mono/metadata/mono-ptr-array.h>
46 #include <mono/utils/mono-string.h>
47 #include <mono/utils/mono-error-internals.h>
48 #include <mono/utils/checked-build.h>
49
50 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
51 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
52
53 /* Class lazy loading functions */
54 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
55 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
56 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
57 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
58 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
59 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
60 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
61 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
62 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
63 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
64 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
65 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
66 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
67 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
68 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
69 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
70
71 void
72 mono_reflection_init (void)
73 {
74         mono_reflection_emit_init ();
75 }
76
77 /*
78  * mono_class_get_ref_info:
79  *
80  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
81  */
82 gpointer
83 mono_class_get_ref_info (MonoClass *klass)
84 {
85         MONO_REQ_GC_UNSAFE_MODE;
86
87         if (klass->ref_info_handle == 0)
88                 return NULL;
89         else
90                 return mono_gchandle_get_target (klass->ref_info_handle);
91 }
92
93 void
94 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
95 {
96         MONO_REQ_GC_UNSAFE_MODE;
97
98         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
99         g_assert (klass->ref_info_handle != 0);
100 }
101
102 void
103 mono_class_free_ref_info (MonoClass *klass)
104 {
105         MONO_REQ_GC_NEUTRAL_MODE;
106
107         if (klass->ref_info_handle) {
108                 mono_gchandle_free (klass->ref_info_handle);
109                 klass->ref_info_handle = 0;
110         }
111 }
112
113
114 void
115 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
116 {
117         MONO_REQ_GC_NEUTRAL_MODE;
118
119         if (ainfo && !ainfo->cached)
120                 g_free (ainfo);
121 }
122
123
124 gboolean
125 reflected_equal (gconstpointer a, gconstpointer b)
126 {
127         const ReflectedEntry *ea = (const ReflectedEntry *)a;
128         const ReflectedEntry *eb = (const ReflectedEntry *)b;
129
130         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
131 }
132
133 guint
134 reflected_hash (gconstpointer a) {
135         const ReflectedEntry *ea = (const ReflectedEntry *)a;
136         return mono_aligned_addr_hash (ea->item);
137 }
138
139
140 static void
141 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
142 {
143         mono_domain_lock (domain);
144         if (domain->refobject_hash) {
145         ReflectedEntry pe;
146                 gpointer orig_pe, orig_value;
147
148                 pe.item = o;
149                 pe.refclass = klass;
150                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
151                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
152                         FREE_REFENTRY (orig_pe);
153                 }
154         }
155         mono_domain_unlock (domain);
156 }
157
158 #ifdef REFENTRY_REQUIRES_CLEANUP
159 static void
160 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
161 {
162         FREE_REFENTRY (key);
163 }
164 #endif
165
166 void
167 mono_reflection_cleanup_domain (MonoDomain *domain)
168 {
169         if (domain->refobject_hash) {
170 /*let's avoid scanning the whole hashtable if not needed*/
171 #ifdef REFENTRY_REQUIRES_CLEANUP
172                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
173 #endif
174                 mono_g_hash_table_destroy (domain->refobject_hash);
175                 domain->refobject_hash = NULL;
176         }
177 }
178
179
180 /*
181  * mono_assembly_get_object:
182  * @domain: an app domain
183  * @assembly: an assembly
184  *
185  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
186  */
187 MonoReflectionAssembly*
188 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
189 {
190         MonoError error;
191         MonoReflectionAssembly *result;
192         result = mono_assembly_get_object_checked (domain, assembly, &error);
193         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
194         return result;
195 }
196 /*
197  * mono_assembly_get_object_checked:
198  * @domain: an app domain
199  * @assembly: an assembly
200  *
201  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
202  */
203 MonoReflectionAssembly*
204 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
205 {
206         MonoReflectionAssembly *res;
207         
208         mono_error_init (error);
209
210         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
211         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
212         if (!res)
213                 return NULL;
214         res->assembly = assembly;
215
216         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
217 }
218
219
220
221 MonoReflectionModule*   
222 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
223 {
224         MonoError error;
225         MonoReflectionModule *result;
226         result = mono_module_get_object_checked (domain, image, &error);
227         mono_error_cleanup (&error);
228         return result;
229 }
230
231 MonoReflectionModule*
232 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
233 {
234         MonoReflectionModule *res;
235         char* basename;
236         
237         mono_error_init (error);
238         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
239         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
240         if (!res)
241                 return NULL;
242
243         res->image = image;
244         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
245         if (!assm_obj)
246                 return NULL;
247         MONO_OBJECT_SETREF (res, assembly, assm_obj);
248
249         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
250         basename = g_path_get_basename (image->name);
251         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
252         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
253         
254         g_free (basename);
255
256         if (image->assembly->image == image) {
257                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
258         } else {
259                 int i;
260                 res->token = 0;
261                 if (image->assembly->image->modules) {
262                         for (i = 0; i < image->assembly->image->module_count; i++) {
263                                 if (image->assembly->image->modules [i] == image)
264                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
265                         }
266                         g_assert (res->token);
267                 }
268         }
269
270         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
271 }
272
273 MonoReflectionModule*
274 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
275 {
276         MonoError error;
277         MonoReflectionModule *result;
278         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
279         mono_error_cleanup (&error);
280         return result;
281 }
282
283 MonoReflectionModule*
284 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
285 {
286         MonoReflectionModule *res;
287         MonoTableInfo *table;
288         guint32 cols [MONO_FILE_SIZE];
289         const char *name;
290         guint32 i, name_idx;
291         const char *val;
292         
293         mono_error_init (error);
294
295         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
296         if (!res)
297                 return NULL;
298
299         table = &image->tables [MONO_TABLE_FILE];
300         g_assert (table_index < table->rows);
301         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
302
303         res->image = NULL;
304         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
305         if (!assm_obj)
306                 return NULL;
307         MONO_OBJECT_SETREF (res, assembly, assm_obj);
308         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
309
310         /* Check whenever the row has a corresponding row in the moduleref table */
311         table = &image->tables [MONO_TABLE_MODULEREF];
312         for (i = 0; i < table->rows; ++i) {
313                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
314                 val = mono_metadata_string_heap (image, name_idx);
315                 if (strcmp (val, name) == 0)
316                         res->image = image->modules [i];
317         }
318
319         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
320         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
321         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
322         res->is_resource = cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA;
323         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
324
325         return res;
326 }
327
328 static gboolean
329 verify_safe_for_managed_space (MonoType *type)
330 {
331         switch (type->type) {
332 #ifdef DEBUG_HARDER
333         case MONO_TYPE_ARRAY:
334                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
335         case MONO_TYPE_PTR:
336                 return verify_safe_for_managed_space (type->data.type);
337         case MONO_TYPE_SZARRAY:
338                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
339         case MONO_TYPE_GENERICINST: {
340                 MonoGenericInst *inst = type->data.generic_class->inst;
341                 int i;
342                 if (!inst->is_open)
343                         break;
344                 for (i = 0; i < inst->type_argc; ++i)
345                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
346                                 return FALSE;
347                 return TRUE;
348         }
349 #endif
350         case MONO_TYPE_VAR:
351         case MONO_TYPE_MVAR:
352                 return TRUE;
353         default:
354                 return TRUE;
355         }
356 }
357
358 static MonoType*
359 mono_type_normalize (MonoType *type)
360 {
361         int i;
362         MonoGenericClass *gclass;
363         MonoGenericInst *ginst;
364         MonoClass *gtd;
365         MonoGenericContainer *gcontainer;
366         MonoType **argv = NULL;
367         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
368
369         if (type->type != MONO_TYPE_GENERICINST)
370                 return type;
371
372         gclass = type->data.generic_class;
373         ginst = gclass->context.class_inst;
374         if (!ginst->is_open)
375                 return type;
376
377         gtd = gclass->container_class;
378         gcontainer = gtd->generic_container;
379         argv = g_newa (MonoType*, ginst->type_argc);
380
381         for (i = 0; i < ginst->type_argc; ++i) {
382                 MonoType *t = ginst->type_argv [i], *norm;
383                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
384                         is_denorm_gtd = FALSE;
385                 norm = mono_type_normalize (t);
386                 argv [i] = norm;
387                 if (norm != t)
388                         requires_rebind = TRUE;
389         }
390
391         if (is_denorm_gtd)
392                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
393
394         if (requires_rebind) {
395                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
396                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
397         }
398
399         return type;
400 }
401 /*
402  * mono_type_get_object:
403  * @domain: an app domain
404  * @type: a type
405  *
406  * Return an System.MonoType object representing the type @type.
407  */
408 MonoReflectionType*
409 mono_type_get_object (MonoDomain *domain, MonoType *type)
410 {
411         MonoError error;
412         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
413         mono_error_cleanup (&error);
414
415         return ret;
416 }
417
418 MonoReflectionType*
419 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
420 {
421         MonoType *norm_type;
422         MonoReflectionType *res;
423         MonoClass *klass;
424
425         mono_error_init (error);
426
427         klass = mono_class_from_mono_type (type);
428
429         /*we must avoid using @type as it might have come
430          * from a mono_metadata_type_dup and the caller
431          * expects that is can be freed.
432          * Using the right type from 
433          */
434         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
435
436         /* void is very common */
437         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
438                 return (MonoReflectionType*)domain->typeof_void;
439
440         /*
441          * If the vtable of the given class was already created, we can use
442          * the MonoType from there and avoid all locking and hash table lookups.
443          * 
444          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
445          * that the resulting object is different.   
446          */
447         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
448                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
449                 if (vtable && vtable->type)
450                         return (MonoReflectionType *)vtable->type;
451         }
452
453         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
454         mono_domain_lock (domain);
455         if (!domain->type_hash)
456                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
457                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
458         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
459                 mono_domain_unlock (domain);
460                 mono_loader_unlock ();
461                 return res;
462         }
463
464         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
465          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
466          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
467          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
468          * artifact of how generics are encoded and should be transparent to managed code so we
469          * need to weed out this diference when retrieving managed System.Type objects.
470          */
471         norm_type = mono_type_normalize (type);
472         if (norm_type != type) {
473                 res = mono_type_get_object_checked (domain, norm_type, error);
474                 if (!mono_error_ok (error))
475                         return NULL;
476                 mono_g_hash_table_insert (domain->type_hash, type, res);
477                 mono_domain_unlock (domain);
478                 mono_loader_unlock ();
479                 return res;
480         }
481
482         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
483         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
484                 g_assert (0);
485
486         if (!verify_safe_for_managed_space (type)) {
487                 mono_domain_unlock (domain);
488                 mono_loader_unlock ();
489                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
490                 return NULL;
491         }
492
493         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
494                 gboolean is_type_done = TRUE;
495                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
496                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
497                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
498                 */
499                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
500                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
501
502                         if (gparam->owner && gparam->owner->is_method) {
503                                 MonoMethod *method = gparam->owner->owner.method;
504                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
505                                         is_type_done = FALSE;
506                         } else if (gparam->owner && !gparam->owner->is_method) {
507                                 MonoClass *klass = gparam->owner->owner.klass;
508                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
509                                         is_type_done = FALSE;
510                         }
511                 } 
512
513                 /* g_assert_not_reached (); */
514                 /* should this be considered an error condition? */
515                 if (is_type_done && !type->byref) {
516                         mono_domain_unlock (domain);
517                         mono_loader_unlock ();
518                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
519                 }
520         }
521         /* This is stored in vtables/JITted code so it has to be pinned */
522         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
523         if (!mono_error_ok (error))
524                 return NULL;
525
526         res->type = type;
527         mono_g_hash_table_insert (domain->type_hash, type, res);
528
529         if (type->type == MONO_TYPE_VOID)
530                 domain->typeof_void = (MonoObject*)res;
531
532         mono_domain_unlock (domain);
533         mono_loader_unlock ();
534         return res;
535 }
536
537 /*
538  * mono_method_get_object:
539  * @domain: an app domain
540  * @method: a method
541  * @refclass: the reflected type (can be NULL)
542  *
543  * Return an System.Reflection.MonoMethod object representing the method @method.
544  */
545 MonoReflectionMethod*
546 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
547 {
548         MonoError error;
549         MonoReflectionMethod *ret = NULL;
550         ret = mono_method_get_object_checked (domain, method, refclass, &error);
551         mono_error_cleanup (&error);
552         return ret;
553 }
554
555 /*
556  * mono_method_get_object_checked:
557  * @domain: an app domain
558  * @method: a method
559  * @refclass: the reflected type (can be NULL)
560  * @error: set on error.
561  *
562  * Return an System.Reflection.MonoMethod object representing the method @method.
563  * Returns NULL and sets @error on error.
564  */
565 MonoReflectionMethod*
566 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
567 {
568         /*
569          * We use the same C representation for methods and constructors, but the type 
570          * name in C# is different.
571          */
572         MonoReflectionType *rt;
573         MonoClass *klass;
574         MonoReflectionMethod *ret;
575
576         mono_error_init (error);
577
578         if (method->is_inflated) {
579                 MonoReflectionGenericMethod *gret;
580
581                 if (!refclass)
582                         refclass = method->klass;
583                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
584                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
585                         klass = mono_class_get_mono_generic_cmethod_class ();
586                 } else {
587                         klass = mono_class_get_mono_generic_method_class ();
588                 }
589                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
590                 if (!mono_error_ok (error))
591                         goto leave;
592                 gret->method.method = method;
593
594                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
595
596                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
597                 if (!mono_error_ok (error))
598                     goto leave;
599
600                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
601
602                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
603         }
604
605         if (!refclass)
606                 refclass = method->klass;
607
608         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
609         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
610                 klass = mono_class_get_mono_cmethod_class ();
611         }
612         else {
613                 klass = mono_class_get_mono_method_class ();
614         }
615         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
616         if (!mono_error_ok (error))
617                 goto leave;
618         ret->method = method;
619
620         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
621         if (!mono_error_ok (error))
622                 goto leave;
623
624         MONO_OBJECT_SETREF (ret, reftype, rt);
625
626         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
627
628 leave:
629         g_assert (!mono_error_ok (error));
630         return NULL;
631 }
632
633 /*
634  * mono_method_clear_object:
635  *
636  *   Clear the cached reflection objects for the dynamic method METHOD.
637  */
638 void
639 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
640 {
641         MonoClass *klass;
642         g_assert (method_is_dynamic (method));
643
644         klass = method->klass;
645         while (klass) {
646                 clear_cached_object (domain, method, klass);
647                 klass = klass->parent;
648         }
649         /* Added by mono_param_get_objects () */
650         clear_cached_object (domain, &(method->signature), NULL);
651         klass = method->klass;
652         while (klass) {
653                 clear_cached_object (domain, &(method->signature), klass);
654                 klass = klass->parent;
655         }
656 }
657
658 /*
659  * mono_field_get_object:
660  * @domain: an app domain
661  * @klass: a type
662  * @field: a field
663  *
664  * Return an System.Reflection.MonoField object representing the field @field
665  * in class @klass.
666  */
667 MonoReflectionField*
668 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
669 {
670         MonoError error;
671         MonoReflectionField *result;
672         result = mono_field_get_object_checked (domain, klass, field, &error);
673         mono_error_cleanup (&error);
674         return result;
675 }
676
677 /*
678  * mono_field_get_object_checked:
679  * @domain: an app domain
680  * @klass: a type
681  * @field: a field
682  * @error: set on error
683  *
684  * Return an System.Reflection.MonoField object representing the field @field
685  * in class @klass. On error, returns NULL and sets @error.
686  */
687 MonoReflectionField*
688 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
689 {
690         MonoReflectionType *rt;
691         MonoReflectionField *res;
692
693         mono_error_init (error);
694
695         CHECK_OBJECT (MonoReflectionField *, field, klass);
696         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
697         if (!res)
698                 return NULL;
699         res->klass = klass;
700         res->field = field;
701         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
702
703         if (field->type) {
704                 rt = mono_type_get_object_checked (domain, field->type, error);
705                 if (!mono_error_ok (error))
706                         return NULL;
707
708                 MONO_OBJECT_SETREF (res, type, rt);
709         }
710         res->attrs = mono_field_get_flags (field);
711         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
712 }
713
714 /*
715  * mono_property_get_object:
716  * @domain: an app domain
717  * @klass: a type
718  * @property: a property
719  *
720  * Return an System.Reflection.MonoProperty object representing the property @property
721  * in class @klass.
722  */
723 MonoReflectionProperty*
724 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
725 {
726         MonoError error;
727         MonoReflectionProperty *result;
728         result = mono_property_get_object_checked (domain, klass, property, &error);
729         mono_error_cleanup (&error);
730         return result;
731 }
732
733 /**
734  * mono_property_get_object:
735  * @domain: an app domain
736  * @klass: a type
737  * @property: a property
738  * @error: set on error
739  *
740  * Return an System.Reflection.MonoProperty object representing the property @property
741  * in class @klass.  On error returns NULL and sets @error.
742  */
743 MonoReflectionProperty*
744 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
745 {
746         MonoReflectionProperty *res;
747
748         mono_error_init (error);
749
750         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
751         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
752         if (!res)
753                 return NULL;
754         res->klass = klass;
755         res->property = property;
756         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
757 }
758
759 /*
760  * mono_event_get_object:
761  * @domain: an app domain
762  * @klass: a type
763  * @event: a event
764  *
765  * Return an System.Reflection.MonoEvent object representing the event @event
766  * in class @klass.
767  */
768 MonoReflectionEvent*
769 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
770 {
771         MonoError error;
772         MonoReflectionEvent *result;
773         result = mono_event_get_object_checked (domain, klass, event, &error);
774         mono_error_cleanup (&error);
775         return result;
776 }
777
778 /**
779  * mono_event_get_object_checked:
780  * @domain: an app domain
781  * @klass: a type
782  * @event: a event
783  * @error: set on error
784  *
785  * Return an System.Reflection.MonoEvent object representing the event @event
786  * in class @klass. On failure sets @error and returns NULL
787  */
788 MonoReflectionEvent*
789 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
790 {
791         MonoReflectionEvent *res;
792         MonoReflectionMonoEvent *mono_event;
793
794         mono_error_init (error);
795         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
796         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
797         if (!mono_event)
798                 return NULL;
799         mono_event->klass = klass;
800         mono_event->event = event;
801         res = (MonoReflectionEvent*)mono_event;
802         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
803 }
804
805 /**
806  * mono_get_reflection_missing_object:
807  * @domain: Domain where the object lives
808  *
809  * Returns the System.Reflection.Missing.Value singleton object
810  * (of type System.Reflection.Missing).
811  *
812  * Used as the value for ParameterInfo.DefaultValue when Optional
813  * is present
814  */
815 static MonoObject *
816 mono_get_reflection_missing_object (MonoDomain *domain)
817 {
818         MonoError error;
819         MonoObject *obj;
820         static MonoClassField *missing_value_field = NULL;
821         
822         if (!missing_value_field) {
823                 MonoClass *missing_klass;
824                 missing_klass = mono_class_get_missing_class ();
825                 mono_class_init (missing_klass);
826                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
827                 g_assert (missing_value_field);
828         }
829         obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
830         mono_error_assert_ok (&error);
831         return obj;
832 }
833
834 static MonoObject*
835 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
836 {
837         if (!*dbnull)
838                 *dbnull = mono_get_dbnull_object (domain);
839         return *dbnull;
840 }
841
842 static MonoObject*
843 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
844 {
845         if (!*reflection_missing)
846                 *reflection_missing = mono_get_reflection_missing_object (domain);
847         return *reflection_missing;
848 }
849
850 /*
851  * mono_param_get_objects:
852  * @domain: an app domain
853  * @method: a method
854  *
855  * Return an System.Reflection.ParameterInfo array object representing the parameters
856  * in the method @method.
857  */
858 MonoArray*
859 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
860 {
861         static MonoClass *System_Reflection_ParameterInfo;
862         static MonoClass *System_Reflection_ParameterInfo_array;
863         MonoArray *res = NULL;
864         MonoReflectionMethod *member = NULL;
865         MonoReflectionParameter *param = NULL;
866         char **names = NULL, **blobs = NULL;
867         guint32 *types = NULL;
868         MonoType *type = NULL;
869         MonoObject *dbnull = NULL;
870         MonoObject *missing = NULL;
871         MonoMarshalSpec **mspecs = NULL;
872         MonoMethodSignature *sig = NULL;
873         MonoVTable *pinfo_vtable;
874         MonoReflectionType *rt;
875         int i;
876
877         mono_error_init (error);
878         
879         if (!System_Reflection_ParameterInfo_array) {
880                 MonoClass *klass;
881
882                 klass = mono_class_get_mono_parameter_info_class ();
883
884                 mono_memory_barrier ();
885                 System_Reflection_ParameterInfo = klass; 
886
887         
888                 klass = mono_array_class_get (klass, 1);
889                 mono_memory_barrier ();
890                 System_Reflection_ParameterInfo_array = klass;
891         }
892
893         sig = mono_method_signature_checked (method, error);
894         if (!mono_error_ok (error))
895                 goto leave;
896
897         if (!sig->param_count) {
898                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
899                 if (!res)
900                         goto leave;
901
902                 return res;
903         }
904
905         /* Note: the cache is based on the address of the signature into the method
906          * since we already cache MethodInfos with the method as keys.
907          */
908         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
909
910         member = mono_method_get_object_checked (domain, method, refclass, error);
911         if (!member)
912                 goto leave;
913         names = g_new (char *, sig->param_count);
914         mono_method_get_param_names (method, (const char **) names);
915
916         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
917         mono_method_get_marshal_info (method, mspecs);
918
919         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
920         if (!res)
921                 goto leave;
922
923         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
924         for (i = 0; i < sig->param_count; ++i) {
925                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
926                 if (!param)
927                         goto leave;
928
929                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
930                 if (!rt)
931                         goto leave;
932
933                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
934
935                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
936
937                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
938
939                 param->PositionImpl = i;
940                 param->AttrsImpl = sig->params [i]->attrs;
941
942                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
943                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
944                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
945                         else
946                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
947                 } else {
948
949                         if (!blobs) {
950                                 blobs = g_new0 (char *, sig->param_count);
951                                 types = g_new0 (guint32, sig->param_count);
952                                 get_default_param_value_blobs (method, blobs, types); 
953                         }
954
955                         /* Build MonoType for the type from the Constant Table */
956                         if (!type)
957                                 type = g_new0 (MonoType, 1);
958                         type->type = (MonoTypeEnum)types [i];
959                         type->data.klass = NULL;
960                         if (types [i] == MONO_TYPE_CLASS)
961                                 type->data.klass = mono_defaults.object_class;
962                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
963                                 /* For enums, types [i] contains the base type */
964
965                                         type->type = MONO_TYPE_VALUETYPE;
966                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
967                         } else
968                                 type->data.klass = mono_class_from_mono_type (type);
969
970                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
971                         if (!is_ok (error))
972                                 goto leave;
973                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
974
975                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
976                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
977                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
978                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
979                                 else
980                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
981                         }
982                         
983                 }
984
985                 if (mspecs [i + 1]) {
986                         MonoReflectionMarshalAsAttribute* mobj;
987                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
988                         if (!mobj)
989                                 goto leave;
990                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
991                 }
992                 
993                 mono_array_setref (res, i, param);
994         }
995
996 leave:
997         g_free (names);
998         g_free (blobs);
999         g_free (types);
1000         g_free (type);
1001
1002         if (sig) {
1003                 for (i = sig->param_count; i >= 0; i--) {
1004                         if (mspecs [i])
1005                                 mono_metadata_free_marshal_spec (mspecs [i]);
1006                 }
1007         }
1008         g_free (mspecs);
1009
1010         if (!is_ok (error))
1011                 return NULL;
1012         
1013         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
1014 }
1015
1016 MonoArray*
1017 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
1018 {
1019         MonoError error;
1020         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
1021         mono_error_assert_ok (&error);
1022         return result;
1023 }
1024
1025 /*
1026  * mono_method_body_get_object:
1027  * @domain: an app domain
1028  * @method: a method
1029  *
1030  * Return an System.Reflection.MethodBody object representing the method @method.
1031  */
1032 MonoReflectionMethodBody*
1033 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
1034 {
1035         MonoError error;
1036         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
1037         mono_error_cleanup (&error);
1038         return result;
1039 }
1040
1041 /**
1042  * mono_method_body_get_object_checked:
1043  * @domain: an app domain
1044  * @method: a method
1045  * @error: set on error
1046  *
1047  * Return an System.Reflection.MethodBody object representing the
1048  * method @method.  On failure, returns NULL and sets @error.
1049  */
1050 MonoReflectionMethodBody*
1051 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
1052 {
1053         MonoReflectionMethodBody *ret;
1054         MonoMethodHeader *header;
1055         MonoImage *image;
1056         MonoReflectionType *rt;
1057         guint32 method_rva, local_var_sig_token;
1058         char *ptr;
1059         unsigned char format, flags;
1060         int i;
1061
1062         mono_error_init (error);
1063
1064         /* for compatibility with .net */
1065         if (method_is_dynamic (method)) {
1066                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
1067                 return NULL;
1068         }
1069
1070         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
1071
1072         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
1073                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
1074             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
1075                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
1076             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
1077                 return NULL;
1078
1079         image = method->klass->image;
1080         header = mono_method_get_header_checked (method, error);
1081         return_val_if_nok (error, NULL);
1082
1083         if (!image_is_dynamic (image)) {
1084                 /* Obtain local vars signature token */
1085                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
1086                 ptr = mono_image_rva_map (image, method_rva);
1087                 flags = *(const unsigned char *) ptr;
1088                 format = flags & METHOD_HEADER_FORMAT_MASK;
1089                 switch (format){
1090                 case METHOD_HEADER_TINY_FORMAT:
1091                         local_var_sig_token = 0;
1092                         break;
1093                 case METHOD_HEADER_FAT_FORMAT:
1094                         ptr += 2;
1095                         ptr += 2;
1096                         ptr += 4;
1097                         local_var_sig_token = read32 (ptr);
1098                         break;
1099                 default:
1100                         g_assert_not_reached ();
1101                 }
1102         } else
1103                 local_var_sig_token = 0; //FIXME
1104
1105         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
1106         if (!is_ok (error))
1107                 goto fail;
1108
1109         ret->init_locals = header->init_locals;
1110         ret->max_stack = header->max_stack;
1111         ret->local_var_sig_token = local_var_sig_token;
1112         MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
1113         if (!is_ok (error))
1114                 goto fail;
1115         MONO_OBJECT_SETREF (ret, il, il_arr);
1116         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
1117
1118         /* Locals */
1119         MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
1120         if (!is_ok (error))
1121                 goto fail;
1122         MONO_OBJECT_SETREF (ret, locals, locals_arr);
1123         for (i = 0; i < header->num_locals; ++i) {
1124                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
1125                 if (!is_ok (error))
1126                         goto fail;
1127
1128                 rt = mono_type_get_object_checked (domain, header->locals [i], error);
1129                 if (!is_ok (error))
1130                         goto fail;
1131
1132                 MONO_OBJECT_SETREF (info, local_type, rt);
1133
1134                 info->is_pinned = header->locals [i]->pinned;
1135                 info->local_index = i;
1136                 mono_array_setref (ret->locals, i, info);
1137         }
1138
1139         /* Exceptions */
1140         MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
1141         if (!is_ok (error))
1142                 goto fail;
1143         MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
1144         for (i = 0; i < header->num_clauses; ++i) {
1145                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
1146                 if (!is_ok (error))
1147                         goto fail;
1148                 MonoExceptionClause *clause = &header->clauses [i];
1149
1150                 info->flags = clause->flags;
1151                 info->try_offset = clause->try_offset;
1152                 info->try_length = clause->try_len;
1153                 info->handler_offset = clause->handler_offset;
1154                 info->handler_length = clause->handler_len;
1155                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
1156                         info->filter_offset = clause->data.filter_offset;
1157                 else if (clause->data.catch_class) {
1158                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
1159                         if (!is_ok (error))
1160                                 goto fail;
1161
1162                         MONO_OBJECT_SETREF (info, catch_type, rt);
1163                 }
1164
1165                 mono_array_setref (ret->clauses, i, info);
1166         }
1167
1168         mono_metadata_free_mh (header);
1169         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
1170         return ret;
1171
1172 fail:
1173         mono_metadata_free_mh (header);
1174         return NULL;
1175 }
1176
1177 /**
1178  * mono_get_dbnull_object:
1179  * @domain: Domain where the object lives
1180  *
1181  * Returns the System.DBNull.Value singleton object
1182  *
1183  * Used as the value for ParameterInfo.DefaultValue 
1184  */
1185 MonoObject *
1186 mono_get_dbnull_object (MonoDomain *domain)
1187 {
1188         MonoError error;
1189         MonoObject *obj;
1190         static MonoClassField *dbnull_value_field = NULL;
1191         
1192         if (!dbnull_value_field) {
1193                 MonoClass *dbnull_klass;
1194                 dbnull_klass = mono_class_get_dbnull_class ();
1195                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
1196                 g_assert (dbnull_value_field);
1197         }
1198         obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
1199         mono_error_assert_ok (&error);
1200         return obj;
1201 }
1202
1203 static void
1204 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
1205 {
1206         guint32 param_index, i, lastp, crow = 0;
1207         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
1208         gint32 idx;
1209
1210         MonoClass *klass = method->klass;
1211         MonoImage *image = klass->image;
1212         MonoMethodSignature *methodsig = mono_method_signature (method);
1213
1214         MonoTableInfo *constt;
1215         MonoTableInfo *methodt;
1216         MonoTableInfo *paramt;
1217
1218         if (!methodsig->param_count)
1219                 return;
1220
1221         mono_class_init (klass);
1222
1223         if (image_is_dynamic (klass->image)) {
1224                 MonoReflectionMethodAux *aux;
1225                 if (method->is_inflated)
1226                         method = ((MonoMethodInflated*)method)->declaring;
1227                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
1228                 if (aux && aux->param_defaults) {
1229                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
1230                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
1231                 }
1232                 return;
1233         }
1234
1235         methodt = &klass->image->tables [MONO_TABLE_METHOD];
1236         paramt = &klass->image->tables [MONO_TABLE_PARAM];
1237         constt = &image->tables [MONO_TABLE_CONSTANT];
1238
1239         idx = mono_method_get_index (method) - 1;
1240         g_assert (idx != -1);
1241
1242         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
1243         if (idx + 1 < methodt->rows)
1244                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
1245         else
1246                 lastp = paramt->rows + 1;
1247
1248         for (i = param_index; i < lastp; ++i) {
1249                 guint32 paramseq;
1250
1251                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
1252                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
1253
1254                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
1255                         continue;
1256
1257                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
1258                 if (!crow) {
1259                         continue;
1260                 }
1261         
1262                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
1263                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
1264                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
1265         }
1266
1267         return;
1268 }
1269
1270 MonoObject *
1271 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
1272 {
1273         void *retval;
1274         MonoClass *klass;
1275         MonoObject *object;
1276         MonoType *basetype = type;
1277
1278         mono_error_init (error);
1279
1280         if (!blob)
1281                 return NULL;
1282         
1283         klass = mono_class_from_mono_type (type);
1284         if (klass->valuetype) {
1285                 object = mono_object_new_checked (domain, klass, error);
1286                 return_val_if_nok (error, NULL);
1287                 retval = ((gchar *) object + sizeof (MonoObject));
1288                 if (klass->enumtype)
1289                         basetype = mono_class_enum_basetype (klass);
1290         } else {
1291                 retval = &object;
1292         }
1293                         
1294         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval, error))
1295                 return object;
1296         else
1297                 return NULL;
1298 }
1299
1300 static int
1301 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
1302         int found_sep;
1303         char *s;
1304         gboolean quoted = FALSE;
1305
1306         memset (assembly, 0, sizeof (MonoAssemblyName));
1307         assembly->culture = "";
1308         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
1309
1310         if (*p == '"') {
1311                 quoted = TRUE;
1312                 p++;
1313         }
1314         assembly->name = p;
1315         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
1316                 p++;
1317         if (quoted) {
1318                 if (*p != '"')
1319                         return 1;
1320                 *p = 0;
1321                 p++;
1322         }
1323         if (*p != ',')
1324                 return 1;
1325         *p = 0;
1326         /* Remove trailing whitespace */
1327         s = p - 1;
1328         while (*s && g_ascii_isspace (*s))
1329                 *s-- = 0;
1330         p ++;
1331         while (g_ascii_isspace (*p))
1332                 p++;
1333         while (*p) {
1334                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
1335                         p += 8;
1336                         assembly->major = strtoul (p, &s, 10);
1337                         if (s == p || *s != '.')
1338                                 return 1;
1339                         p = ++s;
1340                         assembly->minor = strtoul (p, &s, 10);
1341                         if (s == p || *s != '.')
1342                                 return 1;
1343                         p = ++s;
1344                         assembly->build = strtoul (p, &s, 10);
1345                         if (s == p || *s != '.')
1346                                 return 1;
1347                         p = ++s;
1348                         assembly->revision = strtoul (p, &s, 10);
1349                         if (s == p)
1350                                 return 1;
1351                         p = s;
1352                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
1353                         p += 8;
1354                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
1355                                 assembly->culture = "";
1356                                 p += 7;
1357                         } else {
1358                                 assembly->culture = p;
1359                                 while (*p && *p != ',') {
1360                                         p++;
1361                                 }
1362                         }
1363                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
1364                         p += 15;
1365                         if (strncmp (p, "null", 4) == 0) {
1366                                 p += 4;
1367                         } else {
1368                                 int len;
1369                                 gchar *start = p;
1370                                 while (*p && *p != ',') {
1371                                         p++;
1372                                 }
1373                                 len = (p - start + 1);
1374                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
1375                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
1376                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
1377                         }
1378                 } else {
1379                         while (*p && *p != ',')
1380                                 p++;
1381                 }
1382                 found_sep = 0;
1383                 while (g_ascii_isspace (*p) || *p == ',') {
1384                         *p++ = 0;
1385                         found_sep = 1;
1386                         continue;
1387                 }
1388                 /* failed */
1389                 if (!found_sep)
1390                         return 1;
1391         }
1392
1393         return 0;
1394 }
1395
1396 /*
1397  * mono_reflection_parse_type:
1398  * @name: type name
1399  *
1400  * Parse a type name as accepted by the GetType () method and output the info
1401  * extracted in the info structure.
1402  * the name param will be mangled, so, make a copy before passing it to this function.
1403  * The fields in info will be valid until the memory pointed to by name is valid.
1404  *
1405  * See also mono_type_get_name () below.
1406  *
1407  * Returns: 0 on parse error.
1408  */
1409 static int
1410 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
1411                              MonoTypeNameParse *info)
1412 {
1413         char *start, *p, *w, *last_point, *startn;
1414         int in_modifiers = 0;
1415         int isbyref = 0, rank = 0, isptr = 0;
1416
1417         start = p = w = name;
1418
1419         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
1420         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
1421         info->name = info->name_space = NULL;
1422         info->nested = NULL;
1423         info->modifiers = NULL;
1424         info->type_arguments = NULL;
1425
1426         /* last_point separates the namespace from the name */
1427         last_point = NULL;
1428         /* Skips spaces */
1429         while (*p == ' ') p++, start++, w++, name++;
1430
1431         while (*p) {
1432                 switch (*p) {
1433                 case '+':
1434                         *p = 0; /* NULL terminate the name */
1435                         startn = p + 1;
1436                         info->nested = g_list_append (info->nested, startn);
1437                         /* we have parsed the nesting namespace + name */
1438                         if (info->name)
1439                                 break;
1440                         if (last_point) {
1441                                 info->name_space = start;
1442                                 *last_point = 0;
1443                                 info->name = last_point + 1;
1444                         } else {
1445                                 info->name_space = (char *)"";
1446                                 info->name = start;
1447                         }
1448                         break;
1449                 case '.':
1450                         last_point = p;
1451                         break;
1452                 case '\\':
1453                         ++p;
1454                         break;
1455                 case '&':
1456                 case '*':
1457                 case '[':
1458                 case ',':
1459                 case ']':
1460                         in_modifiers = 1;
1461                         break;
1462                 default:
1463                         break;
1464                 }
1465                 if (in_modifiers)
1466                         break;
1467                 // *w++ = *p++;
1468                 p++;
1469         }
1470         
1471         if (!info->name) {
1472                 if (last_point) {
1473                         info->name_space = start;
1474                         *last_point = 0;
1475                         info->name = last_point + 1;
1476                 } else {
1477                         info->name_space = (char *)"";
1478                         info->name = start;
1479                 }
1480         }
1481         while (*p) {
1482                 switch (*p) {
1483                 case '&':
1484                         if (isbyref) /* only one level allowed by the spec */
1485                                 return 0;
1486                         isbyref = 1;
1487                         isptr = 0;
1488                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
1489                         *p++ = 0;
1490                         break;
1491                 case '*':
1492                         if (isbyref) /* pointer to ref not okay */
1493                                 return 0;
1494                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
1495                         isptr = 1;
1496                         *p++ = 0;
1497                         break;
1498                 case '[':
1499                         if (isbyref) /* array of ref and generic ref are not okay */
1500                                 return 0;
1501                         //Decide if it's an array of a generic argument list
1502                         *p++ = 0;
1503
1504                         if (!*p) //XXX test
1505                                 return 0;
1506                         if (*p  == ',' || *p == '*' || *p == ']') { //array
1507                                 isptr = 0;
1508                                 rank = 1;
1509                                 while (*p) {
1510                                         if (*p == ']')
1511                                                 break;
1512                                         if (*p == ',')
1513                                                 rank++;
1514                                         else if (*p == '*') /* '*' means unknown lower bound */
1515                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
1516                                         else
1517                                                 return 0;
1518                                         ++p;
1519                                 }
1520                                 if (*p++ != ']')
1521                                         return 0;
1522                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
1523                         } else {
1524                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
1525                                         return 0;
1526                                 isptr = 0;
1527                                 info->type_arguments = g_ptr_array_new ();
1528                                 while (*p) {
1529                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
1530                                         gboolean fqname = FALSE;
1531
1532                                         g_ptr_array_add (info->type_arguments, subinfo);
1533
1534                                         while (*p == ' ') p++;
1535                                         if (*p == '[') {
1536                                                 p++;
1537                                                 fqname = TRUE;
1538                                         }
1539
1540                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
1541                                                 return 0;
1542
1543                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
1544                                         if (fqname && (*p != ']')) {
1545                                                 char *aname;
1546
1547                                                 if (*p != ',')
1548                                                         return 0;
1549                                                 *p++ = 0;
1550
1551                                                 aname = p;
1552                                                 while (*p && (*p != ']'))
1553                                                         p++;
1554
1555                                                 if (*p != ']')
1556                                                         return 0;
1557
1558                                                 *p++ = 0;
1559                                                 while (*aname) {
1560                                                         if (g_ascii_isspace (*aname)) {
1561                                                                 ++aname;
1562                                                                 continue;
1563                                                         }
1564                                                         break;
1565                                                 }
1566                                                 if (!*aname ||
1567                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
1568                                                         return 0;
1569                                         } else if (fqname && (*p == ']')) {
1570                                                 *p++ = 0;
1571                                         }
1572                                         if (*p == ']') {
1573                                                 *p++ = 0;
1574                                                 break;
1575                                         } else if (!*p) {
1576                                                 return 0;
1577                                         }
1578                                         *p++ = 0;
1579                                 }
1580                         }
1581                         break;
1582                 case ']':
1583                         if (is_recursed)
1584                                 goto end;
1585                         return 0;
1586                 case ',':
1587                         if (is_recursed)
1588                                 goto end;
1589                         *p++ = 0;
1590                         while (*p) {
1591                                 if (g_ascii_isspace (*p)) {
1592                                         ++p;
1593                                         continue;
1594                                 }
1595                                 break;
1596                         }
1597                         if (!*p)
1598                                 return 0; /* missing assembly name */
1599                         if (!assembly_name_to_aname (&info->assembly, p))
1600                                 return 0;
1601                         break;
1602                 default:
1603                         return 0;
1604                 }
1605                 if (info->assembly.name)
1606                         break;
1607         }
1608         // *w = 0; /* terminate class name */
1609  end:
1610         if (!info->name || !*info->name)
1611                 return 0;
1612         if (endptr)
1613                 *endptr = p;
1614         /* add other consistency checks */
1615         return 1;
1616 }
1617
1618
1619 /**
1620  * mono_identifier_unescape_type_name_chars:
1621  * @identifier: the display name of a mono type
1622  *
1623  * Returns:
1624  *  The name in internal form, that is without escaping backslashes.
1625  *
1626  *  The string is modified in place!
1627  */
1628 char*
1629 mono_identifier_unescape_type_name_chars(char* identifier)
1630 {
1631         char *w, *r;
1632         if (!identifier)
1633                 return NULL;
1634         for (w = r = identifier; *r != 0; r++)
1635         {
1636                 char c = *r;
1637                 if (c == '\\') {
1638                         r++;
1639                         if (*r == 0)
1640                                 break;
1641                         c = *r;
1642                 }
1643                 *w = c;
1644                 w++;
1645         }
1646         if (w != r)
1647                 *w = 0;
1648         return identifier;
1649 }
1650
1651 void
1652 mono_identifier_unescape_info (MonoTypeNameParse* info);
1653
1654 static void
1655 unescape_each_type_argument(void* data, void* user_data)
1656 {
1657         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
1658         mono_identifier_unescape_info (info);
1659 }
1660
1661 static void
1662 unescape_each_nested_name (void* data, void* user_data)
1663 {
1664         char* nested_name = (char*) data;
1665         mono_identifier_unescape_type_name_chars(nested_name);
1666 }
1667
1668 /**
1669  * mono_identifier_unescape_info:
1670  *
1671  * @info: a parsed display form of an (optionally assembly qualified) full type name.
1672  *
1673  * Returns: nothing.
1674  *
1675  * Destructively updates the info by unescaping the identifiers that
1676  * comprise the type namespace, name, nested types (if any) and
1677  * generic type arguments (if any).
1678  *
1679  * The resulting info has the names in internal form.
1680  *
1681  */
1682 void
1683 mono_identifier_unescape_info (MonoTypeNameParse *info)
1684 {
1685         if (!info)
1686                 return;
1687         mono_identifier_unescape_type_name_chars(info->name_space);
1688         mono_identifier_unescape_type_name_chars(info->name);
1689         // but don't escape info->assembly
1690         if (info->type_arguments)
1691                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
1692         if (info->nested)
1693                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
1694 }
1695
1696 int
1697 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
1698 {
1699         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
1700         if (ok) {
1701                 mono_identifier_unescape_info (info);
1702         }
1703         return ok;
1704 }
1705
1706 static MonoType*
1707 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
1708 {
1709         gboolean type_resolve = FALSE;
1710         MonoType *type;
1711         MonoImage *rootimage = image;
1712
1713         mono_error_init (error);
1714
1715         if (info->assembly.name) {
1716                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
1717                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
1718                         /* 
1719                          * This could happen in the AOT compiler case when the search hook is not
1720                          * installed.
1721                          */
1722                         assembly = image->assembly;
1723                 if (!assembly) {
1724                         /* then we must load the assembly ourselve - see #60439 */
1725                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
1726                         if (!assembly)
1727                                 return NULL;
1728                 }
1729                 image = assembly->image;
1730         } else if (!image) {
1731                 image = mono_defaults.corlib;
1732         }
1733
1734         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
1735         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
1736                 /* ignore the error and try again */
1737                 mono_error_cleanup (error);
1738                 mono_error_init (error);
1739                 image = mono_defaults.corlib;
1740                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
1741         }
1742
1743         return type;
1744 }
1745
1746 /**
1747  * mono_reflection_get_type_internal:
1748  *
1749  * Returns: may return NULL on success, sets error on failure.
1750  */
1751 static MonoType*
1752 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
1753 {
1754         MonoClass *klass;
1755         GList *mod;
1756         int modval;
1757         gboolean bounded = FALSE;
1758         
1759         mono_error_init (error);
1760         if (!image)
1761                 image = mono_defaults.corlib;
1762
1763         if (!rootimage)
1764                 rootimage = mono_defaults.corlib;
1765
1766         if (ignorecase)
1767                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
1768         else
1769                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
1770
1771         if (!klass)
1772                 return NULL;
1773
1774         for (mod = info->nested; mod; mod = mod->next) {
1775                 gpointer iter = NULL;
1776                 MonoClass *parent;
1777
1778                 parent = klass;
1779                 mono_class_init (parent);
1780
1781                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
1782                         char *lastp;
1783                         char *nested_name, *nested_nspace;
1784                         gboolean match = TRUE;
1785
1786                         lastp = strrchr ((const char *)mod->data, '.');
1787                         if (lastp) {
1788                                 /* Nested classes can have namespaces */
1789                                 int nspace_len;
1790
1791                                 nested_name = g_strdup (lastp + 1);
1792                                 nspace_len = lastp - (char*)mod->data;
1793                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
1794                                 memcpy (nested_nspace, mod->data, nspace_len);
1795                                 nested_nspace [nspace_len] = '\0';
1796
1797                         } else {
1798                                 nested_name = (char *)mod->data;
1799                                 nested_nspace = NULL;
1800                         }
1801
1802                         if (nested_nspace) {
1803                                 if (ignorecase) {
1804                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
1805                                                 match = FALSE;
1806                                 } else {
1807                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
1808                                                 match = FALSE;
1809                                 }
1810                         }
1811                         if (match) {
1812                                 if (ignorecase) {
1813                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
1814                                                 match = FALSE;
1815                                 } else {
1816                                         if (strcmp (klass->name, nested_name) != 0)
1817                                                 match = FALSE;
1818                                 }
1819                         }
1820                         if (lastp) {
1821                                 g_free (nested_name);
1822                                 g_free (nested_nspace);
1823                         }
1824                         if (match)
1825                                 break;
1826                 }
1827
1828                 if (!klass)
1829                         break;
1830         }
1831         if (!klass)
1832                 return NULL;
1833
1834         if (info->type_arguments) {
1835                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
1836                 MonoReflectionType *the_type;
1837                 MonoType *instance;
1838                 int i;
1839
1840                 for (i = 0; i < info->type_arguments->len; i++) {
1841                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
1842
1843                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
1844                         if (!type_args [i]) {
1845                                 g_free (type_args);
1846                                 return NULL;
1847                         }
1848                 }
1849
1850                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
1851                 if (!the_type)
1852                         return NULL;
1853
1854                 instance = mono_reflection_bind_generic_parameters (
1855                         the_type, info->type_arguments->len, type_args, error);
1856
1857                 g_free (type_args);
1858                 if (!instance)
1859                         return NULL;
1860
1861                 klass = mono_class_from_mono_type (instance);
1862         }
1863
1864         for (mod = info->modifiers; mod; mod = mod->next) {
1865                 modval = GPOINTER_TO_UINT (mod->data);
1866                 if (!modval) { /* byref: must be last modifier */
1867                         return &klass->this_arg;
1868                 } else if (modval == -1) {
1869                         klass = mono_ptr_class_get (&klass->byval_arg);
1870                 } else if (modval == -2) {
1871                         bounded = TRUE;
1872                 } else { /* array rank */
1873                         klass = mono_bounded_array_class_get (klass, modval, bounded);
1874                 }
1875         }
1876
1877         return &klass->byval_arg;
1878 }
1879
1880 /*
1881  * mono_reflection_get_type:
1882  * @image: a metadata context
1883  * @info: type description structure
1884  * @ignorecase: flag for case-insensitive string compares
1885  * @type_resolve: whenever type resolve was already tried
1886  *
1887  * Build a MonoType from the type description in @info.
1888  * 
1889  */
1890
1891 MonoType*
1892 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
1893         MonoError error;
1894         MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
1895         mono_error_cleanup (&error);
1896         return result;
1897 }
1898
1899 /**
1900  * mono_reflection_get_type_checked:
1901  * @rootimage: the image of the currently active managed caller
1902  * @image: a metadata context
1903  * @info: type description structure
1904  * @ignorecase: flag for case-insensitive string compares
1905  * @type_resolve: whenever type resolve was already tried
1906  * @error: set on error.
1907  *
1908  * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
1909  *
1910  */
1911 MonoType*
1912 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
1913         mono_error_init (error);
1914         return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
1915 }
1916
1917
1918 static MonoType*
1919 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
1920 {
1921         MonoReflectionAssemblyBuilder *abuilder;
1922         MonoType *type;
1923         int i;
1924
1925         mono_error_init (error);
1926         g_assert (assembly_is_dynamic (assembly));
1927         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
1928         if (!abuilder)
1929                 return NULL;
1930
1931         /* Enumerate all modules */
1932
1933         type = NULL;
1934         if (abuilder->modules) {
1935                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
1936                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
1937                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
1938                         if (type)
1939                                 break;
1940                         if (!mono_error_ok (error))
1941                                 return NULL;
1942                 }
1943         }
1944
1945         if (!type && abuilder->loaded_modules) {
1946                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
1947                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
1948                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
1949                         if (type)
1950                                 break;
1951                         if (!mono_error_ok (error))
1952                                 return NULL;
1953                 }
1954         }
1955
1956         return type;
1957 }
1958         
1959 MonoType*
1960 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
1961 {
1962         MonoType *type;
1963         MonoReflectionAssembly *assembly;
1964         GString *fullName;
1965         GList *mod;
1966
1967         mono_error_init (error);
1968
1969         if (image && image_is_dynamic (image))
1970                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
1971         else {
1972                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
1973         }
1974         return_val_if_nok (error, NULL);
1975
1976         if (type)
1977                 return type;
1978         if (!mono_domain_has_type_resolve (mono_domain_get ()))
1979                 return NULL;
1980
1981         if (type_resolve) {
1982                 if (*type_resolve) 
1983                         return NULL;
1984                 else
1985                         *type_resolve = TRUE;
1986         }
1987         
1988         /* Reconstruct the type name */
1989         fullName = g_string_new ("");
1990         if (info->name_space && (info->name_space [0] != '\0'))
1991                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
1992         else
1993                 g_string_printf (fullName, "%s", info->name);
1994         for (mod = info->nested; mod; mod = mod->next)
1995                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
1996
1997         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
1998         if (!is_ok (error)) {
1999                 g_string_free (fullName, TRUE);
2000                 return NULL;
2001         }
2002
2003         if (assembly) {
2004                 if (assembly_is_dynamic (assembly->assembly))
2005                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
2006                                                                           info, ignorecase, error);
2007                 else
2008                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
2009                                                                   info, ignorecase, error);
2010         }
2011         g_string_free (fullName, TRUE);
2012         return_val_if_nok (error, NULL);
2013         return type;
2014 }
2015
2016 void
2017 mono_reflection_free_type_info (MonoTypeNameParse *info)
2018 {
2019         g_list_free (info->modifiers);
2020         g_list_free (info->nested);
2021
2022         if (info->type_arguments) {
2023                 int i;
2024
2025                 for (i = 0; i < info->type_arguments->len; i++) {
2026                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
2027
2028                         mono_reflection_free_type_info (subinfo);
2029                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
2030                         g_free (subinfo);
2031                 }
2032
2033                 g_ptr_array_free (info->type_arguments, TRUE);
2034         }
2035 }
2036
2037 /*
2038  * mono_reflection_type_from_name:
2039  * @name: type name.
2040  * @image: a metadata context (can be NULL).
2041  *
2042  * Retrieves a MonoType from its @name. If the name is not fully qualified,
2043  * it defaults to get the type from @image or, if @image is NULL or loading
2044  * from it fails, uses corlib.
2045  * 
2046  */
2047 MonoType*
2048 mono_reflection_type_from_name (char *name, MonoImage *image)
2049 {
2050         MonoError error;
2051         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
2052         mono_error_cleanup (&error);
2053         return result;
2054 }
2055
2056 /**
2057  * mono_reflection_type_from_name_checked:
2058  * @name: type name.
2059  * @image: a metadata context (can be NULL).
2060  * @error: set on errror.
2061  *
2062  * Retrieves a MonoType from its @name. If the name is not fully qualified,
2063  * it defaults to get the type from @image or, if @image is NULL or loading
2064  * from it fails, uses corlib.  On failure returns NULL and sets @error.
2065  * 
2066  */
2067 MonoType*
2068 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
2069 {
2070         MonoType *type = NULL;
2071         MonoTypeNameParse info;
2072         char *tmp;
2073
2074         mono_error_init (error);
2075         /* Make a copy since parse_type modifies its argument */
2076         tmp = g_strdup (name);
2077         
2078         /*g_print ("requested type %s\n", str);*/
2079         if (mono_reflection_parse_type (tmp, &info)) {
2080                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
2081                 if (!is_ok (error)) {
2082                         g_free (tmp);
2083                         mono_reflection_free_type_info (&info);
2084                         return NULL;
2085                 }
2086         }
2087
2088         g_free (tmp);
2089         mono_reflection_free_type_info (&info);
2090         return type;
2091 }
2092
2093 /*
2094  * mono_reflection_get_token:
2095  *
2096  *   Return the metadata token of OBJ which should be an object
2097  * representing a metadata element.
2098  */
2099 guint32
2100 mono_reflection_get_token (MonoObject *obj)
2101 {
2102         MonoError error;
2103         guint32 result = mono_reflection_get_token_checked (obj, &error);
2104         mono_error_assert_ok (&error);
2105         return result;
2106 }
2107
2108 /**
2109  * mono_reflection_get_token_checked:
2110  * @obj: the object
2111  * @error: set on error
2112  *
2113  *   Return the metadata token of @obj which should be an object
2114  * representing a metadata element.  On failure sets @error.
2115  */
2116 guint32
2117 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
2118 {
2119         MonoClass *klass;
2120         guint32 token = 0;
2121
2122         mono_error_init (error);
2123
2124         klass = obj->vtable->klass;
2125
2126         if (strcmp (klass->name, "MethodBuilder") == 0) {
2127                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
2128
2129                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2130         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
2131                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
2132
2133                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
2134         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
2135                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
2136
2137                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
2138         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
2139                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
2140                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
2141         } else if (strcmp (klass->name, "RuntimeType") == 0) {
2142                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
2143                 return_val_if_nok (error, 0);
2144                 MonoClass *mc = mono_class_from_mono_type (type);
2145                 if (!mono_class_init (mc)) {
2146                         mono_error_set_for_class_failure (error, mc);
2147                         return 0;
2148                 }
2149
2150                 token = mc->type_token;
2151         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
2152                    strcmp (klass->name, "MonoMethod") == 0 ||
2153                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
2154                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
2155                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
2156                 if (m->method->is_inflated) {
2157                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
2158                         return inflated->declaring->token;
2159                 } else {
2160                         token = m->method->token;
2161                 }
2162         } else if (strcmp (klass->name, "MonoField") == 0) {
2163                 MonoReflectionField *f = (MonoReflectionField*)obj;
2164
2165                 token = mono_class_get_field_token (f->field);
2166         } else if (strcmp (klass->name, "MonoProperty") == 0) {
2167                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
2168
2169                 token = mono_class_get_property_token (p->property);
2170         } else if (strcmp (klass->name, "MonoEvent") == 0) {
2171                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
2172
2173                 token = mono_class_get_event_token (p->event);
2174         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
2175                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
2176                 MonoClass *member_class = mono_object_class (p->MemberImpl);
2177                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
2178
2179                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
2180         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
2181                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
2182
2183                 token = m->token;
2184         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
2185                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
2186         } else {
2187                 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
2188                                                 klass->name_space, klass->name);
2189                 return 0;
2190         }
2191
2192         return token;
2193 }
2194
2195
2196 gboolean
2197 mono_reflection_is_usertype (MonoReflectionType *ref)
2198 {
2199         MonoClass *klass = mono_object_class (ref);
2200         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
2201 }
2202
2203 /**
2204  * mono_reflection_bind_generic_parameters:
2205  * @type: a managed type object (which should be some kind of generic (instance? definition?))
2206  * @type_args: the number of type arguments to bind
2207  * @types: array of type arguments
2208  * @error: set on error
2209  *
2210  * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
2211  * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
2212  */
2213 MonoType*
2214 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
2215 {
2216         MonoClass *klass;
2217         MonoReflectionTypeBuilder *tb = NULL;
2218         gboolean is_dynamic = FALSE;
2219         MonoClass *geninst;
2220
2221         mono_error_init (error);
2222         
2223         mono_loader_lock ();
2224
2225         if (mono_is_sre_type_builder (mono_object_class (type))) {
2226                 tb = (MonoReflectionTypeBuilder *) type;
2227
2228                 is_dynamic = TRUE;
2229         } else if (mono_is_sre_generic_instance (mono_object_class (type))) {
2230                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
2231                 MonoReflectionType *gtd = rgi->generic_type;
2232
2233                 if (mono_is_sre_type_builder (mono_object_class (gtd))) {
2234                         tb = (MonoReflectionTypeBuilder *)gtd;
2235                         is_dynamic = TRUE;
2236                 }
2237         }
2238
2239         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
2240         if (tb && tb->generic_container) {
2241                 if (!mono_reflection_create_generic_class (tb, error)) {
2242                         mono_loader_unlock ();
2243                         return NULL;
2244                 }
2245         }
2246
2247         MonoType *t = mono_reflection_type_get_handle (type, error);
2248         if (!is_ok (error)) {
2249                 mono_loader_unlock ();
2250                 return NULL;
2251         }
2252
2253         klass = mono_class_from_mono_type (t);
2254         if (!klass->generic_container) {
2255                 mono_loader_unlock ();
2256                 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
2257                 return NULL;
2258         }
2259
2260         if (klass->wastypebuilder) {
2261                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
2262
2263                 is_dynamic = TRUE;
2264         }
2265
2266         mono_loader_unlock ();
2267
2268         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
2269
2270         return &geninst->byval_arg;
2271 }
2272
2273 MonoClass*
2274 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
2275 {
2276         MonoGenericClass *gclass;
2277         MonoGenericInst *inst;
2278
2279         g_assert (klass->generic_container);
2280
2281         inst = mono_metadata_get_generic_inst (type_argc, types);
2282         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
2283
2284         return mono_generic_class_get_class (gclass);
2285 }
2286
2287 static MonoReflectionMethod*
2288 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
2289 {
2290         MonoClass *klass;
2291         MonoMethod *method, *inflated;
2292         MonoMethodInflated *imethod;
2293         MonoGenericContext tmp_context;
2294         MonoGenericInst *ginst;
2295         MonoType **type_argv;
2296         int count, i;
2297
2298         mono_error_init (error);
2299
2300         /*FIXME but this no longer should happen*/
2301         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
2302                 method = mono_reflection_method_builder_to_mono_method ((MonoReflectionMethodBuilder*)rmethod, error);
2303                 return_val_if_nok (error, NULL);
2304         } else {
2305                 method = rmethod->method;
2306         }
2307
2308         klass = method->klass;
2309
2310         if (method->is_inflated)
2311                 method = ((MonoMethodInflated *) method)->declaring;
2312
2313         count = mono_method_signature (method)->generic_param_count;
2314         if (count != mono_array_length (types))
2315                 return NULL;
2316
2317         type_argv = g_new0 (MonoType *, count);
2318         for (i = 0; i < count; i++) {
2319                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
2320                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
2321                 if (!is_ok (error)) {
2322                         g_free (type_argv);
2323                         return NULL;
2324                 }
2325         }
2326         ginst = mono_metadata_get_generic_inst (count, type_argv);
2327         g_free (type_argv);
2328
2329         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2330         tmp_context.method_inst = ginst;
2331
2332         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
2333         mono_error_assert_ok (error);
2334         imethod = (MonoMethodInflated *) inflated;
2335
2336         /*FIXME but I think this is no longer necessary*/
2337         if (image_is_dynamic (method->klass->image)) {
2338                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
2339                 /*
2340                  * This table maps metadata structures representing inflated methods/fields
2341                  * to the reflection objects representing their generic definitions.
2342                  */
2343                 mono_image_lock ((MonoImage*)image);
2344                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
2345                 mono_image_unlock ((MonoImage*)image);
2346         }
2347
2348         if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
2349                 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
2350                 return NULL;
2351         }
2352         
2353         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
2354         return ret;
2355 }
2356
2357 MonoReflectionMethod*
2358 ves_icall_MethodBuilder_MakeGenericMethod (MonoReflectionMethod *rmethod, MonoArray *types)
2359 {
2360         MonoError error;
2361         MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
2362         mono_error_set_pending_exception (&error);
2363         return result;
2364 }
2365
2366 MonoReflectionMethod*
2367 ves_icall_MonoMethod_MakeGenericMethod_impl (MonoReflectionMethod *rmethod, MonoArray *types)
2368 {
2369         MonoError error;
2370         MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
2371         mono_error_set_pending_exception (&error);
2372         return result;
2373 }
2374
2375
2376 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
2377 const static guint32 declsec_flags_map[] = {
2378         0x00000000,                                     /* empty */
2379         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
2380         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
2381         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
2382         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
2383         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
2384         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
2385         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
2386         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
2387         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
2388         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
2389         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
2390         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
2391         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
2392         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
2393         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
2394         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
2395         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
2396         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
2397 };
2398
2399 /*
2400  * Returns flags that includes all available security action associated to the handle.
2401  * @token: metadata token (either for a class or a method)
2402  * @image: image where resides the metadata.
2403  */
2404 static guint32
2405 mono_declsec_get_flags (MonoImage *image, guint32 token)
2406 {
2407         int index = mono_metadata_declsec_from_index (image, token);
2408         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
2409         guint32 result = 0;
2410         guint32 action;
2411         int i;
2412
2413         /* HasSecurity can be present for other, not specially encoded, attributes,
2414            e.g. SuppressUnmanagedCodeSecurityAttribute */
2415         if (index < 0)
2416                 return 0;
2417
2418         for (i = index; i < t->rows; i++) {
2419                 guint32 cols [MONO_DECL_SECURITY_SIZE];
2420
2421                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
2422                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
2423                         break;
2424
2425                 action = cols [MONO_DECL_SECURITY_ACTION];
2426                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
2427                         result |= declsec_flags_map [action];
2428                 } else {
2429                         g_assert_not_reached ();
2430                 }
2431         }
2432         return result;
2433 }
2434
2435 /*
2436  * Get the security actions (in the form of flags) associated with the specified method.
2437  *
2438  * @method: The method for which we want the declarative security flags.
2439  * Return the declarative security flags for the method (only).
2440  *
2441  * Note: To keep MonoMethod size down we do not cache the declarative security flags
2442  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
2443  */
2444 guint32
2445 mono_declsec_flags_from_method (MonoMethod *method)
2446 {
2447         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
2448                 /* FIXME: No cache (for the moment) */
2449                 guint32 idx = mono_method_get_index (method);
2450                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
2451                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
2452                 return mono_declsec_get_flags (method->klass->image, idx);
2453         }
2454         return 0;
2455 }
2456
2457 /*
2458  * Get the security actions (in the form of flags) associated with the specified class.
2459  *
2460  * @klass: The class for which we want the declarative security flags.
2461  * Return the declarative security flags for the class.
2462  *
2463  * Note: We cache the flags inside the MonoClass structure as this will get 
2464  *       called very often (at least for each method).
2465  */
2466 guint32
2467 mono_declsec_flags_from_class (MonoClass *klass)
2468 {
2469         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
2470                 if (!klass->ext || !klass->ext->declsec_flags) {
2471                         guint32 idx;
2472
2473                         idx = mono_metadata_token_index (klass->type_token);
2474                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
2475                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
2476                         mono_loader_lock ();
2477                         mono_class_alloc_ext (klass);
2478                         mono_loader_unlock ();
2479                         /* we cache the flags on classes */
2480                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
2481                 }
2482                 return klass->ext->declsec_flags;
2483         }
2484         return 0;
2485 }
2486
2487 /*
2488  * Get the security actions (in the form of flags) associated with the specified assembly.
2489  *
2490  * @assembly: The assembly for which we want the declarative security flags.
2491  * Return the declarative security flags for the assembly.
2492  */
2493 guint32
2494 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
2495 {
2496         guint32 idx = 1; /* there is only one assembly */
2497         idx <<= MONO_HAS_DECL_SECURITY_BITS;
2498         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
2499         return mono_declsec_get_flags (assembly->image, idx);
2500 }
2501
2502
2503 /*
2504  * Fill actions for the specific index (which may either be an encoded class token or
2505  * an encoded method token) from the metadata image.
2506  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
2507  */
2508 static MonoBoolean
2509 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
2510         guint32 id_std, guint32 id_noncas, guint32 id_choice)
2511 {
2512         MonoBoolean result = FALSE;
2513         MonoTableInfo *t;
2514         guint32 cols [MONO_DECL_SECURITY_SIZE];
2515         int index = mono_metadata_declsec_from_index (image, token);
2516         int i;
2517
2518         t  = &image->tables [MONO_TABLE_DECLSECURITY];
2519         for (i = index; i < t->rows; i++) {
2520                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
2521
2522                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
2523                         return result;
2524
2525                 /* if present only replace (class) permissions with method permissions */
2526                 /* if empty accept either class or method permissions */
2527                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
2528                         if (!actions->demand.blob) {
2529                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
2530                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
2531                                 actions->demand.blob = (char*) (blob + 2);
2532                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
2533                                 result = TRUE;
2534                         }
2535                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
2536                         if (!actions->noncasdemand.blob) {
2537                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
2538                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
2539                                 actions->noncasdemand.blob = (char*) (blob + 2);
2540                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
2541                                 result = TRUE;
2542                         }
2543                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
2544                         if (!actions->demandchoice.blob) {
2545                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
2546                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
2547                                 actions->demandchoice.blob = (char*) (blob + 2);
2548                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
2549                                 result = TRUE;
2550                         }
2551                 }
2552         }
2553
2554         return result;
2555 }
2556
2557 static MonoBoolean
2558 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
2559         guint32 id_std, guint32 id_noncas, guint32 id_choice)
2560 {
2561         guint32 idx = mono_metadata_token_index (klass->type_token);
2562         idx <<= MONO_HAS_DECL_SECURITY_BITS;
2563         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
2564         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
2565 }
2566
2567 static MonoBoolean
2568 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
2569         guint32 id_std, guint32 id_noncas, guint32 id_choice)
2570 {
2571         guint32 idx = mono_method_get_index (method);
2572         idx <<= MONO_HAS_DECL_SECURITY_BITS;
2573         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
2574         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
2575 }
2576
2577 /*
2578  * Collect all actions (that requires to generate code in mini) assigned for
2579  * the specified method.
2580  * Note: Don't use the content of actions if the function return FALSE.
2581  */
2582 MonoBoolean
2583 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
2584 {
2585         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
2586                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
2587         MonoBoolean result = FALSE;
2588         guint32 flags;
2589
2590         /* quick exit if no declarative security is present in the metadata */
2591         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
2592                 return FALSE;
2593
2594         /* we want the original as the wrapper is "free" of the security informations */
2595         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
2596                 method = mono_marshal_method_from_wrapper (method);
2597                 if (!method)
2598                         return FALSE;
2599         }
2600
2601         /* First we look for method-level attributes */
2602         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
2603                 mono_class_init (method->klass);
2604                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
2605
2606                 result = mono_declsec_get_method_demands_params (method, demands, 
2607                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
2608         }
2609
2610         /* Here we use (or create) the class declarative cache to look for demands */
2611         flags = mono_declsec_flags_from_class (method->klass);
2612         if (flags & mask) {
2613                 if (!result) {
2614                         mono_class_init (method->klass);
2615                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
2616                 }
2617                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
2618                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
2619         }
2620
2621         /* The boolean return value is used as a shortcut in case nothing needs to
2622            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
2623         return result;
2624 }
2625
2626
2627 /*
2628  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
2629  *
2630  * Note: Don't use the content of actions if the function return FALSE.
2631  */
2632 MonoBoolean
2633 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
2634 {
2635         MonoBoolean result = FALSE;
2636         guint32 flags;
2637
2638         /* quick exit if no declarative security is present in the metadata */
2639         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
2640                 return FALSE;
2641
2642         /* we want the original as the wrapper is "free" of the security informations */
2643         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
2644                 method = mono_marshal_method_from_wrapper (method);
2645                 if (!method)
2646                         return FALSE;
2647         }
2648
2649         /* results are independant - zeroize both */
2650         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
2651         memset (klass, 0, sizeof (MonoDeclSecurityActions));
2652
2653         /* First we look for method-level attributes */
2654         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
2655                 mono_class_init (method->klass);
2656
2657                 result = mono_declsec_get_method_demands_params (method, cmethod, 
2658                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
2659         }
2660
2661         /* Here we use (or create) the class declarative cache to look for demands */
2662         flags = mono_declsec_flags_from_class (method->klass);
2663         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
2664                 mono_class_init (method->klass);
2665
2666                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
2667                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
2668         }
2669
2670         return result;
2671 }
2672
2673 /*
2674  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
2675  *
2676  * @klass       The inherited class - this is the class that provides the security check (attributes)
2677  * @demans      
2678  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
2679  * 
2680  * Note: Don't use the content of actions if the function return FALSE.
2681  */
2682 MonoBoolean
2683 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
2684 {
2685         MonoBoolean result = FALSE;
2686         guint32 flags;
2687
2688         /* quick exit if no declarative security is present in the metadata */
2689         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
2690                 return FALSE;
2691
2692         /* Here we use (or create) the class declarative cache to look for demands */
2693         flags = mono_declsec_flags_from_class (klass);
2694         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
2695                 mono_class_init (klass);
2696                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
2697
2698                 result |= mono_declsec_get_class_demands_params (klass, demands, 
2699                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
2700         }
2701
2702         return result;
2703 }
2704
2705 /*
2706  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
2707  *
2708  * Note: Don't use the content of actions if the function return FALSE.
2709  */
2710 MonoBoolean
2711 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
2712 {
2713         /* quick exit if no declarative security is present in the metadata */
2714         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
2715                 return FALSE;
2716
2717         /* we want the original as the wrapper is "free" of the security informations */
2718         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
2719                 method = mono_marshal_method_from_wrapper (method);
2720                 if (!method)
2721                         return FALSE;
2722         }
2723
2724         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
2725                 mono_class_init (method->klass);
2726                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
2727
2728                 return mono_declsec_get_method_demands_params (method, demands, 
2729                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
2730         }
2731         return FALSE;
2732 }
2733
2734
2735 static MonoBoolean
2736 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
2737 {
2738         guint32 cols [MONO_DECL_SECURITY_SIZE];
2739         MonoTableInfo *t;
2740         int i;
2741
2742         int index = mono_metadata_declsec_from_index (image, token);
2743         if (index == -1)
2744                 return FALSE;
2745
2746         t =  &image->tables [MONO_TABLE_DECLSECURITY];
2747         for (i = index; i < t->rows; i++) {
2748                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
2749
2750                 /* shortcut - index are ordered */
2751                 if (token != cols [MONO_DECL_SECURITY_PARENT])
2752                         return FALSE;
2753
2754                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
2755                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
2756                         entry->blob = (char*) (metadata + 2);
2757                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
2758                         return TRUE;
2759                 }
2760         }
2761
2762         return FALSE;
2763 }
2764
2765 MonoBoolean
2766 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
2767 {
2768         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
2769                 guint32 idx = mono_method_get_index (method);
2770                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
2771                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
2772                 return get_declsec_action (method->klass->image, idx, action, entry);
2773         }
2774         return FALSE;
2775 }
2776
2777 MonoBoolean
2778 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
2779 {
2780         /* use cache */
2781         guint32 flags = mono_declsec_flags_from_class (klass);
2782         if (declsec_flags_map [action] & flags) {
2783                 guint32 idx = mono_metadata_token_index (klass->type_token);
2784                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
2785                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
2786                 return get_declsec_action (klass->image, idx, action, entry);
2787         }
2788         return FALSE;
2789 }
2790
2791 MonoBoolean
2792 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
2793 {
2794         guint32 idx = 1; /* there is only one assembly */
2795         idx <<= MONO_HAS_DECL_SECURITY_BITS;
2796         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
2797
2798         return get_declsec_action (assembly->image, idx, action, entry);
2799 }
2800
2801 gboolean
2802 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
2803 {
2804         MonoObject *res, *exc;
2805         void *params [1];
2806         static MonoMethod *method = NULL;
2807
2808         mono_error_init (error);
2809
2810         if (method == NULL) {
2811                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
2812                 g_assert (method);
2813         }
2814
2815         /* 
2816          * The result of mono_type_get_object_checked () might be a System.MonoType but we
2817          * need a TypeBuilder so use mono_class_get_ref_info (klass).
2818          */
2819         g_assert (mono_class_get_ref_info (klass));
2820         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
2821
2822         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
2823         return_val_if_nok (error, FALSE);
2824
2825         MonoError inner_error;
2826         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &inner_error);
2827
2828         if (exc || !is_ok (&inner_error)) {
2829                 mono_error_cleanup (&inner_error);
2830                 return FALSE;
2831         } else
2832                 return *(MonoBoolean*)mono_object_unbox (res);
2833 }
2834
2835 /**
2836  * mono_reflection_type_get_type:
2837  * @reftype: the System.Type object
2838  *
2839  * Returns the MonoType* associated with the C# System.Type object @reftype.
2840  */
2841 MonoType*
2842 mono_reflection_type_get_type (MonoReflectionType *reftype)
2843 {
2844         g_assert (reftype);
2845
2846         MonoError error;
2847         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
2848         mono_error_assert_ok (&error);
2849         return result;
2850 }
2851
2852 /**
2853  * mono_reflection_assembly_get_assembly:
2854  * @refassembly: the System.Reflection.Assembly object
2855  *
2856  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
2857  */
2858 MonoAssembly*
2859 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
2860 {
2861         g_assert (refassembly);
2862
2863         return refassembly->assembly;
2864 }
2865