2009-06-09 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / metadata.c
1 /*
2  * metadata.c: Routines for accessing the metadata
3  *
4  * Authors:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10  */
11
12 #include <config.h>
13 #ifdef HAVE_ALLOCA_H
14 #include <alloca.h>
15 #endif
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <glib.h>
20 #include "metadata.h"
21 #include "tabledefs.h"
22 #include "mono-endian.h"
23 #include "cil-coff.h"
24 #include "tokentype.h"
25 #include "metadata-internals.h"
26 #include "class-internals.h"
27 #include "class.h"
28 #include "marshal.h"
29
30 static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
31                                          const char *ptr, const char **rptr);
32
33 static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
34 static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
35 static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
36 static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
37                                                     gboolean signature_only);
38 static void free_generic_inst (MonoGenericInst *ginst);
39 static void free_generic_class (MonoGenericClass *ginst);
40 static void free_inflated_method (MonoMethodInflated *method);
41 static void mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image);
42
43 /*
44  * This enumeration is used to describe the data types in the metadata
45  * tables
46  */
47 enum {
48         MONO_MT_END,
49
50         /* Sized elements */
51         MONO_MT_UINT32,
52         MONO_MT_UINT16,
53         MONO_MT_UINT8,
54
55         /* Index into Blob heap */
56         MONO_MT_BLOB_IDX,
57
58         /* Index into String heap */
59         MONO_MT_STRING_IDX,
60
61         /* GUID index */
62         MONO_MT_GUID_IDX,
63
64         /* Pointer into a table */
65         MONO_MT_TABLE_IDX,
66
67         /* HasConstant:Parent pointer (Param, Field or Property) */
68         MONO_MT_CONST_IDX,
69
70         /* HasCustomAttribute index.  Indexes any table except CustomAttribute */
71         MONO_MT_HASCAT_IDX,
72         
73         /* CustomAttributeType encoded index */
74         MONO_MT_CAT_IDX,
75
76         /* HasDeclSecurity index: TypeDef Method or Assembly */
77         MONO_MT_HASDEC_IDX,
78
79         /* Implementation coded index: File, Export AssemblyRef */
80         MONO_MT_IMPL_IDX,
81
82         /* HasFieldMarshal coded index: Field or Param table */
83         MONO_MT_HFM_IDX,
84
85         /* MemberForwardedIndex: Field or Method */
86         MONO_MT_MF_IDX,
87
88         /* TypeDefOrRef coded index: typedef, typeref, typespec */
89         MONO_MT_TDOR_IDX,
90
91         /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
92         MONO_MT_MRP_IDX,
93
94         /* MethodDefOrRef coded index: Method or Member Ref table */
95         MONO_MT_MDOR_IDX,
96
97         /* HasSemantic coded index: Event or Property */
98         MONO_MT_HS_IDX,
99
100         /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
101         MONO_MT_RS_IDX
102 };
103
104 const static unsigned char TableSchemas [] = {
105 #define ASSEMBLY_SCHEMA_OFFSET 0
106         MONO_MT_UINT32,     /* "HashId" }, */
107         MONO_MT_UINT16,     /* "Major" },  */
108         MONO_MT_UINT16,     /* "Minor" }, */
109         MONO_MT_UINT16,     /* "BuildNumber" }, */
110         MONO_MT_UINT16,     /* "RevisionNumber" }, */
111         MONO_MT_UINT32,     /* "Flags" }, */
112         MONO_MT_BLOB_IDX,   /* "PublicKey" }, */
113         MONO_MT_STRING_IDX, /* "Name" }, */
114         MONO_MT_STRING_IDX, /* "Culture" }, */
115         MONO_MT_END,
116
117 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
118         MONO_MT_UINT32,     /* "OSPlatformID" }, */
119         MONO_MT_UINT32,     /* "OSMajor" }, */
120         MONO_MT_UINT32,     /* "OSMinor" }, */
121         MONO_MT_END,
122
123 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
124         MONO_MT_UINT32,     /* "Processor" }, */
125         MONO_MT_END,
126
127 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
128         MONO_MT_UINT16,     /* "Major" }, */
129         MONO_MT_UINT16,     /* "Minor" }, */
130         MONO_MT_UINT16,     /* "Build" }, */
131         MONO_MT_UINT16,     /* "Revision" }, */
132         MONO_MT_UINT32,     /* "Flags" }, */
133         MONO_MT_BLOB_IDX,   /* "PublicKeyOrToken" }, */
134         MONO_MT_STRING_IDX, /* "Name" }, */
135         MONO_MT_STRING_IDX, /* "Culture" }, */
136         MONO_MT_BLOB_IDX,   /* "HashValue" }, */
137         MONO_MT_END,
138
139 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
140         MONO_MT_UINT32,     /* "OSPlatformID" }, */
141         MONO_MT_UINT32,     /* "OSMajorVersion" }, */
142         MONO_MT_UINT32,     /* "OSMinorVersion" }, */
143         MONO_MT_TABLE_IDX,  /* "AssemblyRef:AssemblyRef" }, */
144         MONO_MT_END,
145
146 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
147         MONO_MT_UINT32,     /* "Processor" }, */
148         MONO_MT_TABLE_IDX,  /* "AssemblyRef:AssemblyRef" }, */
149         MONO_MT_END,
150
151 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
152         MONO_MT_UINT16,     /* "PackingSize" }, */
153         MONO_MT_UINT32,     /* "ClassSize" }, */
154         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
155         MONO_MT_END,
156
157 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
158         MONO_MT_UINT8,      /* "Type" }, */
159         MONO_MT_UINT8,      /* "PaddingZero" }, */
160         MONO_MT_CONST_IDX,  /* "Parent" }, */
161         MONO_MT_BLOB_IDX,   /* "Value" }, */
162         MONO_MT_END,
163
164 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
165         MONO_MT_HASCAT_IDX, /* "Parent" }, */
166         MONO_MT_CAT_IDX,    /* "Type" }, */
167         MONO_MT_BLOB_IDX,   /* "Value" }, */
168         MONO_MT_END,
169
170 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
171         MONO_MT_UINT16,     /* "Action" }, */
172         MONO_MT_HASDEC_IDX, /* "Parent" }, */
173         MONO_MT_BLOB_IDX,   /* "PermissionSet" }, */
174         MONO_MT_END,
175
176 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
177         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
178         MONO_MT_TABLE_IDX,  /* "EventList:Event" }, */
179         MONO_MT_END,
180
181 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
182         MONO_MT_UINT16,     /* "EventFlags#EventAttribute" }, */
183         MONO_MT_STRING_IDX, /* "Name" }, */
184         MONO_MT_TABLE_IDX,  /* "EventType" }, TypeDef or TypeRef  */
185         MONO_MT_END,
186
187 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
188         MONO_MT_TABLE_IDX,  /* "Event" }, */
189         MONO_MT_END,
190
191 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
192         MONO_MT_UINT32,     /* "Flags" }, */
193         MONO_MT_TABLE_IDX,  /* "TypeDefId" }, */
194         MONO_MT_STRING_IDX, /* "TypeName" }, */
195         MONO_MT_STRING_IDX, /* "TypeNameSpace" }, */
196         MONO_MT_IMPL_IDX,   /* "Implementation" }, */
197         MONO_MT_END,
198
199 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
200         MONO_MT_UINT16,     /* "Flags" }, */
201         MONO_MT_STRING_IDX, /* "Name" }, */
202         MONO_MT_BLOB_IDX,   /* "Signature" }, */
203         MONO_MT_END,
204
205 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
206         MONO_MT_UINT32,     /* "Offset" }, */
207         MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
208         MONO_MT_END,
209
210 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
211         MONO_MT_HFM_IDX,    /* "Parent" }, */
212         MONO_MT_BLOB_IDX,   /* "NativeType" }, */
213         MONO_MT_END,
214
215 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
216         MONO_MT_UINT32,     /* "RVA" }, */
217         MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
218         MONO_MT_END,
219
220 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
221         MONO_MT_TABLE_IDX,  /* "Field" }, */
222         MONO_MT_END,
223
224 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
225         MONO_MT_UINT32,     /* "Flags" }, */
226         MONO_MT_STRING_IDX, /* "Name" }, */
227         MONO_MT_BLOB_IDX,   /* "Value" },  */
228         MONO_MT_END,
229
230 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
231         MONO_MT_UINT16,     /* "MappingFlag" }, */
232         MONO_MT_MF_IDX,     /* "MemberForwarded" }, */
233         MONO_MT_STRING_IDX, /* "ImportName" }, */
234         MONO_MT_TABLE_IDX,  /* "ImportScope:ModuleRef" }, */
235         MONO_MT_END,
236
237 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
238         MONO_MT_TABLE_IDX,  /* "Class:TypeDef" },  */
239         MONO_MT_TDOR_IDX,  /* "Interface=TypeDefOrRef" }, */
240         MONO_MT_END,
241
242 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
243         MONO_MT_UINT32,     /* "Offset" }, */
244         MONO_MT_UINT32,     /* "Flags" }, */
245         MONO_MT_STRING_IDX, /* "Name" }, */
246         MONO_MT_IMPL_IDX,   /* "Implementation" }, */
247         MONO_MT_END,
248
249 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
250         MONO_MT_MRP_IDX,    /* "Class" }, */
251         MONO_MT_STRING_IDX, /* "Name" }, */
252         MONO_MT_BLOB_IDX,   /* "Signature" }, */
253         MONO_MT_END,
254
255 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
256         MONO_MT_UINT32,     /* "RVA" }, */
257         MONO_MT_UINT16,     /* "ImplFlags#MethodImplAttributes" }, */
258         MONO_MT_UINT16,     /* "Flags#MethodAttribute" }, */
259         MONO_MT_STRING_IDX, /* "Name" }, */
260         MONO_MT_BLOB_IDX,   /* "Signature" }, */
261         MONO_MT_TABLE_IDX,  /* "ParamList:Param" }, */
262         MONO_MT_END,
263
264 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
265         MONO_MT_TABLE_IDX,  /* "Class:TypeDef" }, */
266         MONO_MT_MDOR_IDX,   /* "MethodBody" }, */
267         MONO_MT_MDOR_IDX,   /* "MethodDeclaration" }, */
268         MONO_MT_END,
269
270 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
271         MONO_MT_UINT16,     /* "MethodSemantic" }, */
272         MONO_MT_TABLE_IDX,  /* "Method:Method" }, */
273         MONO_MT_HS_IDX,     /* "Association" }, */
274         MONO_MT_END,
275
276 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
277         MONO_MT_TABLE_IDX,  /* "Method" }, */
278         MONO_MT_END,
279
280 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
281         MONO_MT_UINT16,     /* "Generation" }, */
282         MONO_MT_STRING_IDX, /* "Name" }, */
283         MONO_MT_GUID_IDX,   /* "MVID" }, */
284         MONO_MT_GUID_IDX,   /* "EncID" }, */
285         MONO_MT_GUID_IDX,   /* "EncBaseID" }, */
286         MONO_MT_END,
287
288 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
289         MONO_MT_STRING_IDX, /* "Name" }, */
290         MONO_MT_END,
291
292 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
293         MONO_MT_TABLE_IDX,  /* "NestedClass:TypeDef" }, */
294         MONO_MT_TABLE_IDX,  /* "EnclosingClass:TypeDef" }, */
295         MONO_MT_END,
296
297 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
298         MONO_MT_UINT16,     /* "Flags" }, */
299         MONO_MT_UINT16,     /* "Sequence" }, */
300         MONO_MT_STRING_IDX, /* "Name" }, */
301         MONO_MT_END,
302
303 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
304         MONO_MT_TABLE_IDX,  /* "Param" }, */
305         MONO_MT_END,
306
307 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
308         MONO_MT_UINT16,     /* "Flags" }, */
309         MONO_MT_STRING_IDX, /* "Name" }, */
310         MONO_MT_BLOB_IDX,   /* "Type" }, */
311         MONO_MT_END,
312
313 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
314         MONO_MT_TABLE_IDX, /* "Property" }, */
315         MONO_MT_END,
316
317 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
318         MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
319         MONO_MT_TABLE_IDX,  /* "PropertyList:Property" }, */
320         MONO_MT_END,
321
322 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
323         MONO_MT_BLOB_IDX,   /* "Signature" }, */
324         MONO_MT_END,
325
326 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
327         MONO_MT_UINT32,     /* "Flags" }, */
328         MONO_MT_STRING_IDX, /* "Name" }, */
329         MONO_MT_STRING_IDX, /* "Namespace" }, */
330         MONO_MT_TDOR_IDX,   /* "Extends" }, */
331         MONO_MT_TABLE_IDX,  /* "FieldList:Field" }, */
332         MONO_MT_TABLE_IDX,  /* "MethodList:Method" }, */
333         MONO_MT_END,
334
335 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
336         MONO_MT_RS_IDX,     /* "ResolutionScope=ResolutionScope" }, */
337         MONO_MT_STRING_IDX, /* "Name" }, */
338         MONO_MT_STRING_IDX, /* "Namespace" }, */
339         MONO_MT_END,
340
341 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
342         MONO_MT_BLOB_IDX,   /* "Signature" }, */
343         MONO_MT_END,
344
345 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
346         MONO_MT_UINT16,     /* "Number" }, */
347         MONO_MT_UINT16,     /* "Flags" }, */
348         MONO_MT_TABLE_IDX,  /* "Owner" },  TypeDef or MethodDef */
349         MONO_MT_STRING_IDX, /* "Name" }, */
350         MONO_MT_END,
351
352 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
353         MONO_MT_MDOR_IDX,   /* "Method" }, */
354         MONO_MT_BLOB_IDX,   /* "Signature" }, */
355         MONO_MT_END,
356
357 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
358         MONO_MT_TABLE_IDX,  /* "GenericParam" }, */
359         MONO_MT_TDOR_IDX,   /* "Constraint" }, */
360         MONO_MT_END,
361
362 #define NULL_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
363         MONO_MT_END
364 };
365
366 /* Must be the same order as MONO_TABLE_* */
367 const static unsigned char
368 table_description [] = {
369         MODULE_SCHEMA_OFFSET,
370         TYPEREF_SCHEMA_OFFSET,
371         TYPEDEF_SCHEMA_OFFSET,
372         FIELD_POINTER_SCHEMA_OFFSET,
373         FIELD_SCHEMA_OFFSET,
374         METHOD_POINTER_SCHEMA_OFFSET,
375         METHOD_SCHEMA_OFFSET,
376         PARAM_POINTER_SCHEMA_OFFSET,
377         PARAM_SCHEMA_OFFSET,
378         IFACEMAP_SCHEMA_OFFSET,
379         MEMBERREF_SCHEMA_OFFSET, /* 0xa */
380         CONSTANT_SCHEMA_OFFSET,
381         CUSTOM_ATTR_SCHEMA_OFFSET,
382         FIELD_MARSHAL_SCHEMA_OFFSET,
383         DECL_SEC_SCHEMA_OFFSET,
384         CLASS_LAYOUT_SCHEMA_OFFSET,
385         FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
386         STDALON_SIG_SCHEMA_OFFSET,
387         EVENTMAP_SCHEMA_OFFSET,
388         EVENT_POINTER_SCHEMA_OFFSET,
389         EVENT_SCHEMA_OFFSET,
390         PROPERTY_MAP_SCHEMA_OFFSET,
391         PROPERTY_POINTER_SCHEMA_OFFSET,
392         PROPERTY_SCHEMA_OFFSET,
393         METHOD_SEMA_SCHEMA_OFFSET,
394         METHOD_IMPL_SCHEMA_OFFSET,
395         MODULEREF_SCHEMA_OFFSET, /* 0x1a */
396         TYPESPEC_SCHEMA_OFFSET,
397         IMPLMAP_SCHEMA_OFFSET,
398         FIELD_RVA_SCHEMA_OFFSET,
399         NULL_SCHEMA_OFFSET,
400         NULL_SCHEMA_OFFSET,
401         ASSEMBLY_SCHEMA_OFFSET, /* 0x20 */
402         ASSEMBLYPROC_SCHEMA_OFFSET,
403         ASSEMBLYOS_SCHEMA_OFFSET,
404         ASSEMBLYREF_SCHEMA_OFFSET,
405         ASSEMBLYREFPROC_SCHEMA_OFFSET,
406         ASSEMBLYREFOS_SCHEMA_OFFSET,
407         FILE_SCHEMA_OFFSET,
408         EXPORTED_TYPE_SCHEMA_OFFSET,
409         MANIFEST_SCHEMA_OFFSET,
410         NESTED_CLASS_SCHEMA_OFFSET,
411         GENPARAM_SCHEMA_OFFSET, /* 0x2a */
412         METHOD_SPEC_SCHEMA_OFFSET,
413         GEN_CONSTRAINT_SCHEMA_OFFSET
414 };
415
416 #ifdef HAVE_ARRAY_ELEM_INIT
417 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
418 #define MSGSTRFIELD1(line) str##line
419 static const struct msgstr_t {
420 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
421 #include "mono/cil/tables.def"
422 #undef TABLEDEF
423 } tablestr = {
424 #define TABLEDEF(a,b) b,
425 #include "mono/cil/tables.def"
426 #undef TABLEDEF
427 };
428 static const gint16 tableidx [] = {
429 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
430 #include "mono/cil/tables.def"
431 #undef TABLEDEF
432 };
433
434 #else
435 #define TABLEDEF(a,b) b,
436 static const char* const
437 mono_tables_names [] = {
438 #include "mono/cil/tables.def"
439         NULL
440 };
441
442 #endif
443
444 /* Auxiliary structure used for caching inflated signatures */
445 typedef struct {
446         MonoMethodSignature *sig;
447         MonoGenericContext context;
448 } MonoInflatedMethodSignature;
449
450 /**
451  * mono_meta_table_name:
452  * @table: table index
453  *
454  * Returns the name of the given ECMA metadata logical format table
455  * as described in ECMA 335, Partition II, Section 22.
456  * 
457  * Returns: the name for the @table index
458  */
459 const char *
460 mono_meta_table_name (int table)
461 {
462         if ((table < 0) || (table > MONO_TABLE_LAST))
463                 return "";
464
465 #ifdef HAVE_ARRAY_ELEM_INIT
466         return (const char*)&tablestr + tableidx [table];
467 #else
468         return mono_tables_names [table];
469 #endif
470 }
471
472 /* The guy who wrote the spec for this should not be allowed near a
473  * computer again.
474  
475 If  e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1, 
476 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of 
477 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of 
478 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the 
479 inverse of this mapping.
480
481  */
482 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
483 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
484
485 /* Reference: Partition II - 23.2.6 */
486 /*
487  * mono_metadata_compute_size:
488  * @meta: metadata context
489  * @tableindex: metadata table number
490  * @result_bitfield: pointer to guint32 where to store additional info
491  * 
492  * mono_metadata_compute_size() computes the lenght in bytes of a single
493  * row in a metadata table. The size of each column is encoded in the
494  * @result_bitfield return value along with the number of columns in the table.
495  * the resulting bitfield should be handed to the mono_metadata_table_size()
496  * and mono_metadata_table_count() macros.
497  * This is a Mono runtime internal only function.
498  */
499 int
500 mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
501 {
502         guint32 bitfield = 0;
503         int size = 0, field_size = 0;
504         int i, n, code;
505         int shift = 0;
506         const unsigned char *description = TableSchemas + table_description [tableindex];
507
508         for (i = 0; (code = description [i]) != MONO_MT_END; i++){
509                 switch (code){
510                 case MONO_MT_UINT32:
511                         field_size = 4; break;
512                         
513                 case MONO_MT_UINT16:
514                         field_size = 2; break;
515                         
516                 case MONO_MT_UINT8:
517                         field_size = 1; break;
518                         
519                 case MONO_MT_BLOB_IDX:
520                         field_size = meta->idx_blob_wide ? 4 : 2; break;
521                         
522                 case MONO_MT_STRING_IDX:
523                         field_size = meta->idx_string_wide ? 4 : 2; break;
524                         
525                 case MONO_MT_GUID_IDX:
526                         field_size = meta->idx_guid_wide ? 4 : 2; break;
527
528                 case MONO_MT_TABLE_IDX:
529                         /* Uhm, a table index can point to other tables besides the current one
530                          * so, it's not correct to use the rowcount of the current table to
531                          * get the size for this column - lupus 
532                          */
533                         switch (tableindex) {
534                         case MONO_TABLE_ASSEMBLYREFOS:
535                                 g_assert (i == 3);
536                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
537                         case MONO_TABLE_ASSEMBLYPROCESSOR:
538                                 g_assert (i == 1);
539                                 field_size = idx_size (MONO_TABLE_ASSEMBLYREF); break;
540                         case MONO_TABLE_CLASSLAYOUT:
541                                 g_assert (i == 2);
542                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
543                         case MONO_TABLE_EVENTMAP:
544                                 g_assert (i == 0 || i == 1);
545                                 field_size = i ? idx_size (MONO_TABLE_EVENT):
546                                         idx_size(MONO_TABLE_TYPEDEF); 
547                                 break;
548                         case MONO_TABLE_EVENT:
549                                 g_assert (i == 2);
550                                 n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows, meta->tables [MONO_TABLE_TYPEREF].rows);
551                                 n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
552                                 /*This is a coded token for 3 tables, so takes 2 bits */
553                                 field_size = rtsize (n, 16 - MONO_TYPEDEFORREF_BITS);
554                                 break;
555                         case MONO_TABLE_EVENT_POINTER:
556                                 g_assert (i == 0);
557                                 field_size = idx_size (MONO_TABLE_EVENT); break;
558                         case MONO_TABLE_EXPORTEDTYPE:
559                                 g_assert (i == 1);
560                                 /* the index is in another metadata file, so it must be 4 */
561                                 field_size = 4; break;
562                         case MONO_TABLE_FIELDLAYOUT:
563                                 g_assert (i == 1);
564                                 field_size = idx_size (MONO_TABLE_FIELD); break;
565                         case MONO_TABLE_FIELDRVA:
566                                 g_assert (i == 1);
567                                 field_size = idx_size (MONO_TABLE_FIELD); break;
568                         case MONO_TABLE_FIELD_POINTER:
569                                 g_assert (i == 0);
570                                 field_size = idx_size (MONO_TABLE_FIELD); break;
571                         case MONO_TABLE_IMPLMAP:
572                                 g_assert (i == 3);
573                                 field_size = idx_size (MONO_TABLE_MODULEREF); break;
574                         case MONO_TABLE_INTERFACEIMPL:
575                                 g_assert (i == 0);
576                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
577                         case MONO_TABLE_METHOD:
578                                 g_assert (i == 5);
579                                 field_size = idx_size (MONO_TABLE_PARAM); break;
580                         case MONO_TABLE_METHODIMPL:
581                                 g_assert (i == 0);
582                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
583                         case MONO_TABLE_METHODSEMANTICS:
584                                 g_assert (i == 1);
585                                 field_size = idx_size (MONO_TABLE_METHOD); break;
586                         case MONO_TABLE_METHOD_POINTER:
587                                 g_assert (i == 0);
588                                 field_size = idx_size (MONO_TABLE_METHOD); break;
589                         case MONO_TABLE_NESTEDCLASS:
590                                 g_assert (i == 0 || i == 1);
591                                 field_size = idx_size (MONO_TABLE_TYPEDEF); break;
592                         case MONO_TABLE_PARAM_POINTER:
593                                 g_assert (i == 0);
594                                 field_size = idx_size (MONO_TABLE_PARAM); break;
595                         case MONO_TABLE_PROPERTYMAP:
596                                 g_assert (i == 0 || i == 1);
597                                 field_size = i ? idx_size (MONO_TABLE_PROPERTY):
598                                         idx_size(MONO_TABLE_TYPEDEF); 
599                                 break;
600                         case MONO_TABLE_PROPERTY_POINTER:
601                                 g_assert (i == 0);
602                                 field_size = idx_size (MONO_TABLE_PROPERTY); break;
603                         case MONO_TABLE_TYPEDEF:
604                                 g_assert (i == 4 || i == 5);
605                                 field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
606                                         idx_size(MONO_TABLE_METHOD);
607                                 break;
608                         case MONO_TABLE_GENERICPARAM:
609                                 g_assert (i == 2 || i == 4 || i == 5);
610                                 if (i == 2) {
611                                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows, meta->tables [MONO_TABLE_TYPEDEF].rows);
612                                         /*This is a coded token for 2 tables, so takes 1 bit */
613                                         field_size = rtsize (n, 16 - MONO_TYPEORMETHOD_BITS);
614                                 } else if (i == 4)
615                                         field_size = idx_size (MONO_TABLE_TYPEDEF);
616                                 else if (i == 5)
617                                         field_size = idx_size (MONO_TABLE_TYPEDEF);
618                                 break;
619
620                         case MONO_TABLE_GENERICPARAMCONSTRAINT:
621                                 g_assert (i == 0);
622                                 field_size = idx_size (MONO_TABLE_GENERICPARAM);
623                                 break;
624                                 
625                         default:
626                                 g_assert_not_reached ();
627                         }
628                         break;
629
630                         /*
631                          * HasConstant: ParamDef, FieldDef, Property
632                          */
633                 case MONO_MT_CONST_IDX:
634                         n = MAX (meta->tables [MONO_TABLE_PARAM].rows,
635                                  meta->tables [MONO_TABLE_FIELD].rows);
636                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
637
638                         /* 2 bits to encode tag */
639                         field_size = rtsize (n, 16-2);
640                         break;
641
642                         /*
643                          * HasCustomAttribute: points to any table but
644                          * itself.
645                          */
646                 case MONO_MT_HASCAT_IDX:
647                         /*
648                          * We believe that since the signature and
649                          * permission are indexing the Blob heap,
650                          * we should consider the blob size first
651                          */
652                         /* I'm not a believer - lupus
653                         if (meta->idx_blob_wide){
654                                 field_size = 4;
655                                 break;
656                         }*/
657                         
658                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
659                                  meta->tables [MONO_TABLE_FIELD].rows);
660                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
661                         n = MAX (n, meta->tables [MONO_TABLE_TYPEDEF].rows);
662                         n = MAX (n, meta->tables [MONO_TABLE_PARAM].rows);
663                         n = MAX (n, meta->tables [MONO_TABLE_INTERFACEIMPL].rows);
664                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
665                         n = MAX (n, meta->tables [MONO_TABLE_MODULE].rows);
666                         n = MAX (n, meta->tables [MONO_TABLE_DECLSECURITY].rows);
667                         n = MAX (n, meta->tables [MONO_TABLE_PROPERTY].rows);
668                         n = MAX (n, meta->tables [MONO_TABLE_EVENT].rows);
669                         n = MAX (n, meta->tables [MONO_TABLE_STANDALONESIG].rows);
670                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
671                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
672                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
673                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
674                         n = MAX (n, meta->tables [MONO_TABLE_FILE].rows);
675                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
676                         n = MAX (n, meta->tables [MONO_TABLE_MANIFESTRESOURCE].rows);
677
678                         /* 5 bits to encode */
679                         field_size = rtsize (n, 16-5);
680                         break;
681
682                         /*
683                          * CustomAttributeType: TypeDef, TypeRef, MethodDef, 
684                          * MemberRef and String.  
685                          */
686                 case MONO_MT_CAT_IDX:
687                         /* String is a heap, if it is wide, we know the size */
688                         /* See above, nope. 
689                         if (meta->idx_string_wide){
690                                 field_size = 4;
691                                 break;
692                         }*/
693                         
694                         n = MAX (meta->tables [MONO_TABLE_TYPEREF].rows,
695                                  meta->tables [MONO_TABLE_TYPEDEF].rows);
696                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
697                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
698
699                         /* 3 bits to encode */
700                         field_size = rtsize (n, 16-3);
701                         break;
702
703                         /*
704                          * HasDeclSecurity: Typedef, MethodDef, Assembly
705                          */
706                 case MONO_MT_HASDEC_IDX:
707                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
708                                  meta->tables [MONO_TABLE_METHOD].rows);
709                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLY].rows);
710
711                         /* 2 bits to encode */
712                         field_size = rtsize (n, 16-2);
713                         break;
714
715                         /*
716                          * Implementation: File, AssemblyRef, ExportedType
717                          */
718                 case MONO_MT_IMPL_IDX:
719                         n = MAX (meta->tables [MONO_TABLE_FILE].rows,
720                                  meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
721                         n = MAX (n, meta->tables [MONO_TABLE_EXPORTEDTYPE].rows);
722
723                         /* 2 bits to encode tag */
724                         field_size = rtsize (n, 16-2);
725                         break;
726
727                         /*
728                          * HasFieldMarshall: FieldDef, ParamDef
729                          */
730                 case MONO_MT_HFM_IDX:
731                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
732                                  meta->tables [MONO_TABLE_PARAM].rows);
733
734                         /* 1 bit used to encode tag */
735                         field_size = rtsize (n, 16-1);
736                         break;
737
738                         /*
739                          * MemberForwarded: FieldDef, MethodDef
740                          */
741                 case MONO_MT_MF_IDX:
742                         n = MAX (meta->tables [MONO_TABLE_FIELD].rows,
743                                  meta->tables [MONO_TABLE_METHOD].rows);
744
745                         /* 1 bit used to encode tag */
746                         field_size = rtsize (n, 16-1);
747                         break;
748
749                         /*
750                          * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
751                          * LAMESPEC
752                          * It is TypeDef, _TypeRef_, TypeSpec, instead.
753                          */
754                 case MONO_MT_TDOR_IDX:
755                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
756                                  meta->tables [MONO_TABLE_TYPEREF].rows);
757                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
758
759                         /* 2 bits to encode */
760                         field_size = rtsize (n, 16-2);
761                         break;
762
763                         /*
764                          * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
765                          */
766                 case MONO_MT_MRP_IDX:
767                         n = MAX (meta->tables [MONO_TABLE_TYPEDEF].rows,
768                                  meta->tables [MONO_TABLE_TYPEREF].rows);
769                         n = MAX (n, meta->tables [MONO_TABLE_METHOD].rows);
770                         n = MAX (n, meta->tables [MONO_TABLE_MODULEREF].rows);
771                         n = MAX (n, meta->tables [MONO_TABLE_TYPESPEC].rows);
772                         n = MAX (n, meta->tables [MONO_TABLE_MEMBERREF].rows);
773
774                         /* 3 bits to encode */
775                         field_size = rtsize (n, 16 - 3);
776                         break;
777                         
778                         /*
779                          * MethodDefOrRef: MethodDef, MemberRef
780                          */
781                 case MONO_MT_MDOR_IDX:
782                         n = MAX (meta->tables [MONO_TABLE_METHOD].rows,
783                                  meta->tables [MONO_TABLE_MEMBERREF].rows);
784
785                         /* 1 bit used to encode tag */
786                         field_size = rtsize (n, 16-1);
787                         break;
788                         
789                         /*
790                          * HasSemantics: Property, Event
791                          */
792                 case MONO_MT_HS_IDX:
793                         n = MAX (meta->tables [MONO_TABLE_PROPERTY].rows,
794                                  meta->tables [MONO_TABLE_EVENT].rows);
795
796                         /* 1 bit used to encode tag */
797                         field_size = rtsize (n, 16-1);
798                         break;
799
800                         /*
801                          * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
802                          */
803                 case MONO_MT_RS_IDX:
804                         n = MAX (meta->tables [MONO_TABLE_MODULE].rows,
805                                  meta->tables [MONO_TABLE_MODULEREF].rows);
806                         n = MAX (n, meta->tables [MONO_TABLE_ASSEMBLYREF].rows);
807                         n = MAX (n, meta->tables [MONO_TABLE_TYPEREF].rows);
808
809                         /* 2 bits used to encode tag (ECMA spec claims 3) */
810                         field_size = rtsize (n, 16 - 2);
811                         break;
812                 }
813
814                 /*
815                  * encode field size as follows (we just need to
816                  * distinguish them).
817                  *
818                  * 4 -> 3
819                  * 2 -> 1
820                  * 1 -> 0
821                  */
822                 bitfield |= (field_size-1) << shift;
823                 shift += 2;
824                 size += field_size;
825                 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
826         }
827
828         *result_bitfield = (i << 24) | bitfield;
829         return size;
830 }
831
832 /**
833  * mono_metadata_compute_table_bases:
834  * @meta: metadata context to compute table values
835  *
836  * Computes the table bases for the metadata structure.
837  * This is an internal function used by the image loader code.
838  */
839 void
840 mono_metadata_compute_table_bases (MonoImage *meta)
841 {
842         int i;
843         const char *base = meta->tables_base;
844         
845         for (i = 0; i < MONO_TABLE_NUM; i++) {
846                 MonoTableInfo *table = &meta->tables [i];
847                 if (table->rows == 0)
848                         continue;
849
850                 table->row_size = mono_metadata_compute_size (meta, i, &table->size_bitfield);
851                 table->base = base;
852                 base += table->rows * table->row_size;
853         }
854 }
855
856 /**
857  * mono_metadata_locate:
858  * @meta: metadata context
859  * @table: table code.
860  * @idx: index of element to retrieve from @table.
861  *
862  * Returns: a pointer to the @idx element in the metadata table
863  * whose code is @table.
864  */
865 const char *
866 mono_metadata_locate (MonoImage *meta, int table, int idx)
867 {
868         /* idx == 0 refers always to NULL */
869         g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, "");
870            
871         return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
872 }
873
874 /**
875  * mono_metadata_locate_token:
876  * @meta: metadata context
877  * @token: metadata token
878  *
879  * Returns: a pointer to the data in the metadata represented by the
880  * token #token.
881  */
882 const char *
883 mono_metadata_locate_token (MonoImage *meta, guint32 token)
884 {
885         return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
886 }
887
888 /**
889  * mono_metadata_string_heap:
890  * @meta: metadata context
891  * @index: index into the string heap.
892  *
893  * Returns: an in-memory pointer to the @index in the string heap.
894  */
895 const char *
896 mono_metadata_string_heap (MonoImage *meta, guint32 index)
897 {
898         g_return_val_if_fail (index < meta->heap_strings.size, "");
899         return meta->heap_strings.data + index;
900 }
901
902 /**
903  * mono_metadata_user_string:
904  * @meta: metadata context
905  * @index: index into the user string heap.
906  *
907  * Returns: an in-memory pointer to the @index in the user string heap ("#US").
908  */
909 const char *
910 mono_metadata_user_string (MonoImage *meta, guint32 index)
911 {
912         g_return_val_if_fail (index < meta->heap_us.size, "");
913         return meta->heap_us.data + index;
914 }
915
916 /**
917  * mono_metadata_blob_heap:
918  * @meta: metadata context
919  * @index: index into the blob.
920  *
921  * Returns: an in-memory pointer to the @index in the Blob heap.
922  */
923 const char *
924 mono_metadata_blob_heap (MonoImage *meta, guint32 index)
925 {
926         g_return_val_if_fail (index < meta->heap_blob.size, "");
927         return meta->heap_blob.data + index;
928 }
929
930 /**
931  * mono_metadata_guid_heap:
932  * @meta: metadata context
933  * @index: index into the guid heap.
934  *
935  * Returns: an in-memory pointer to the @index in the guid heap.
936  */
937 const char *
938 mono_metadata_guid_heap (MonoImage *meta, guint32 index)
939 {
940         --index;
941         index *= 16; /* adjust for guid size and 1-based index */
942         g_return_val_if_fail (index < meta->heap_guid.size, "");
943         return meta->heap_guid.data + index;
944 }
945
946 static const unsigned char *
947 dword_align (const unsigned char *ptr)
948 {
949 #if SIZEOF_VOID_P == 8
950         return (const unsigned char *) (((guint64) (ptr + 3)) & ~3);
951 #else
952         return (const unsigned char *) (((guint32) (ptr + 3)) & ~3);
953 #endif
954 }
955
956 /**
957  * mono_metadata_decode_row:
958  * @t: table to extract information from.
959  * @idx: index in table.
960  * @res: array of @res_size cols to store the results in
961  *
962  * This decompresses the metadata element @idx in table @t
963  * into the guint32 @res array that has res_size elements
964  */
965 void
966 mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size)
967 {
968         guint32 bitfield = t->size_bitfield;
969         int i, count = mono_metadata_table_count (bitfield);
970         const char *data;
971
972         g_assert (idx < t->rows);
973         data = t->base + idx * t->row_size;
974         
975         g_assert (res_size == count);
976
977         for (i = 0; i < count; i++) {
978                 int n = mono_metadata_table_size (bitfield, i);
979
980                 switch (n){
981                 case 1:
982                         res [i] = *data; break;
983                 case 2:
984                         res [i] = read16 (data); break;
985                 case 4:
986                         res [i] = read32 (data); break;
987                 default:
988                         g_assert_not_reached ();
989                 }
990                 data += n;
991         }
992 }
993
994 /**
995  * mono_metadata_decode_row_col:
996  * @t: table to extract information from.
997  * @idx: index for row in table.
998  * @col: column in the row.
999  *
1000  * This function returns the value of column @col from the @idx
1001  * row in the table @t.
1002  */
1003 guint32
1004 mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
1005 {
1006         guint32 bitfield = t->size_bitfield;
1007         int i;
1008         register const char *data; 
1009         register int n;
1010         
1011         g_assert (idx < t->rows);
1012         g_assert (col < mono_metadata_table_count (bitfield));
1013         data = t->base + idx * t->row_size;
1014
1015         n = mono_metadata_table_size (bitfield, 0);
1016         for (i = 0; i < col; ++i) {
1017                 data += n;
1018                 n = mono_metadata_table_size (bitfield, i + 1);
1019         }
1020         switch (n) {
1021         case 1:
1022                 return *data;
1023         case 2:
1024                 return read16 (data);
1025         case 4:
1026                 return read32 (data);
1027         default:
1028                 g_assert_not_reached ();
1029         }
1030         return 0;
1031 }
1032
1033 /**
1034  * mono_metadata_decode_blob_size:
1035  * @ptr: pointer to a blob object
1036  * @rptr: the new position of the pointer
1037  *
1038  * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
1039  *
1040  * Returns: the size of the blob object
1041  */
1042 guint32
1043 mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
1044 {
1045         const unsigned char *ptr = (const unsigned char *)xptr;
1046         guint32 size;
1047         
1048         if ((*ptr & 0x80) == 0){
1049                 size = ptr [0] & 0x7f;
1050                 ptr++;
1051         } else if ((*ptr & 0x40) == 0){
1052                 size = ((ptr [0] & 0x3f) << 8) + ptr [1];
1053                 ptr += 2;
1054         } else {
1055                 size = ((ptr [0] & 0x1f) << 24) +
1056                         (ptr [1] << 16) +
1057                         (ptr [2] << 8) +
1058                         ptr [3];
1059                 ptr += 4;
1060         }
1061         if (rptr)
1062                 *rptr = (char*)ptr;
1063         return size;
1064 }
1065
1066 /**
1067  * mono_metadata_decode_value:
1068  * @ptr: pointer to decode from
1069  * @rptr: the new position of the pointer
1070  *
1071  * This routine decompresses 32-bit values as specified in the "Blob and
1072  * Signature" section (22.2)
1073  *
1074  * Returns: the decoded value
1075  */
1076 guint32
1077 mono_metadata_decode_value (const char *_ptr, const char **rptr)
1078 {
1079         const unsigned char *ptr = (const unsigned char *) _ptr;
1080         unsigned char b = *ptr;
1081         guint32 len;
1082         
1083         if ((b & 0x80) == 0){
1084                 len = b;
1085                 ++ptr;
1086         } else if ((b & 0x40) == 0){
1087                 len = ((b & 0x3f) << 8 | ptr [1]);
1088                 ptr += 2;
1089         } else {
1090                 len = ((b & 0x1f) << 24) |
1091                         (ptr [1] << 16) |
1092                         (ptr [2] << 8) |
1093                         ptr [3];
1094                 ptr += 4;
1095         }
1096         if (rptr)
1097                 *rptr = (char*)ptr;
1098         
1099         return len;
1100 }
1101
1102 /**
1103  * mono_metadata_decode_signed_value:
1104  * @ptr: pointer to decode from
1105  * @rptr: the new position of the pointer
1106  *
1107  * This routine decompresses 32-bit signed values
1108  * (not specified in the spec)
1109  *
1110  * Returns: the decoded value
1111  */
1112 gint32
1113 mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
1114 {
1115         guint32 uval = mono_metadata_decode_value (ptr, rptr);
1116         gint32 ival = uval >> 1;
1117         if (!(uval & 1))
1118                 return ival;
1119         /* ival is a truncated 2's complement negative number.  */
1120         if (ival < 0x40)
1121                 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1122                 return ival - 0x40;
1123         if (ival < 0x2000)
1124                 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1125                 return ival - 0x2000;
1126         if (ival < 0x10000000)
1127                 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1128                 return ival - 0x10000000;
1129         g_assert (ival < 0x20000000);
1130         g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival, uval);
1131         return ival - 0x20000000;
1132 }
1133
1134 /* 
1135  * Translates the given 1-based index into the Method, Field, Event, or Param tables
1136  * using the *Ptr tables in uncompressed metadata, if they are available.
1137  *
1138  * FIXME: The caller is not forced to call this function, which is error-prone, since 
1139  * forgetting to call it would only show up as a bug on uncompressed metadata.
1140  */
1141 guint32
1142 mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
1143 {
1144         if (!image->uncompressed_metadata)
1145                 return idx;
1146
1147         switch (table) {
1148         case MONO_TABLE_METHOD:
1149                 if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
1150                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
1151                 else
1152                         return idx;
1153         case MONO_TABLE_FIELD:
1154                 if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
1155                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
1156                 else
1157                         return idx;
1158         case MONO_TABLE_EVENT:
1159                 if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
1160                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
1161                 else
1162                         return idx;
1163         case MONO_TABLE_PROPERTY:
1164                 if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
1165                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
1166                 else
1167                         return idx;
1168         case MONO_TABLE_PARAM:
1169                 if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
1170                         return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
1171                 else
1172                         return idx;
1173         default:
1174                 return idx;
1175         }
1176 }
1177
1178 /**
1179  * mono_metadata_decode_table_row:
1180  *
1181  *   Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
1182  * uncompressed metadata into account, so it should be used to access the
1183  * Method, Field, Param and Event tables when the access is made from metadata, i.e.
1184  * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
1185  */
1186 void
1187 mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
1188 {
1189         if (image->uncompressed_metadata)
1190                 idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1191
1192         mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
1193 }
1194
1195 /**
1196  * mono_metadata_decode_table_row_col:
1197  *
1198  *   Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
1199  * uncompressed metadata into account, so it should be used to access the
1200  * Method, Field, Param and Event tables.
1201  */
1202 guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
1203 {
1204         if (image->uncompressed_metadata)
1205                 idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1206
1207         return mono_metadata_decode_row_col (&image->tables [table], idx, col);
1208 }
1209
1210 /*
1211  * mono_metadata_parse_typedef_or_ref:
1212  * @m: a metadata context.
1213  * @ptr: a pointer to an encoded TypedefOrRef in @m
1214  * @rptr: pointer updated to match the end of the decoded stream
1215  *
1216  * Returns: a token valid in the @m metadata decoded from
1217  * the compressed representation.
1218  */
1219 guint32
1220 mono_metadata_parse_typedef_or_ref (MonoImage *m, const char *ptr, const char **rptr)
1221 {
1222         guint32 token;
1223         token = mono_metadata_decode_value (ptr, &ptr);
1224         if (rptr)
1225                 *rptr = ptr;
1226         return mono_metadata_token_from_dor (token);
1227 }
1228
1229 /*
1230  * mono_metadata_parse_custom_mod:
1231  * @m: a metadata context.
1232  * @dest: storage where the info about the custom modifier is stored (may be NULL)
1233  * @ptr: a pointer to (possibly) the start of a custom modifier list
1234  * @rptr: pointer updated to match the end of the decoded stream
1235  *
1236  * Checks if @ptr points to a type custom modifier compressed representation.
1237  *
1238  * Returns: #TRUE if a custom modifier was found, #FALSE if not.
1239  */
1240 int
1241 mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
1242 {
1243         MonoCustomMod local;
1244         if ((*ptr == MONO_TYPE_CMOD_OPT) || (*ptr == MONO_TYPE_CMOD_REQD)) {
1245                 if (!dest)
1246                         dest = &local;
1247                 dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
1248                 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, rptr);
1249                 return TRUE;
1250         }
1251         return FALSE;
1252 }
1253
1254 /*
1255  * mono_metadata_parse_array_full:
1256  * @m: a metadata context.
1257  * @ptr: a pointer to an encoded array description.
1258  * @rptr: pointer updated to match the end of the decoded stream
1259  *
1260  * Decodes the compressed array description found in the metadata @m at @ptr.
1261  *
1262  * Returns: a #MonoArrayType structure describing the array type
1263  * and dimensions. Memory is allocated from the image mempool.
1264  *
1265  * LOCKING: Acquires the loader lock
1266  */
1267 MonoArrayType *
1268 mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container,
1269                                 const char *ptr, const char **rptr)
1270 {
1271         int i;
1272         MonoArrayType *array;
1273         MonoType *etype;
1274         
1275         array = mono_image_alloc0 (m, sizeof (MonoArrayType));
1276         etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
1277         if (!etype)
1278                 return NULL;
1279         array->eklass = mono_class_from_mono_type (etype);
1280         array->rank = mono_metadata_decode_value (ptr, &ptr);
1281
1282         array->numsizes = mono_metadata_decode_value (ptr, &ptr);
1283         if (array->numsizes)
1284                 array->sizes = g_new0 (int, array->numsizes);
1285         for (i = 0; i < array->numsizes; ++i)
1286                 array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
1287
1288         array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
1289         if (array->numlobounds)
1290                 array->lobounds = g_new0 (int, array->numlobounds);
1291         for (i = 0; i < array->numlobounds; ++i)
1292                 array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr);
1293
1294         if (rptr)
1295                 *rptr = ptr;
1296         return array;
1297 }
1298
1299 MonoArrayType *
1300 mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
1301 {
1302         return mono_metadata_parse_array_full (m, NULL, ptr, rptr);
1303 }
1304
1305 /*
1306  * mono_metadata_free_array:
1307  * @array: array description
1308  *
1309  * Frees the array description returned from mono_metadata_parse_array().
1310  */
1311 void
1312 mono_metadata_free_array (MonoArrayType *array)
1313 {
1314         g_free (array->sizes);
1315         g_free (array->lobounds);
1316         g_free (array);
1317 }
1318
1319 /*
1320  * need to add common field and param attributes combinations:
1321  * [out] param
1322  * public static
1323  * public static literal
1324  * private
1325  * private static
1326  * private static literal
1327  */
1328 static const MonoType
1329 builtin_types[] = {
1330         /* data, attrs, type,              nmods, byref, pinned */
1331         {{NULL}, 0,     MONO_TYPE_VOID,    0,     0,     0},
1332         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     0,     0},
1333         {{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     1,     0},
1334         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     0,     0},
1335         {{NULL}, 0,     MONO_TYPE_CHAR,    0,     1,     0},
1336         {{NULL}, 0,     MONO_TYPE_I1,      0,     0,     0},
1337         {{NULL}, 0,     MONO_TYPE_I1,      0,     1,     0},
1338         {{NULL}, 0,     MONO_TYPE_U1,      0,     0,     0},
1339         {{NULL}, 0,     MONO_TYPE_U1,      0,     1,     0},
1340         {{NULL}, 0,     MONO_TYPE_I2,      0,     0,     0},
1341         {{NULL}, 0,     MONO_TYPE_I2,      0,     1,     0},
1342         {{NULL}, 0,     MONO_TYPE_U2,      0,     0,     0},
1343         {{NULL}, 0,     MONO_TYPE_U2,      0,     1,     0},
1344         {{NULL}, 0,     MONO_TYPE_I4,      0,     0,     0},
1345         {{NULL}, 0,     MONO_TYPE_I4,      0,     1,     0},
1346         {{NULL}, 0,     MONO_TYPE_U4,      0,     0,     0},
1347         {{NULL}, 0,     MONO_TYPE_U4,      0,     1,     0},
1348         {{NULL}, 0,     MONO_TYPE_I8,      0,     0,     0},
1349         {{NULL}, 0,     MONO_TYPE_I8,      0,     1,     0},
1350         {{NULL}, 0,     MONO_TYPE_U8,      0,     0,     0},
1351         {{NULL}, 0,     MONO_TYPE_U8,      0,     1,     0},
1352         {{NULL}, 0,     MONO_TYPE_R4,      0,     0,     0},
1353         {{NULL}, 0,     MONO_TYPE_R4,      0,     1,     0},
1354         {{NULL}, 0,     MONO_TYPE_R8,      0,     0,     0},
1355         {{NULL}, 0,     MONO_TYPE_R8,      0,     1,     0},
1356         {{NULL}, 0,     MONO_TYPE_STRING,  0,     0,     0},
1357         {{NULL}, 0,     MONO_TYPE_STRING,  0,     1,     0},
1358         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     0,     0},
1359         {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     1,     0},
1360         {{NULL}, 0,     MONO_TYPE_TYPEDBYREF,  0,     0,     0},
1361         {{NULL}, 0,     MONO_TYPE_I,       0,     0,     0},
1362         {{NULL}, 0,     MONO_TYPE_I,       0,     1,     0},
1363         {{NULL}, 0,     MONO_TYPE_U,       0,     0,     0},
1364         {{NULL}, 0,     MONO_TYPE_U,       0,     1,     0},
1365 };
1366
1367 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1368
1369 static GHashTable *type_cache = NULL;
1370 static GHashTable *generic_inst_cache = NULL;
1371 static GHashTable *generic_class_cache = NULL;
1372 static int next_generic_inst_id = 0;
1373
1374 /*
1375  * Protected by the loader lock.
1376  * It has a MonoMethodInflated* as key and value.
1377  * The key lookup will just access the declaring and context fields
1378  */
1379 static GHashTable *generic_method_cache = NULL;
1380
1381 /*
1382  * Protected by the loader lock.
1383  * It has a MonoInflatedMethodSignature* as key and value.
1384  */
1385 static GHashTable *generic_signature_cache = NULL;
1386
1387 static guint mono_generic_class_hash (gconstpointer data);
1388
1389 /*
1390  * MonoTypes with modifies are never cached, so we never check or use that field.
1391  */
1392 static guint
1393 mono_type_hash (gconstpointer data)
1394 {
1395         const MonoType *type = (const MonoType *) data;
1396         if (type->type == MONO_TYPE_GENERICINST)
1397                 return mono_generic_class_hash (type->data.generic_class);
1398         else
1399                 return type->type | (type->byref << 8) | (type->attrs << 9);
1400 }
1401
1402 static gint
1403 mono_type_equal (gconstpointer ka, gconstpointer kb)
1404 {
1405         const MonoType *a = (const MonoType *) ka;
1406         const MonoType *b = (const MonoType *) kb;
1407         
1408         if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
1409                 return 0;
1410         /* need other checks */
1411         return 1;
1412 }
1413
1414 guint
1415 mono_metadata_generic_inst_hash (gconstpointer data)
1416 {
1417         const MonoGenericInst *ginst = (const MonoGenericInst *) data;
1418         guint hash = 0;
1419         int i;
1420         
1421         for (i = 0; i < ginst->type_argc; ++i) {
1422                 hash *= 13;
1423                 hash += mono_metadata_type_hash (ginst->type_argv [i]);
1424         }
1425
1426         return hash ^ (ginst->is_open << 8);
1427 }
1428
1429 static gboolean
1430 mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b, gboolean signature_only)
1431 {
1432         int i;
1433
1434         if (a->id && b->id) {
1435                 if (a->id == b->id)
1436                         return TRUE;
1437                 if (!signature_only)
1438                         return FALSE;
1439         }
1440
1441         if (a->is_open != b->is_open || a->type_argc != b->type_argc)
1442                 return FALSE;
1443         for (i = 0; i < a->type_argc; ++i) {
1444                 if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], signature_only))
1445                         return FALSE;
1446         }
1447         return TRUE;
1448 }
1449
1450 gboolean
1451 mono_metadata_generic_inst_equal (gconstpointer ka, gconstpointer kb)
1452 {
1453         const MonoGenericInst *a = (const MonoGenericInst *) ka;
1454         const MonoGenericInst *b = (const MonoGenericInst *) kb;
1455
1456         return mono_generic_inst_equal_full (a, b, FALSE);
1457 }
1458
1459 static guint
1460 mono_generic_class_hash (gconstpointer data)
1461 {
1462         const MonoGenericClass *gclass = (const MonoGenericClass *) data;
1463         guint hash = mono_metadata_type_hash (&gclass->container_class->byval_arg);
1464
1465         hash *= 13;
1466         hash += gclass->is_tb_open;
1467         hash += mono_metadata_generic_context_hash (&gclass->context);
1468
1469         return hash;
1470 }
1471
1472 static gboolean
1473 mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
1474 {
1475         const MonoGenericClass *a = (const MonoGenericClass *) ka;
1476         const MonoGenericClass *b = (const MonoGenericClass *) kb;
1477
1478         return _mono_metadata_generic_class_equal (a, b, FALSE);
1479 }
1480
1481 /**
1482  * mono_metadata_init:
1483  *
1484  * Initialize the global variables of this module.
1485  * This is a Mono runtime internal function.
1486  */
1487 void
1488 mono_metadata_init (void)
1489 {
1490         int i;
1491
1492         type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
1493         generic_inst_cache = g_hash_table_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst);
1494         generic_class_cache = g_hash_table_new_full (mono_generic_class_hash, mono_generic_class_equal, NULL, (GDestroyNotify)free_generic_class);
1495
1496         for (i = 0; i < NBUILTIN_TYPES (); ++i)
1497                 g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
1498 }
1499
1500 /**
1501  * mono_metadata_cleanup:
1502  *
1503  * Free all resources used by this module.
1504  * This is a Mono runtime internal function.
1505  */
1506 void
1507 mono_metadata_cleanup (void)
1508 {
1509         g_hash_table_destroy (type_cache);
1510         g_hash_table_destroy (generic_inst_cache);
1511         g_hash_table_destroy (generic_class_cache);
1512         if (generic_method_cache)
1513                 g_hash_table_destroy (generic_method_cache);
1514         if (generic_signature_cache)
1515                 g_hash_table_destroy (generic_signature_cache);
1516         type_cache = NULL;
1517         generic_inst_cache = NULL;
1518         generic_class_cache = NULL;
1519         generic_method_cache = NULL;
1520         generic_signature_cache = NULL;
1521 }
1522
1523 /**
1524  * mono_metadata_parse_type:
1525  * @m: metadata context
1526  * @mode: king of type that may be found at @ptr
1527  * @opt_attrs: optional attributes to store in the returned type
1528  * @ptr: pointer to the type representation
1529  * @rptr: pointer updated to match the end of the decoded stream
1530  * 
1531  * Decode a compressed type description found at @ptr in @m.
1532  * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
1533  * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
1534  * This function can be used to decode type descriptions in method signatures,
1535  * field signatures, locals signatures etc.
1536  *
1537  * To parse a generic type, `generic_container' points to the current class'es
1538  * (the `generic_container' field in the MonoClass) or the current generic method's
1539  * (the `generic_container' field in the MonoMethodNormal) generic container.
1540  * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
1541  * this MonoGenericContainer.
1542  * This is a Mono runtime internal function.
1543  *
1544  * LOCKING: Acquires the loader lock.
1545  *
1546  * Returns: a #MonoType structure representing the decoded type.
1547  */
1548 MonoType*
1549 mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
1550                                short opt_attrs, const char *ptr, const char **rptr)
1551 {
1552         MonoType *type, *cached;
1553         MonoType stype;
1554         gboolean byref = FALSE;
1555         gboolean pinned = FALSE;
1556         const char *tmp_ptr;
1557         int count = 0;
1558         gboolean found;
1559
1560         /*
1561          * According to the spec, custom modifiers should come before the byref
1562          * flag, but the IL produced by ilasm from the following signature:
1563          *   object modopt(...) &
1564          * starts with a byref flag, followed by the modifiers. (bug #49802)
1565          * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1566          * it would be better to treat byref as real type constructor instead of
1567          * a modifier...
1568          * Also, pinned should come before anything else, but some MSV++ produced
1569          * assemblies violate this (#bug 61990).
1570          */
1571
1572         /* Count the modifiers first */
1573         tmp_ptr = ptr;
1574         found = TRUE;
1575         while (found) {
1576                 switch (*tmp_ptr) {
1577                 case MONO_TYPE_PINNED:
1578                 case MONO_TYPE_BYREF:
1579                         ++tmp_ptr;
1580                         break;
1581                 case MONO_TYPE_CMOD_REQD:
1582                 case MONO_TYPE_CMOD_OPT:
1583                         count ++;
1584                         mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
1585                         break;
1586                 default:
1587                         found = FALSE;
1588                 }
1589         }
1590
1591         if (count) {
1592                 type = mono_image_alloc0 (m, sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
1593                 type->num_mods = count;
1594                 if (count > 64)
1595                         g_warning ("got more than 64 modifiers in type");
1596         } else {
1597                 type = &stype;
1598                 memset (type, 0, sizeof (MonoType));
1599         }
1600
1601         /* Parse pinned, byref and custom modifiers */
1602         found = TRUE;
1603         count = 0;
1604         while (found) {
1605                 switch (*ptr) {
1606                 case MONO_TYPE_PINNED:
1607                         pinned = TRUE;
1608                         ++ptr;
1609                         break;
1610                 case MONO_TYPE_BYREF:
1611                         byref = TRUE;
1612                         ++ptr;
1613                         break;
1614                 case MONO_TYPE_CMOD_REQD:
1615                 case MONO_TYPE_CMOD_OPT:
1616                         mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
1617                         count ++;
1618                         break;
1619                 default:
1620                         found = FALSE;
1621                 }
1622         }
1623         
1624         type->attrs = opt_attrs;
1625         type->byref = byref;
1626         type->pinned = pinned ? 1 : 0;
1627
1628         if (!do_mono_metadata_parse_type (type, m, container, ptr, &ptr)) {
1629                 return NULL;
1630         }
1631
1632         if (rptr)
1633                 *rptr = ptr;
1634
1635         if (!type->num_mods) {
1636                 /* no need to free type here, because it is on the stack */
1637                 if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
1638                         MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
1639
1640                         /* Consider the case:
1641
1642                              class Foo<T> { class Bar {} }
1643                              class Test : Foo<Test>.Bar {}
1644
1645                            When Foo<Test> is being expanded, 'Test' isn't yet initialized.  It's actually in
1646                            a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1647
1648                            We ensure that the MonoClass is in a state that we can canonicalize to:
1649
1650                              klass->byval_arg.data.klass == klass
1651                              klass->this_arg.data.klass == klass
1652
1653                            If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1654
1655                            LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1656                                     of a MonoClass which currently holds the loader lock.  'type' is local.
1657                         */
1658                         if (ret->data.klass == type->data.klass) {
1659                                 return ret;
1660                         }
1661                 }
1662                 /* No need to use locking since nobody is modifying the hash table */
1663                 if ((cached = g_hash_table_lookup (type_cache, type))) {
1664                         return cached;
1665                 }
1666         }
1667         
1668         /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1669         
1670         if (type == &stype) {
1671                 type = mono_image_alloc (m, sizeof (MonoType));
1672                 memcpy (type, &stype, sizeof (MonoType));
1673         }
1674         return type;
1675 }
1676
1677 /*
1678  * LOCKING: Acquires the loader lock.
1679  */
1680 MonoType*
1681 mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
1682                           const char *ptr, const char **rptr)
1683 {
1684         return mono_metadata_parse_type_full (m, NULL, mode, opt_attrs, ptr, rptr);
1685 }
1686
1687 /*
1688  * mono_metadata_get_param_attrs:
1689  *
1690  *   Return the parameter attributes for the method whose MethodDef index is DEF. The 
1691  * returned memory needs to be freed by the caller. If all the param attributes are
1692  * 0, then NULL is returned.
1693  */
1694 int*
1695 mono_metadata_get_param_attrs (MonoImage *m, int def)
1696 {
1697         MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1698         MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1699         guint32 cols [MONO_PARAM_SIZE];
1700         guint lastp, i, param_index = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def - 1, MONO_METHOD_PARAMLIST);
1701         int *pattrs = NULL;
1702
1703         if (def < methodt->rows)
1704                 lastp = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def, MONO_METHOD_PARAMLIST);
1705         else
1706                 lastp = paramt->rows + 1;
1707
1708         for (i = param_index; i < lastp; ++i) {
1709                 mono_metadata_decode_row (&m->tables [MONO_TABLE_PARAM], i - 1, cols, MONO_PARAM_SIZE);
1710                 if (cols [MONO_PARAM_FLAGS]) {
1711                         if (!pattrs)
1712                                 pattrs = g_new0 (int, 1 + (lastp - param_index));
1713                         pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
1714                 }
1715         }
1716
1717         return pattrs;
1718 }
1719
1720 /*
1721  * mono_metadata_parse_signature_full:
1722  * @image: metadata context
1723  * @generic_container: generic container
1724  * @toke: metadata token
1725  *
1726  * Decode a method signature stored in the STANDALONESIG table
1727  *
1728  * LOCKING: Assumes the loader lock is held.
1729  *
1730  * Returns: a MonoMethodSignature describing the signature.
1731  */
1732 MonoMethodSignature*
1733 mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 token)
1734 {
1735         MonoTableInfo *tables = image->tables;
1736         guint32 idx = mono_metadata_token_index (token);
1737         guint32 sig;
1738         const char *ptr;
1739
1740         if (image->dynamic)
1741                 return mono_lookup_dynamic_token (image, token, NULL);
1742
1743         g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
1744                 
1745         sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
1746
1747         ptr = mono_metadata_blob_heap (image, sig);
1748         mono_metadata_decode_blob_size (ptr, &ptr);
1749
1750         return mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL); 
1751 }
1752
1753 /*
1754  * mono_metadata_parse_signature:
1755  * @image: metadata context
1756  * @toke: metadata token
1757  *
1758  * Decode a method signature stored in the STANDALONESIG table
1759  *
1760  * Returns: a MonoMethodSignature describing the signature.
1761  */
1762 MonoMethodSignature*
1763 mono_metadata_parse_signature (MonoImage *image, guint32 token)
1764 {
1765         return mono_metadata_parse_signature_full (image, NULL, token);
1766 }
1767
1768 /*
1769  * mono_metadata_signature_alloc:
1770  * @image: metadata context
1771  * @nparmas: number of parameters in the signature
1772  *
1773  * Allocate a MonoMethodSignature structure with the specified number of params.
1774  * The return type and the params types need to be filled later.
1775  * This is a Mono runtime internal function.
1776  *
1777  * LOCKING: Assumes the loader lock is held.
1778  *
1779  * Returns: the new MonoMethodSignature structure.
1780  */
1781 MonoMethodSignature*
1782 mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
1783 {
1784         MonoMethodSignature *sig;
1785
1786         sig = mono_image_alloc0 (m, sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
1787         sig->param_count = nparams;
1788         sig->sentinelpos = -1;
1789
1790         return sig;
1791 }
1792
1793 static MonoMethodSignature*
1794 mono_metadata_signature_dup_internal (MonoImage *image, MonoMemPool *mp, MonoMethodSignature *sig)
1795 {
1796         int sigsize;
1797         MonoMethodSignature *ret;
1798         sigsize = sizeof (MonoMethodSignature) + (sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *);
1799
1800         if (image) {
1801                 ret = mono_image_alloc (image, sigsize);
1802         } else if (mp) {
1803                 ret = mono_mempool_alloc (mp, sigsize);
1804         } else {
1805                 ret = g_malloc (sigsize);
1806         }
1807         memcpy (ret, sig, sigsize);
1808         return ret;
1809 }
1810
1811 MonoMethodSignature*
1812 mono_metadata_signature_dup_full (MonoImage *image, MonoMethodSignature *sig)
1813 {
1814         return mono_metadata_signature_dup_internal (image, NULL, sig);
1815 }
1816
1817 /*The mempool is accessed without synchronization*/
1818 MonoMethodSignature*
1819 mono_metadata_signature_dup_mempool (MonoMemPool *mp, MonoMethodSignature *sig)
1820 {
1821         return mono_metadata_signature_dup_internal (NULL, mp, sig);
1822 }
1823
1824 /*
1825  * mono_metadata_signature_dup:
1826  * @sig: method signature
1827  *
1828  * Duplicate an existing MonoMethodSignature so it can be modified.
1829  * This is a Mono runtime internal function.
1830  *
1831  * Returns: the new MonoMethodSignature structure.
1832  */
1833 MonoMethodSignature*
1834 mono_metadata_signature_dup (MonoMethodSignature *sig)
1835 {
1836         return mono_metadata_signature_dup_full (NULL, sig);
1837 }
1838
1839 /*
1840  * mono_metadata_signature_size:
1841  *
1842  *   Return the amount of memory allocated to SIG.
1843  */
1844 guint32
1845 mono_metadata_signature_size (MonoMethodSignature *sig)
1846 {
1847         return sizeof (MonoMethodSignature) + (sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *);
1848 }
1849
1850 /*
1851  * mono_metadata_parse_method_signature:
1852  * @m: metadata context
1853  * @generic_container: generics container
1854  * @def: the MethodDef index or 0 for Ref signatures.
1855  * @ptr: pointer to the signature metadata representation
1856  * @rptr: pointer updated to match the end of the decoded stream
1857  *
1858  * Decode a method signature stored at @ptr.
1859  * This is a Mono runtime internal function.
1860  *
1861  * LOCKING: Assumes the loader lock is held.
1862  *
1863  * Returns: a MonoMethodSignature describing the signature.
1864  */
1865 MonoMethodSignature *
1866 mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container,
1867                                            int def, const char *ptr, const char **rptr)
1868 {
1869         MonoMethodSignature *method;
1870         int i, *pattrs = NULL;
1871         guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
1872         guint32 gen_param_count = 0;
1873         gboolean is_open = FALSE;
1874
1875         if (*ptr & 0x10)
1876                 gen_param_count = 1;
1877         if (*ptr & 0x20)
1878                 hasthis = 1;
1879         if (*ptr & 0x40)
1880                 explicit_this = 1;
1881         call_convention = *ptr & 0x0F;
1882         ptr++;
1883         if (gen_param_count)
1884                 gen_param_count = mono_metadata_decode_value (ptr, &ptr);
1885         param_count = mono_metadata_decode_value (ptr, &ptr);
1886
1887         if (def)
1888                 pattrs = mono_metadata_get_param_attrs (m, def);
1889         method = mono_metadata_signature_alloc (m, param_count);
1890         method->hasthis = hasthis;
1891         method->explicit_this = explicit_this;
1892         method->call_convention = call_convention;
1893         method->generic_param_count = gen_param_count;
1894
1895         if (call_convention != 0xa) {
1896                 method->ret = mono_metadata_parse_type_full (m, container, MONO_PARSE_RET, pattrs ? pattrs [0] : 0, ptr, &ptr);
1897                 if (!method->ret) {
1898                         mono_metadata_free_method_signature (method);
1899                         g_free (pattrs);
1900                         return NULL;
1901                 }
1902                 is_open = mono_class_is_open_constructed_type (method->ret);
1903         }
1904
1905         for (i = 0; i < method->param_count; ++i) {
1906                 if (*ptr == MONO_TYPE_SENTINEL) {
1907                         if (method->call_convention != MONO_CALL_VARARG || def)
1908                                 g_error ("found sentinel for methoddef or no vararg method");
1909                         if (method->sentinelpos >= 0)
1910                                 g_error ("found sentinel twice in the same signature");
1911                         method->sentinelpos = i;
1912                         ptr++;
1913                 }
1914                 method->params [i] = mono_metadata_parse_type_full (m, container, MONO_PARSE_PARAM, pattrs ? pattrs [i+1] : 0, ptr, &ptr);
1915                 if (!method->params [i]) {
1916                         mono_metadata_free_method_signature (method);
1917                         g_free (pattrs);
1918                         return NULL;
1919                 }
1920                 if (!is_open)
1921                         is_open = mono_class_is_open_constructed_type (method->params [i]);
1922         }
1923
1924         /* The sentinel could be missing if the caller does not pass any additional arguments */
1925         if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0)
1926                 method->sentinelpos = method->param_count;
1927
1928         method->has_type_parameters = is_open;
1929
1930         if (def && (method->call_convention == MONO_CALL_VARARG))
1931                 method->sentinelpos = method->param_count;
1932
1933         g_free (pattrs);
1934
1935         if (rptr)
1936                 *rptr = ptr;
1937         /*
1938          * Add signature to a cache and increase ref count...
1939          */
1940
1941         return method;
1942 }
1943
1944 /*
1945  * mono_metadata_parse_method_signature:
1946  * @m: metadata context
1947  * @def: the MethodDef index or 0 for Ref signatures.
1948  * @ptr: pointer to the signature metadata representation
1949  * @rptr: pointer updated to match the end of the decoded stream
1950  *
1951  * Decode a method signature stored at @ptr.
1952  * This is a Mono runtime internal function.
1953  *
1954  * LOCKING: Assumes the loader lock is held.
1955  *
1956  * Returns: a MonoMethodSignature describing the signature.
1957  */
1958 MonoMethodSignature *
1959 mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
1960 {
1961         return mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr);
1962 }
1963
1964 /*
1965  * mono_metadata_free_method_signature:
1966  * @sig: signature to destroy
1967  *
1968  * Free the memory allocated in the signature @sig.
1969  * This method needs to be robust and work also on partially-built
1970  * signatures, so it does extra checks.
1971  */
1972 void
1973 mono_metadata_free_method_signature (MonoMethodSignature *sig)
1974 {
1975         /* Everything is allocated from mempools */
1976         /*
1977         int i;
1978         if (sig->ret)
1979                 mono_metadata_free_type (sig->ret);
1980         for (i = 0; i < sig->param_count; ++i) {
1981                 if (sig->params [i])
1982                         mono_metadata_free_type (sig->params [i]);
1983         }
1984         */
1985 }
1986
1987 void
1988 mono_metadata_free_inflated_signature (MonoMethodSignature *sig)
1989 {
1990         int i;
1991
1992         /* Allocated in inflate_generic_signature () */
1993         if (sig->ret)
1994                 mono_metadata_free_type (sig->ret);
1995         for (i = 0; i < sig->param_count; ++i) {
1996                 if (sig->params [i])
1997                         mono_metadata_free_type (sig->params [i]);
1998         }
1999         g_free (sig);
2000 }
2001
2002 static gboolean
2003 inflated_method_equal (gconstpointer a, gconstpointer b)
2004 {
2005         const MonoMethodInflated *ma = a;
2006         const MonoMethodInflated *mb = b;
2007         if (ma->declaring != mb->declaring)
2008                 return FALSE;
2009         if (ma->method.method.is_mb_open != mb->method.method.is_mb_open)
2010                 return FALSE;
2011         return mono_metadata_generic_context_equal (&ma->context, &mb->context);
2012 }
2013
2014 static guint
2015 inflated_method_hash (gconstpointer a)
2016 {
2017         const MonoMethodInflated *ma = a;
2018         return (mono_metadata_generic_context_hash (&ma->context) ^ mono_aligned_addr_hash (ma->declaring)) + ma->method.method.is_mb_open;
2019 }
2020
2021 static gboolean
2022 inflated_signature_equal (gconstpointer a, gconstpointer b)
2023 {
2024         const MonoInflatedMethodSignature *sig1 = a;
2025         const MonoInflatedMethodSignature *sig2 = b;
2026
2027         /* sig->sig is assumed to be canonized */
2028         if (sig1->sig != sig2->sig)
2029                 return FALSE;
2030         /* The generic instances are canonized */
2031         return mono_metadata_generic_context_equal (&sig1->context, &sig2->context);
2032 }
2033
2034 static guint
2035 inflated_signature_hash (gconstpointer a)
2036 {
2037         const MonoInflatedMethodSignature *sig = a;
2038
2039         /* sig->sig is assumed to be canonized */
2040         return mono_metadata_generic_context_hash (&sig->context) ^ mono_aligned_addr_hash (sig->sig);
2041 }
2042
2043 /*static void
2044 dump_ginst (MonoGenericInst *ginst)
2045 {
2046         int i;
2047         char *name;
2048
2049         g_print ("Ginst: <");
2050         for (i = 0; i < ginst->type_argc; ++i) {
2051                 if (i != 0)
2052                         g_print (", ");
2053                 name = mono_type_get_name (ginst->type_argv [i]);
2054                 g_print ("%s", name);
2055                 g_free (name);
2056         }
2057         g_print (">");
2058 }*/
2059
2060 static gboolean type_in_image (MonoType *type, MonoImage *image);
2061
2062 static gboolean
2063 signature_in_image (MonoMethodSignature *sig, MonoImage *image)
2064 {
2065         gpointer iter = NULL;
2066         MonoType *p;
2067
2068         while ((p = mono_signature_get_params (sig, &iter)) != NULL)
2069                 if (type_in_image (p, image))
2070                         return TRUE;
2071
2072         return type_in_image (mono_signature_get_return_type (sig), image);
2073 }
2074
2075 static gboolean
2076 ginst_in_image (MonoGenericInst *ginst, MonoImage *image)
2077 {
2078         int i;
2079
2080         for (i = 0; i < ginst->type_argc; ++i) {
2081                 if (type_in_image (ginst->type_argv [i], image))
2082                         return TRUE;
2083         }
2084
2085         return FALSE;
2086 }
2087
2088 static gboolean
2089 gclass_in_image (MonoGenericClass *gclass, MonoImage *image)
2090 {
2091         return gclass->container_class->image == image ||
2092                 ginst_in_image (gclass->context.class_inst, image);
2093 }
2094
2095 static gboolean
2096 type_in_image (MonoType *type, MonoImage *image)
2097 {
2098 retry:
2099         switch (type->type) {
2100         case MONO_TYPE_GENERICINST:
2101                 return gclass_in_image (type->data.generic_class, image);
2102         case MONO_TYPE_PTR:
2103                 type = type->data.type;
2104                 goto retry;
2105         case MONO_TYPE_SZARRAY:
2106                 type = &type->data.klass->byval_arg;
2107                 goto retry;
2108         case MONO_TYPE_ARRAY:
2109                 type = &type->data.array->eklass->byval_arg;
2110                 goto retry;
2111         case MONO_TYPE_FNPTR:
2112                 return signature_in_image (type->data.method, image);
2113         case MONO_TYPE_VAR: {
2114                 MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
2115                 if (container) {
2116                         g_assert (!container->is_method);
2117                         /*
2118                          * FIXME: The following check is here solely
2119                          * for monodis, which uses the internal
2120                          * function
2121                          * mono_metadata_load_generic_params().  The
2122                          * caller of that function needs to fill in
2123                          * owner->klass or owner->method of the
2124                          * returned struct, but monodis doesn't do
2125                          * that.  The image unloading depends on that,
2126                          * however, so a crash results without this
2127                          * check.
2128                          */
2129                         if (!container->owner.klass)
2130                                 return FALSE;
2131                         return container->owner.klass->image == image;
2132                 } else {
2133                         return type->data.generic_param->image == image;
2134                 }
2135         }
2136         case MONO_TYPE_MVAR: {
2137                 MonoGenericContainer *container = mono_type_get_generic_param_owner (type);
2138                 if (container) {
2139                         g_assert (container->is_method);
2140                         if (!container->owner.method)
2141                                 /* RefEmit created generic param whose method is not finished */
2142                                 return FALSE;
2143                         return container->owner.method->klass->image == image;
2144                 } else {
2145                         return type->data.generic_param->image == image;
2146                 }
2147         }
2148         default:
2149                 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2150                 return image == mono_class_from_mono_type (type)->image;
2151         }
2152 }
2153
2154 typedef struct {
2155         MonoImage *image;
2156         GSList *list;
2157 } CleanForImageUserData;
2158
2159 static gboolean
2160 steal_gclass_in_image (gpointer key, gpointer value, gpointer data)
2161 {
2162         MonoGenericClass *gclass = key;
2163         CleanForImageUserData *user_data = data;
2164
2165         if (!gclass_in_image (gclass, user_data->image))
2166                 return FALSE;
2167
2168         user_data->list = g_slist_prepend (user_data->list, gclass);
2169         return TRUE;
2170 }
2171
2172 static gboolean
2173 steal_ginst_in_image (gpointer key, gpointer value, gpointer data)
2174 {
2175         MonoGenericInst *ginst = key;
2176         CleanForImageUserData *user_data = data;
2177
2178         if (!ginst_in_image (ginst, user_data->image))
2179                 return FALSE;
2180
2181         user_data->list = g_slist_prepend (user_data->list, ginst);
2182         return TRUE;
2183 }
2184
2185 static gboolean
2186 inflated_method_in_image (gpointer key, gpointer value, gpointer data)
2187 {
2188         MonoImage *image = data;
2189         MonoMethodInflated *method = key;
2190
2191         // FIXME:
2192         // https://bugzilla.novell.com/show_bug.cgi?id=458168
2193         return method->declaring->klass->image == image ||
2194                 (method->context.class_inst && ginst_in_image (method->context.class_inst, image)) ||
2195                 (method->context.method_inst && ginst_in_image (method->context.method_inst, image)) || (((MonoMethod*)method)->signature && signature_in_image (mono_method_signature ((MonoMethod*)method), image));
2196 }
2197
2198 static gboolean
2199 inflated_signature_in_image (gpointer key, gpointer value, gpointer data)
2200 {
2201         MonoImage *image = data;
2202         MonoInflatedMethodSignature *sig = key;
2203
2204         return signature_in_image (sig->sig, image) ||
2205                 (sig->context.class_inst && ginst_in_image (sig->context.class_inst, image)) ||
2206                 (sig->context.method_inst && ginst_in_image (sig->context.method_inst, image));
2207 }       
2208
2209 void
2210 mono_metadata_clean_for_image (MonoImage *image)
2211 {
2212         CleanForImageUserData ginst_data, gclass_data;
2213         GSList *l;
2214
2215         /* The data structures could reference each other so we delete them in two phases */
2216         ginst_data.image = gclass_data.image = image;
2217         ginst_data.list = gclass_data.list = NULL;
2218
2219         mono_loader_lock ();    
2220         /* Collect the items to delete and remove them from the hash table */
2221         g_hash_table_foreach_steal (generic_inst_cache, steal_ginst_in_image, &ginst_data);
2222         g_hash_table_foreach_steal (generic_class_cache, steal_gclass_in_image, &gclass_data);
2223         if (generic_method_cache)
2224                 g_hash_table_foreach_remove (generic_method_cache, inflated_method_in_image, image);
2225         if (generic_signature_cache)
2226                 g_hash_table_foreach_remove (generic_signature_cache, inflated_signature_in_image, image);
2227         /* Delete the removed items */
2228         for (l = ginst_data.list; l; l = l->next)
2229                 free_generic_inst (l->data);
2230         for (l = gclass_data.list; l; l = l->next)
2231                 free_generic_class (l->data);
2232         g_slist_free (ginst_data.list);
2233         g_slist_free (gclass_data.list);
2234         mono_class_unregister_image_generic_subclasses (image);
2235         mono_loader_unlock ();
2236 }
2237
2238 static void
2239 free_inflated_method (MonoMethodInflated *imethod)
2240 {
2241         int i;
2242         MonoMethod *method = (MonoMethod*)imethod;
2243
2244         mono_marshal_free_inflated_wrappers (method);
2245
2246         if (method->signature)
2247                 mono_metadata_free_inflated_signature (method->signature);
2248
2249         if (!((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))) {
2250                 MonoMethodNormal* mn = (MonoMethodNormal*) method;
2251                 MonoMethodHeader *header = mn->header;
2252
2253                 if (header) {
2254                         /* Allocated in inflate_generic_header () */
2255                         for (i = 0; i < header->num_locals; ++i)
2256                                 mono_metadata_free_type (header->locals [i]);
2257                         g_free (header->clauses);
2258                         g_free (header);
2259                 }
2260         }
2261
2262         g_free (method);
2263 }
2264
2265 static void
2266 free_generic_inst (MonoGenericInst *ginst)
2267 {
2268         int i;
2269
2270         for (i = 0; i < ginst->type_argc; ++i)
2271                 mono_metadata_free_type (ginst->type_argv [i]);
2272         g_free (ginst);
2273 }
2274
2275
2276 static void
2277 free_generic_class (MonoGenericClass *gclass)
2278 {
2279         int i;
2280
2281         /* FIXME: The dynamic case */
2282         if (gclass->cached_class && !gclass->cached_class->image->dynamic && !mono_generic_class_is_generic_type_definition (gclass)) {
2283                 MonoClass *class = gclass->cached_class;
2284
2285                 /* Allocated in mono_class_init () */
2286                 g_free (class->methods);
2287                 if (class->ext)
2288                         g_free (class->ext->properties);
2289                 /* Allocated in mono_generic_class_get_class () */
2290                 g_free (class->interfaces);
2291                 g_free (class);
2292         } else if (gclass->is_dynamic) {
2293                 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *)gclass;
2294
2295                 for (i = 0; i < dgclass->count_fields; ++i) {
2296                         MonoClassField *field = dgclass->fields + i;
2297                         mono_metadata_free_type (field->type);
2298                         g_free ((char*)field->name);
2299                 }
2300                 for (i = 0; i < dgclass->count_properties; ++i) {
2301                         MonoProperty *property = dgclass->properties + i;
2302                         g_free ((char*)property->name);
2303                 }
2304                 for (i = 0; i < dgclass->count_events; ++i) {
2305                         MonoEvent *event = dgclass->events + i;
2306                         g_free ((char*)event->name);
2307                 }
2308                 
2309                 g_free (dgclass->methods);
2310                 g_free (dgclass->ctors);
2311                 g_free (dgclass->fields);
2312                 g_free (dgclass->properties);
2313                 g_free (dgclass->events);
2314                 g_free (dgclass->field_objects);
2315                 g_free (dgclass->field_generic_types);
2316                 if (!mono_generic_class_is_generic_type_definition (gclass))
2317                         g_free (gclass->cached_class);
2318         }
2319         g_free (gclass);
2320 }
2321
2322 static void
2323 free_inflated_signature (MonoInflatedMethodSignature *sig)
2324 {
2325         mono_metadata_free_inflated_signature (sig->sig);
2326         g_free (sig);
2327 }
2328
2329 /*
2330  * LOCKING: assumes the loader lock is held.
2331  */
2332 MonoMethodInflated*
2333 mono_method_inflated_lookup (MonoMethodInflated* method, gboolean cache)
2334 {
2335         if (cache) {
2336                 if (!generic_method_cache)
2337                         generic_method_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method);
2338                 g_hash_table_insert (generic_method_cache, method, method);
2339                 return method;
2340         } else {
2341                 if (generic_method_cache)
2342                         return g_hash_table_lookup (generic_method_cache, method);
2343                 return NULL;
2344         }
2345 }
2346
2347 /*
2348  * mono_metadata_get_inflated_signature:
2349  *
2350  *   Given an inflated signature and a generic context, return a canonical copy of the 
2351  * signature. The returned signature might be equal to SIG or it might be a cached copy.
2352  */
2353 MonoMethodSignature *
2354 mono_metadata_get_inflated_signature (MonoMethodSignature *sig, MonoGenericContext *context)
2355 {
2356         MonoInflatedMethodSignature helper;
2357         MonoInflatedMethodSignature *res;
2358
2359         mono_loader_lock ();
2360         if (!generic_signature_cache)
2361                 generic_signature_cache = g_hash_table_new_full (inflated_signature_hash, inflated_signature_equal, NULL, (GDestroyNotify)free_inflated_signature);
2362
2363         helper.sig = sig;
2364         helper.context.class_inst = context->class_inst;
2365         helper.context.method_inst = context->method_inst;
2366         res = g_hash_table_lookup (generic_signature_cache, &helper);
2367         if (!res) {
2368                 res = g_new0 (MonoInflatedMethodSignature, 1);
2369                 res->sig = sig;
2370                 res->context.class_inst = context->class_inst;
2371                 res->context.method_inst = context->method_inst;
2372                 g_hash_table_insert (generic_signature_cache, res, res);
2373         }
2374
2375         mono_loader_unlock ();
2376         return res->sig;
2377 }
2378
2379 /*
2380  * mono_metadata_get_generic_inst:
2381  *
2382  * Given a list of types, return a MonoGenericInst that represents that list.
2383  * The returned MonoGenericInst has its own copy of the list of types.  The list
2384  * passed in the argument can be freed, modified or disposed of.
2385  *
2386  */
2387 MonoGenericInst *
2388 mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
2389 {
2390         MonoGenericInst *ginst;
2391         gboolean is_open;
2392         int i;
2393         int size = sizeof (MonoGenericInst) + (type_argc - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *);
2394
2395         for (i = 0; i < type_argc; ++i)
2396                 if (mono_class_is_open_constructed_type (type_argv [i]))
2397                         break;
2398         is_open = (i < type_argc);
2399
2400         ginst = alloca (size);
2401         ginst->id = 0;
2402         ginst->is_open = is_open;
2403         ginst->type_argc = type_argc;
2404         memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
2405
2406         mono_loader_lock ();
2407
2408         ginst = g_hash_table_lookup (generic_inst_cache, ginst);
2409         if (!ginst) {
2410                 ginst = g_malloc (size);
2411                 ginst->id = ++next_generic_inst_id;
2412                 ginst->is_open = is_open;
2413                 ginst->type_argc = type_argc;
2414
2415                 for (i = 0; i < type_argc; ++i)
2416                         ginst->type_argv [i] = mono_metadata_type_dup (NULL, type_argv [i]);
2417
2418                 g_hash_table_insert (generic_inst_cache, ginst, ginst);
2419         }
2420
2421         mono_loader_unlock ();
2422         return ginst;
2423 }
2424
2425 static gboolean
2426 mono_metadata_is_type_builder_generic_type_definition (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
2427 {
2428         MonoGenericContainer *container = container_class->generic_container; 
2429
2430         if (!is_dynamic || container_class->wastypebuilder || container->type_argc != inst->type_argc)
2431                 return FALSE;
2432         return inst == container->context.class_inst;
2433 }
2434
2435 /*
2436  * mono_metadata_lookup_generic_class:
2437  *
2438  * Returns a MonoGenericClass with the given properties.
2439  *
2440  */
2441 MonoGenericClass *
2442 mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
2443 {
2444         MonoGenericClass *gclass;
2445         MonoGenericClass helper;
2446         gboolean is_tb_open = mono_metadata_is_type_builder_generic_type_definition (container_class, inst, is_dynamic);
2447
2448         helper.container_class = container_class;
2449         helper.context.class_inst = inst;
2450         helper.context.method_inst = NULL;
2451         helper.is_dynamic = is_dynamic; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
2452         helper.is_tb_open = is_tb_open;
2453         helper.cached_class = NULL;
2454
2455         mono_loader_lock ();
2456
2457         gclass = g_hash_table_lookup (generic_class_cache, &helper);
2458
2459         /* A tripwire just to keep us honest */
2460         g_assert (!helper.cached_class);
2461
2462         if (gclass) {
2463                 mono_loader_unlock ();
2464                 return gclass;
2465         }
2466
2467         if (is_dynamic) {
2468                 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
2469                 gclass = &dgclass->generic_class;
2470                 gclass->is_dynamic = 1;
2471         } else {
2472                 gclass = g_new0 (MonoGenericClass, 1);
2473         }
2474
2475         gclass->is_tb_open = is_tb_open;
2476         gclass->container_class = container_class;
2477         gclass->context.class_inst = inst;
2478         gclass->context.method_inst = NULL;
2479         if (inst == container_class->generic_container->context.class_inst && !is_tb_open)
2480                 gclass->cached_class = container_class;
2481
2482         g_hash_table_insert (generic_class_cache, gclass, gclass);
2483
2484         mono_loader_unlock ();
2485
2486         return gclass;
2487 }
2488
2489 /*
2490  * mono_metadata_inflate_generic_inst:
2491  *
2492  * Instantiate the generic instance @ginst with the context @context.
2493  *
2494  */
2495 MonoGenericInst *
2496 mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context)
2497 {
2498         MonoType **type_argv;
2499         MonoGenericInst *nginst;
2500         int i;
2501
2502         if (!ginst->is_open)
2503                 return ginst;
2504
2505         type_argv = g_new0 (MonoType*, ginst->type_argc);
2506
2507         for (i = 0; i < ginst->type_argc; i++)
2508                 type_argv [i] = mono_class_inflate_generic_type (ginst->type_argv [i], context);
2509
2510         nginst = mono_metadata_get_generic_inst (ginst->type_argc, type_argv);
2511
2512         for (i = 0; i < ginst->type_argc; i++)
2513                 mono_metadata_free_type (type_argv [i]);
2514         g_free (type_argv);
2515
2516         return nginst;
2517 }
2518
2519 MonoGenericInst *
2520 mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container,
2521                                   int count, const char *ptr, const char **rptr)
2522 {
2523         MonoType **type_argv;
2524         MonoGenericInst *ginst;
2525         int i;
2526
2527         type_argv = g_new0 (MonoType*, count);
2528
2529         for (i = 0; i < count; i++) {
2530                 MonoType *t = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
2531                 if (!t) {
2532                         g_free (type_argv);
2533                         return NULL;
2534                 }
2535                 type_argv [i] = t;
2536         }
2537
2538         if (rptr)
2539                 *rptr = ptr;
2540
2541         ginst = mono_metadata_get_generic_inst (count, type_argv);
2542
2543         g_free (type_argv);
2544
2545         return ginst;
2546 }
2547
2548 static gboolean
2549 do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
2550                                       const char *ptr, const char **rptr)
2551 {
2552         MonoGenericInst *inst;
2553         MonoClass *gklass;
2554         MonoType *gtype;
2555         int count;
2556
2557         gtype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
2558         if (gtype == NULL)
2559                 return FALSE;
2560
2561         gklass = mono_class_from_mono_type (gtype);
2562         if (!gklass->generic_container)
2563                 return FALSE;
2564
2565         count = mono_metadata_decode_value (ptr, &ptr);
2566         inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr);
2567         if (inst == NULL)
2568                 return FALSE;
2569
2570         if (rptr)
2571                 *rptr = ptr;
2572
2573         type->data.generic_class = mono_metadata_lookup_generic_class (gklass, inst, FALSE);
2574         return TRUE;
2575 }
2576
2577 /*
2578  * select_container:
2579  * @gc: The generic container to normalize
2580  * @type: The kind of generic parameters the resulting generic-container should contain
2581  */
2582
2583 static MonoGenericContainer *
2584 select_container (MonoGenericContainer *gc, MonoTypeEnum type)
2585 {
2586         gboolean is_var = (type == MONO_TYPE_VAR);
2587         if (!gc)
2588                 return NULL;
2589
2590         g_assert (is_var || type == MONO_TYPE_MVAR);
2591
2592         if (is_var) {
2593                 if (gc->is_method || gc->parent)
2594                         /*
2595                          * The current MonoGenericContainer is a generic method -> its `parent'
2596                          * points to the containing class'es container.
2597                          */
2598                         return gc->parent;
2599         }
2600
2601         return gc;
2602 }
2603
2604 /* 
2605  * mono_metadata_parse_generic_param:
2606  * @generic_container: Our MonoClass's or MonoMethodNormal's MonoGenericContainer;
2607  *                     see mono_metadata_parse_type_full() for details.
2608  * Internal routine to parse a generic type parameter.
2609  * LOCKING: Acquires the loader lock
2610  */
2611 static MonoGenericParam *
2612 mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
2613                                    MonoTypeEnum type, const char *ptr, const char **rptr)
2614 {
2615         int index = mono_metadata_decode_value (ptr, &ptr);
2616         if (rptr)
2617                 *rptr = ptr;
2618
2619         generic_container = select_container (generic_container, type);
2620         if (!generic_container) {
2621                 /* Create dummy MonoGenericParam */
2622                 MonoGenericParam *param;
2623
2624                 param = mono_image_alloc0 (m, sizeof (MonoGenericParam));
2625                 param->num = index;
2626                 param->image = m;
2627
2628                 return param;
2629         }
2630
2631         g_assert (index < generic_container->type_argc);
2632         return mono_generic_container_get_param (generic_container, index);
2633 }
2634
2635 /*
2636  * mono_metadata_get_shared_type:
2637  *
2638  *   Return a shared instance of TYPE, if available, NULL otherwise.
2639  * Shared MonoType instances help save memory. Their contents should not be modified
2640  * by the caller. They do not need to be freed as their lifetime is bound by either
2641  * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
2642  * instance they are embedded in. If they are freed, they should be freed using
2643  * mono_metadata_free_type () instead of g_free ().
2644  */
2645 MonoType*
2646 mono_metadata_get_shared_type (MonoType *type)
2647 {
2648         MonoType *cached;
2649
2650         /* No need to use locking since nobody is modifying the hash table */
2651         if ((cached = g_hash_table_lookup (type_cache, type)))
2652                 return cached;
2653
2654         switch (type->type){
2655         case MONO_TYPE_CLASS:
2656         case MONO_TYPE_VALUETYPE:
2657                 if (type == &type->data.klass->byval_arg)
2658                         return type;
2659                 if (type == &type->data.klass->this_arg)
2660                         return type;
2661                 break;
2662         }
2663
2664         return NULL;
2665 }
2666
2667 /* 
2668  * do_mono_metadata_parse_type:
2669  * @type: MonoType to be filled in with the return value
2670  * @m: image context
2671  * @generic_context: generics_context
2672  * @ptr: pointer to the encoded type
2673  * @rptr: pointer where the end of the encoded type is saved
2674  * 
2675  * Internal routine used to "fill" the contents of @type from an 
2676  * allocated pointer.  This is done this way to avoid doing too
2677  * many mini-allocations (particularly for the MonoFieldType which
2678  * most of the time is just a MonoType, but sometimes might be augmented).
2679  *
2680  * This routine is used by mono_metadata_parse_type and
2681  * mono_metadata_parse_field_type
2682  *
2683  * This extracts a Type as specified in Partition II (22.2.12) 
2684  *
2685  * Returns: FALSE if the type could not be loaded
2686  */
2687 static gboolean
2688 do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
2689                              const char *ptr, const char **rptr)
2690 {
2691         gboolean ok = TRUE;
2692         type->type = mono_metadata_decode_value (ptr, &ptr);
2693         
2694         switch (type->type){
2695         case MONO_TYPE_VOID:
2696         case MONO_TYPE_BOOLEAN:
2697         case MONO_TYPE_CHAR:
2698         case MONO_TYPE_I1:
2699         case MONO_TYPE_U1:
2700         case MONO_TYPE_I2:
2701         case MONO_TYPE_U2:
2702         case MONO_TYPE_I4:
2703         case MONO_TYPE_U4:
2704         case MONO_TYPE_I8:
2705         case MONO_TYPE_U8:
2706         case MONO_TYPE_R4:
2707         case MONO_TYPE_R8:
2708         case MONO_TYPE_I:
2709         case MONO_TYPE_U:
2710         case MONO_TYPE_STRING:
2711         case MONO_TYPE_OBJECT:
2712         case MONO_TYPE_TYPEDBYREF:
2713                 break;
2714         case MONO_TYPE_VALUETYPE:
2715         case MONO_TYPE_CLASS: {
2716                 guint32 token;
2717                 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
2718                 type->data.klass = mono_class_get (m, token);
2719                 if (!type->data.klass)
2720                         return FALSE;
2721                 break;
2722         }
2723         case MONO_TYPE_SZARRAY: {
2724                 MonoType *etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
2725                 if (!etype)
2726                         return FALSE;
2727                 type->data.klass = mono_class_from_mono_type (etype);
2728                 break;
2729         }
2730         case MONO_TYPE_PTR:
2731                 type->data.type = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
2732                 if (!type->data.type)
2733                         return FALSE;
2734                 break;
2735         case MONO_TYPE_FNPTR:
2736                 type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr);
2737                 break;
2738         case MONO_TYPE_ARRAY:
2739                 type->data.array = mono_metadata_parse_array_full (m, container, ptr, &ptr);
2740                 break;
2741         case MONO_TYPE_MVAR:
2742                 if (container && !container->is_method)
2743                         return FALSE;
2744         case MONO_TYPE_VAR:
2745                 type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr);
2746                 break;
2747         case MONO_TYPE_GENERICINST:
2748                 ok = do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr);
2749                 break;
2750         default:
2751                 g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type->type);
2752         }
2753         
2754         if (rptr)
2755                 *rptr = ptr;
2756         return ok;
2757 }
2758
2759 /*
2760  * mono_metadata_free_type:
2761  * @type: type to free
2762  *
2763  * Free the memory allocated for type @type which is allocated on the heap.
2764  */
2765 void
2766 mono_metadata_free_type (MonoType *type)
2767 {
2768         if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
2769                 return;
2770         
2771         switch (type->type){
2772         case MONO_TYPE_OBJECT:
2773         case MONO_TYPE_STRING:
2774                 if (!type->data.klass)
2775                         break;
2776                 /* fall through */
2777         case MONO_TYPE_CLASS:
2778         case MONO_TYPE_VALUETYPE:
2779                 if (type == &type->data.klass->byval_arg || type == &type->data.klass->this_arg)
2780                         return;
2781                 break;
2782         case MONO_TYPE_PTR:
2783                 mono_metadata_free_type (type->data.type);
2784                 break;
2785         case MONO_TYPE_FNPTR:
2786                 mono_metadata_free_method_signature (type->data.method);
2787                 break;
2788         case MONO_TYPE_ARRAY:
2789                 mono_metadata_free_array (type->data.array);
2790                 break;
2791         }
2792
2793         g_free (type);
2794 }
2795
2796 #if 0
2797 static void
2798 hex_dump (const char *buffer, int base, int count)
2799 {
2800         int show_header = 1;
2801         int i;
2802
2803         if (count < 0){
2804                 count = -count;
2805                 show_header = 0;
2806         }
2807         
2808         for (i = 0; i < count; i++){
2809                 if (show_header)
2810                         if ((i % 16) == 0)
2811                                 printf ("\n0x%08x: ", (unsigned char) base + i);
2812
2813                 printf ("%02x ", (unsigned char) (buffer [i]));
2814         }
2815         fflush (stdout);
2816 }
2817 #endif
2818
2819 /** 
2820  * @mh: The Method header
2821  * @ptr: Points to the beginning of the Section Data (25.3)
2822  */
2823 static void
2824 parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr)
2825 {
2826         unsigned char sect_data_flags;
2827         const unsigned char *sptr;
2828         int is_fat;
2829         guint32 sect_data_len;
2830         
2831         while (1) {
2832                 /* align on 32-bit boundary */
2833                 sptr = ptr = dword_align (ptr); 
2834                 sect_data_flags = *ptr;
2835                 ptr++;
2836                 
2837                 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
2838                 if (is_fat) {
2839                         sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
2840                         ptr += 3;
2841                 } else {
2842                         sect_data_len = ptr [0];
2843                         ++ptr;
2844                 }
2845                 /*
2846                 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
2847                 hex_dump (sptr, 0, sect_data_len+8);
2848                 g_print ("\nheader: ");
2849                 hex_dump (sptr-4, 0, 4);
2850                 g_print ("\n");
2851                 */
2852                 
2853                 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
2854                         const unsigned char *p = dword_align (ptr);
2855                         int i;
2856                         mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
2857                         /* we could just store a pointer if we don't need to byteswap */
2858                         mh->clauses = mono_image_alloc0 (m, sizeof (MonoExceptionClause) * mh->num_clauses);
2859                         for (i = 0; i < mh->num_clauses; ++i) {
2860                                 MonoExceptionClause *ec = &mh->clauses [i];
2861                                 guint32 tof_value;
2862                                 if (is_fat) {
2863                                         ec->flags = read32 (p);
2864                                         ec->try_offset = read32 (p + 4);
2865                                         ec->try_len = read32 (p + 8);
2866                                         ec->handler_offset = read32 (p + 12);
2867                                         ec->handler_len = read32 (p + 16);
2868                                         tof_value = read32 (p + 20);
2869                                         p += 24;
2870                                 } else {
2871                                         ec->flags = read16 (p);
2872                                         ec->try_offset = read16 (p + 2);
2873                                         ec->try_len = *(p + 4);
2874                                         ec->handler_offset = read16 (p + 5);
2875                                         ec->handler_len = *(p + 7);
2876                                         tof_value = read32 (p + 8);
2877                                         p += 12;
2878                                 }
2879                                 if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
2880                                         ec->data.filter_offset = tof_value;
2881                                 } else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) {
2882                                         ec->data.catch_class = tof_value? mono_class_get (m, tof_value): 0;
2883                                 } else {
2884                                         ec->data.catch_class = NULL;
2885                                 }
2886                                 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
2887                         }
2888
2889                 }
2890                 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
2891                         ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
2892                 else
2893                         return;
2894         }
2895 }
2896
2897 /*
2898  * mono_metadata_parse_mh_full:
2899  * @m: metadata context
2900  * @generic_context: generics context
2901  * @ptr: pointer to the method header.
2902  *
2903  * Decode the method header at @ptr, including pointer to the IL code,
2904  * info about local variables and optional exception tables.
2905  * This is a Mono runtime internal function.
2906  *
2907  * LOCKING: Acquires the loader lock.
2908  *
2909  * Returns: a MonoMethodHeader allocated from the image mempool.
2910  */
2911 MonoMethodHeader *
2912 mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr)
2913 {
2914         MonoMethodHeader *mh;
2915         unsigned char flags = *(const unsigned char *) ptr;
2916         unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
2917         guint16 fat_flags;
2918         guint32 local_var_sig_tok, max_stack, code_size, init_locals;
2919         const unsigned char *code;
2920         int hsize;
2921         
2922         g_return_val_if_fail (ptr != NULL, NULL);
2923
2924         switch (format) {
2925         case METHOD_HEADER_TINY_FORMAT:
2926                 mh = mono_image_alloc0 (m, sizeof (MonoMethodHeader));
2927                 ptr++;
2928                 mh->max_stack = 8;
2929                 local_var_sig_tok = 0;
2930                 mh->code_size = flags >> 2;
2931                 mh->code = (unsigned char*)ptr;
2932                 return mh;
2933         case METHOD_HEADER_TINY_FORMAT1:
2934                 mh = mono_image_alloc0 (m, sizeof (MonoMethodHeader));
2935                 ptr++;
2936                 mh->max_stack = 8;
2937                 local_var_sig_tok = 0;
2938
2939                 /*
2940                  * The spec claims 3 bits, but the Beta2 is
2941                  * incorrect
2942                  */
2943                 mh->code_size = flags >> 2;
2944                 mh->code = (unsigned char*)ptr;
2945                 return mh;
2946         case METHOD_HEADER_FAT_FORMAT:
2947                 fat_flags = read16 (ptr);
2948                 ptr += 2;
2949                 hsize = (fat_flags >> 12) & 0xf;
2950                 max_stack = read16 (ptr);
2951                 ptr += 2;
2952                 code_size = read32 (ptr);
2953                 ptr += 4;
2954                 local_var_sig_tok = read32 (ptr);
2955                 ptr += 4;
2956
2957                 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
2958                         init_locals = 1;
2959                 else
2960                         init_locals = 0;
2961
2962                 code = (unsigned char*)ptr;
2963
2964                 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
2965                         break;
2966
2967                 /*
2968                  * There are more sections
2969                  */
2970                 ptr = (char*)code + code_size;
2971                 break;
2972         default:
2973                 return NULL;
2974         }
2975                        
2976         if (local_var_sig_tok) {
2977                 MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
2978                 const char *locals_ptr;
2979                 guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
2980                 int len=0, i, bsize;
2981
2982                 mono_metadata_decode_row (t, (local_var_sig_tok & 0xffffff)-1, cols, 1);
2983                 locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
2984                 bsize = mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
2985                 if (*locals_ptr != 0x07)
2986                         g_warning ("wrong signature for locals blob");
2987                 locals_ptr++;
2988                 len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
2989                 mh = mono_image_alloc0 (m, sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
2990                 mh->num_locals = len;
2991                 for (i = 0; i < len; ++i) {
2992                         mh->locals [i] = mono_metadata_parse_type_full (
2993                                 m, container, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
2994                         if (!mh->locals [i]) {
2995                                 return NULL;
2996                         }
2997                 }
2998         } else {
2999                 mh = mono_image_alloc0 (m, sizeof (MonoMethodHeader));
3000         }
3001         mh->code = code;
3002         mh->code_size = code_size;
3003         mh->max_stack = max_stack;
3004         mh->init_locals = init_locals;
3005         if (fat_flags & METHOD_HEADER_MORE_SECTS)
3006                 parse_section_data (m, mh, (const unsigned char*)ptr);
3007         return mh;
3008 }
3009
3010 /*
3011  * mono_metadata_parse_mh:
3012  * @generic_context: generics context
3013  * @ptr: pointer to the method header.
3014  *
3015  * Decode the method header at @ptr, including pointer to the IL code,
3016  * info about local variables and optional exception tables.
3017  * This is a Mono runtime internal function.
3018  *
3019  * Returns: a MonoMethodHeader.
3020  */
3021 MonoMethodHeader *
3022 mono_metadata_parse_mh (MonoImage *m, const char *ptr)
3023 {
3024         MonoMethodHeader *res;
3025
3026         mono_loader_lock ();
3027
3028         res = mono_metadata_parse_mh_full (m, NULL, ptr);
3029
3030         mono_loader_unlock ();
3031
3032         return res;
3033 }
3034
3035 /*
3036  * mono_metadata_free_mh:
3037  * @mh: a method header
3038  *
3039  * Free the memory allocated for the method header.
3040  * This is a Mono runtime internal function.
3041  */
3042 void
3043 mono_metadata_free_mh (MonoMethodHeader *mh)
3044 {
3045         /* Allocated from the mempool */
3046 }
3047
3048 /*
3049  * mono_method_header_get_code:
3050  * @header: a MonoMethodHeader pointer
3051  * @code_size: memory location for returning the code size
3052  * @max_stack: memory location for returning the max stack
3053  *
3054  * Method header accessor to retreive info about the IL code properties:
3055  * a pointer to the IL code itself, the size of the code and the max number
3056  * of stack slots used by the code.
3057  *
3058  * Returns: pointer to the IL code represented by the method header.
3059  */
3060 const unsigned char*
3061 mono_method_header_get_code (MonoMethodHeader *header, guint32* code_size, guint32* max_stack)
3062 {
3063         if (code_size)
3064                 *code_size = header->code_size;
3065         if (max_stack)
3066                 *max_stack = header->max_stack;
3067         return header->code;
3068 }
3069
3070 /*
3071  * mono_method_header_get_locals:
3072  * @header: a MonoMethodHeader pointer
3073  * @num_locals: memory location for returning the number of local variables
3074  * @init_locals: memory location for returning the init_locals flag
3075  *
3076  * Method header accessor to retreive info about the local variables:
3077  * an array of local types, the number of locals and whether the locals
3078  * are supposed to be initialized to 0 on method entry
3079  *
3080  * Returns: pointer to an array of types of the local variables
3081  */
3082 MonoType**
3083 mono_method_header_get_locals (MonoMethodHeader *header, guint32* num_locals, gboolean *init_locals)
3084 {
3085         if (num_locals)
3086                 *num_locals = header->num_locals;
3087         if (init_locals)
3088                 *init_locals = header->init_locals;
3089         return header->locals;
3090 }
3091
3092 /*
3093  * mono_method_header_get_num_clauses:
3094  * @header: a MonoMethodHeader pointer
3095  *
3096  * Method header accessor to retreive the number of exception clauses.
3097  *
3098  * Returns: the number of exception clauses present
3099  */
3100 int
3101 mono_method_header_get_num_clauses (MonoMethodHeader *header)
3102 {
3103         return header->num_clauses;
3104 }
3105
3106 /*
3107  * mono_method_header_get_clauses:
3108  * @header: a MonoMethodHeader pointer
3109  * @method: MonoMethod the header belongs to
3110  * @iter: pointer to a iterator
3111  * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
3112  *
3113  * Get the info about the exception clauses in the method. Set *iter to NULL to
3114  * initiate the iteration, then call the method repeatedly until it returns FALSE.
3115  * At each iteration, the structure pointed to by clause if filled with the
3116  * exception clause information.
3117  *
3118  * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
3119  * clauses.
3120  */
3121 int
3122 mono_method_header_get_clauses (MonoMethodHeader *header, MonoMethod *method, gpointer *iter, MonoExceptionClause *clause)
3123 {
3124         MonoExceptionClause *sc;
3125         /* later we'll be able to use this interface to parse the clause info on demand,
3126          * without allocating anything.
3127          */
3128         if (!iter || !header->num_clauses)
3129                 return FALSE;
3130         if (!*iter) {
3131                 *iter = sc = header->clauses;
3132                 *clause = *sc;
3133                 return TRUE;
3134         }
3135         sc = *iter;
3136         sc++;
3137         if (sc < header->clauses + header->num_clauses) {
3138                 *iter = sc;
3139                 *clause = *sc;
3140                 return TRUE;
3141         }
3142         return FALSE;
3143 }
3144
3145 /**
3146  * mono_metadata_parse_field_type:
3147  * @m: metadata context to extract information from
3148  * @ptr: pointer to the field signature
3149  * @rptr: pointer updated to match the end of the decoded stream
3150  *
3151  * Parses the field signature, and returns the type information for it. 
3152  *
3153  * Returns: The MonoType that was extracted from @ptr.
3154  */
3155 MonoType *
3156 mono_metadata_parse_field_type (MonoImage *m, short field_flags, const char *ptr, const char **rptr)
3157 {
3158         return mono_metadata_parse_type (m, MONO_PARSE_FIELD, field_flags, ptr, rptr);
3159 }
3160
3161 /**
3162  * mono_metadata_parse_param:
3163  * @m: metadata context to extract information from
3164  * @ptr: pointer to the param signature
3165  * @rptr: pointer updated to match the end of the decoded stream
3166  *
3167  * Parses the param signature, and returns the type information for it. 
3168  *
3169  * Returns: The MonoType that was extracted from @ptr.
3170  */
3171 MonoType *
3172 mono_metadata_parse_param (MonoImage *m, const char *ptr, const char **rptr)
3173 {
3174         return mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, rptr);
3175 }
3176
3177 /*
3178  * mono_metadata_token_from_dor:
3179  * @dor_token: A TypeDefOrRef coded index
3180  *
3181  * dor_token is a TypeDefOrRef coded index: it contains either
3182  * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
3183  * bits contain an index into the table.
3184  *
3185  * Returns: an expanded token
3186  */
3187 guint32
3188 mono_metadata_token_from_dor (guint32 dor_index)
3189 {
3190         guint32 table, idx;
3191
3192         table = dor_index & 0x03;
3193         idx = dor_index >> 2;
3194
3195         switch (table){
3196         case 0: /* TypeDef */
3197                 return MONO_TOKEN_TYPE_DEF | idx;
3198         case 1: /* TypeRef */
3199                 return MONO_TOKEN_TYPE_REF | idx;
3200         case 2: /* TypeSpec */
3201                 return MONO_TOKEN_TYPE_SPEC | idx;
3202         default:
3203                 g_assert_not_reached ();
3204         }
3205
3206         return 0;
3207 }
3208
3209 /*
3210  * We use this to pass context information to the row locator
3211  */
3212 typedef struct {
3213         int idx;                        /* The index that we are trying to locate */
3214         int col_idx;            /* The index in the row where idx may be stored */
3215         MonoTableInfo *t;       /* pointer to the table */
3216         guint32 result;
3217 } locator_t;
3218
3219 /*
3220  * How the row locator works.
3221  *
3222  *   Table A
3223  *   ___|___
3224  *   ___|___         Table B
3225  *   ___|___------>  _______
3226  *   ___|___         _______
3227  *   
3228  * A column in the rows of table A references an index in table B.
3229  * For example A may be the TYPEDEF table and B the METHODDEF table.
3230  * 
3231  * Given an index in table B we want to get the row in table A
3232  * where the column n references our index in B.
3233  *
3234  * In the locator_t structure:
3235  *      t is table A
3236  *      col_idx is the column number
3237  *      index is the index in table B
3238  *      result will be the index in table A
3239  *
3240  * Examples:
3241  * Table A              Table B         column (in table A)
3242  * TYPEDEF              METHODDEF   MONO_TYPEDEF_METHOD_LIST
3243  * TYPEDEF              FIELD           MONO_TYPEDEF_FIELD_LIST
3244  * PROPERTYMAP  PROPERTY        MONO_PROPERTY_MAP_PROPERTY_LIST
3245  * INTERFIMPL   TYPEDEF         MONO_INTERFACEIMPL_CLASS
3246  * METHODSEM    PROPERTY        ASSOCIATION (encoded index)
3247  *
3248  * Note that we still don't support encoded indexes.
3249  *
3250  */
3251 static int
3252 typedef_locator (const void *a, const void *b)
3253 {
3254         locator_t *loc = (locator_t *) a;
3255         const char *bb = (const char *) b;
3256         int typedef_index = (bb - loc->t->base) / loc->t->row_size;
3257         guint32 col, col_next;
3258
3259         col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx);
3260
3261         if (loc->idx < col)
3262                 return -1;
3263
3264         /*
3265          * Need to check that the next row is valid.
3266          */
3267         if (typedef_index + 1 < loc->t->rows) {
3268                 col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx);
3269                 if (loc->idx >= col_next)
3270                         return 1;
3271
3272                 if (col == col_next)
3273                         return 1; 
3274         }
3275
3276         loc->result = typedef_index;
3277         
3278         return 0;
3279 }
3280
3281 static int
3282 table_locator (const void *a, const void *b)
3283 {
3284         locator_t *loc = (locator_t *) a;
3285         const char *bb = (const char *) b;
3286         guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
3287         guint32 col;
3288         
3289         col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
3290
3291         if (loc->idx == col) {
3292                 loc->result = table_index;
3293                 return 0;
3294         }
3295         if (loc->idx < col)
3296                 return -1;
3297         else 
3298                 return 1;
3299 }
3300
3301 static int
3302 declsec_locator (const void *a, const void *b)
3303 {
3304         locator_t *loc = (locator_t *) a;
3305         const char *bb = (const char *) b;
3306         guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
3307         guint32 col;
3308
3309         col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
3310
3311         if (loc->idx == col) {
3312                 loc->result = table_index;
3313                 return 0;
3314         }
3315         if (loc->idx < col)
3316                 return -1;
3317         else
3318                 return 1;
3319 }
3320
3321 /**
3322  * search_ptr_table:
3323  *
3324  *  Return the 1-based row index in TABLE, which must be one of the *Ptr tables, 
3325  * which contains IDX.
3326  */
3327 static guint32
3328 search_ptr_table (MonoImage *image, int table, int idx)
3329 {
3330         MonoTableInfo *ptrdef = &image->tables [table];
3331         int i;
3332
3333         /* Use a linear search to find our index in the table */
3334         for (i = 0; i < ptrdef->rows; i ++)
3335                 /* All the Ptr tables have the same structure */
3336                 if (mono_metadata_decode_row_col (ptrdef, i, 0) == idx)
3337                         break;
3338
3339         if (i < ptrdef->rows)
3340                 return i + 1;
3341         else
3342                 return idx;
3343 }
3344
3345 /**
3346  * mono_metadata_typedef_from_field:
3347  * @meta: metadata context
3348  * @index: FieldDef token
3349  *
3350  * Returns: the 1-based index into the TypeDef table of the type that
3351  * declared the field described by @index, or 0 if not found.
3352  */
3353 guint32
3354 mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
3355 {
3356         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
3357         locator_t loc;
3358
3359         if (!tdef->base)
3360                 return 0;
3361
3362         loc.idx = mono_metadata_token_index (index);
3363         loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
3364         loc.t = tdef;
3365
3366         if (meta->uncompressed_metadata)
3367                 loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
3368
3369         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
3370                 g_assert_not_reached ();
3371
3372         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3373         return loc.result + 1;
3374 }
3375
3376 /*
3377  * mono_metadata_typedef_from_method:
3378  * @meta: metadata context
3379  * @index: MethodDef token
3380  *
3381  * Returns: the 1-based index into the TypeDef table of the type that
3382  * declared the method described by @index.  0 if not found.
3383  */
3384 guint32
3385 mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
3386 {
3387         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
3388         locator_t loc;
3389         
3390         if (!tdef->base)
3391                 return 0;
3392
3393         loc.idx = mono_metadata_token_index (index);
3394         loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
3395         loc.t = tdef;
3396
3397         if (meta->uncompressed_metadata)
3398                 loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx);
3399
3400         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
3401                 g_assert_not_reached ();
3402
3403         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3404         return loc.result + 1;
3405 }
3406
3407 /*
3408  * mono_metadata_interfaces_from_typedef_full:
3409  * @meta: metadata context
3410  * @index: typedef token
3411  * 
3412  * The array of interfaces that the @index typedef token implements is returned in
3413  * @interfaces. The number of elemnts in the array is returned in @count.
3414  *
3415  * LOCKING: Assumes the loader lock is held.
3416  *
3417  * Returns: TRUE on success, FALSE on failure.
3418  */
3419 gboolean
3420 mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, MonoGenericContext *context)
3421 {
3422         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
3423         locator_t loc;
3424         guint32 start, pos;
3425         guint32 cols [MONO_INTERFACEIMPL_SIZE];
3426         MonoClass **result;
3427
3428         *interfaces = NULL;
3429         *count = 0;
3430
3431         if (!tdef->base)
3432                 return TRUE;
3433
3434         loc.idx = mono_metadata_token_index (index);
3435         loc.col_idx = MONO_INTERFACEIMPL_CLASS;
3436         loc.t = tdef;
3437
3438         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3439                 return TRUE;
3440
3441         start = loc.result;
3442         /*
3443          * We may end up in the middle of the rows... 
3444          */
3445         while (start > 0) {
3446                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_INTERFACEIMPL_CLASS))
3447                         start--;
3448                 else
3449                         break;
3450         }
3451         pos = start;
3452         while (pos < tdef->rows) {
3453                 mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
3454                 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
3455                         break;
3456                 ++pos;
3457         }
3458
3459         result = mono_image_alloc0 (meta, sizeof (MonoClass*) * (pos - start));
3460
3461         pos = start;
3462         while (pos < tdef->rows) {
3463                 MonoClass *iface;
3464                 
3465                 mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
3466                 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
3467                         break;
3468                 iface = mono_class_get_full (
3469                         meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context);
3470                 if (iface == NULL)
3471                         return FALSE;
3472                 result [pos - start] = iface;
3473                 ++pos;
3474         }
3475         *count = pos - start;
3476         *interfaces = result;
3477         return TRUE;
3478 }
3479
3480 MonoClass**
3481 mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
3482 {
3483         MonoClass **interfaces;
3484         gboolean rv;
3485
3486         mono_loader_lock ();
3487         rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, NULL);
3488         mono_loader_unlock ();
3489         if (rv)
3490                 return interfaces;
3491         else
3492                 return NULL;
3493 }
3494
3495 /*
3496  * mono_metadata_nested_in_typedef:
3497  * @meta: metadata context
3498  * @index: typedef token
3499  * 
3500  * Returns: the 1-based index into the TypeDef table of the type
3501  * where the type described by @index is nested.
3502  * Retruns 0 if @index describes a non-nested type.
3503  */
3504 guint32
3505 mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
3506 {
3507         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
3508         locator_t loc;
3509         
3510         if (!tdef->base)
3511                 return 0;
3512
3513         loc.idx = mono_metadata_token_index (index);
3514         loc.col_idx = MONO_NESTED_CLASS_NESTED;
3515         loc.t = tdef;
3516
3517         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3518                 return 0;
3519
3520         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3521         return mono_metadata_decode_row_col (tdef, loc.result, MONO_NESTED_CLASS_ENCLOSING) | MONO_TOKEN_TYPE_DEF;
3522 }
3523
3524 /*
3525  * mono_metadata_nesting_typedef:
3526  * @meta: metadata context
3527  * @index: typedef token
3528  * 
3529  * Returns: the 1-based index into the TypeDef table of the first type
3530  * that is nested inside the type described by @index. The search starts at
3531  * @start_index.  returns 0 if no such type is found.
3532  */
3533 guint32
3534 mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
3535 {
3536         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
3537         guint32 start;
3538         guint32 class_index = mono_metadata_token_index (index);
3539         
3540         if (!tdef->base)
3541                 return 0;
3542
3543         start = start_index;
3544
3545         while (start <= tdef->rows) {
3546                 if (class_index == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
3547                         break;
3548                 else
3549                         start++;
3550         }
3551
3552         if (start > tdef->rows)
3553                 return 0;
3554         else
3555                 return start;
3556 }
3557
3558 /*
3559  * mono_metadata_packing_from_typedef:
3560  * @meta: metadata context
3561  * @index: token representing a type
3562  * 
3563  * Returns: the info stored in the ClassLAyout table for the given typedef token
3564  * into the @packing and @size pointers.
3565  * Returns 0 if the info is not found.
3566  */
3567 guint32
3568 mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *packing, guint32 *size)
3569 {
3570         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CLASSLAYOUT];
3571         locator_t loc;
3572         guint32 cols [MONO_CLASS_LAYOUT_SIZE];
3573         
3574         if (!tdef->base)
3575                 return 0;
3576
3577         loc.idx = mono_metadata_token_index (index);
3578         loc.col_idx = MONO_CLASS_LAYOUT_PARENT;
3579         loc.t = tdef;
3580
3581         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3582                 return 0;
3583
3584         mono_metadata_decode_row (tdef, loc.result, cols, MONO_CLASS_LAYOUT_SIZE);
3585         if (packing)
3586                 *packing = cols [MONO_CLASS_LAYOUT_PACKING_SIZE];
3587         if (size)
3588                 *size = cols [MONO_CLASS_LAYOUT_CLASS_SIZE];
3589
3590         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3591         return loc.result + 1;
3592 }
3593
3594 /*
3595  * mono_metadata_custom_attrs_from_index:
3596  * @meta: metadata context
3597  * @index: token representing the parent
3598  * 
3599  * Returns: the 1-based index into the CustomAttribute table of the first 
3600  * attribute which belongs to the metadata object described by @index.
3601  * Returns 0 if no such attribute is found.
3602  */
3603 guint32
3604 mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
3605 {
3606         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3607         locator_t loc;
3608         
3609         if (!tdef->base)
3610                 return 0;
3611
3612         loc.idx = index;
3613         loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
3614         loc.t = tdef;
3615
3616         /* FIXME: Index translation */
3617
3618         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
3619                 return 0;
3620
3621         /* Find the first entry by searching backwards */
3622         while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_CUSTOM_ATTR_PARENT) == index))
3623                 loc.result --;
3624
3625         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3626         return loc.result + 1;
3627 }
3628
3629 /*
3630  * mono_metadata_declsec_from_index:
3631  * @meta: metadata context
3632  * @index: token representing the parent
3633  * 
3634  * Returns: the 0-based index into the DeclarativeSecurity table of the first 
3635  * attribute which belongs to the metadata object described by @index.
3636  * Returns -1 if no such attribute is found.
3637  */
3638 guint32
3639 mono_metadata_declsec_from_index (MonoImage *meta, guint32 index)
3640 {
3641         MonoTableInfo *tdef = &meta->tables [MONO_TABLE_DECLSECURITY];
3642         locator_t loc;
3643
3644         if (!tdef->base)
3645                 return -1;
3646
3647         loc.idx = index;
3648         loc.col_idx = MONO_DECL_SECURITY_PARENT;
3649         loc.t = tdef;
3650
3651         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
3652                 return -1;
3653
3654         /* Find the first entry by searching backwards */
3655         while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_DECL_SECURITY_PARENT) == index))
3656                 loc.result --;
3657
3658         return loc.result;
3659 }
3660
3661 #ifdef DEBUG
3662 static void
3663 mono_backtrace (int limit)
3664 {
3665         void *array[limit];
3666         char **names;
3667         int i;
3668         backtrace (array, limit);
3669         names = backtrace_symbols (array, limit);
3670         for (i =0; i < limit; ++i) {
3671                 g_print ("\t%s\n", names [i]);
3672         }
3673         g_free (names);
3674 }
3675 #endif
3676
3677 #ifndef __GNUC__
3678 /*#define __alignof__(a) sizeof(a)*/
3679 #define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
3680 #endif
3681
3682 /*
3683  * mono_type_size:
3684  * @t: the type to return the size of
3685  *
3686  * Returns: the number of bytes required to hold an instance of this
3687  * type in memory
3688  */
3689 int
3690 mono_type_size (MonoType *t, int *align)
3691 {
3692         if (!t) {
3693                 *align = 1;
3694                 return 0;
3695         }
3696         if (t->byref) {
3697                 *align = __alignof__(gpointer);
3698                 return sizeof (gpointer);
3699         }
3700
3701         switch (t->type){
3702         case MONO_TYPE_VOID:
3703                 *align = 1;
3704                 return 0;
3705         case MONO_TYPE_BOOLEAN:
3706                 *align = __alignof__(gint8);
3707                 return 1;
3708         case MONO_TYPE_I1:
3709         case MONO_TYPE_U1:
3710                 *align = __alignof__(gint8);
3711                 return 1;
3712         case MONO_TYPE_CHAR:
3713         case MONO_TYPE_I2:
3714         case MONO_TYPE_U2:
3715                 *align = __alignof__(gint16);
3716                 return 2;               
3717         case MONO_TYPE_I4:
3718         case MONO_TYPE_U4:
3719                 *align = __alignof__(gint32);
3720                 return 4;
3721         case MONO_TYPE_R4:
3722                 *align = __alignof__(float);
3723                 return 4;
3724         case MONO_TYPE_I8:
3725         case MONO_TYPE_U8:
3726                 *align = __alignof__(gint64);
3727                 return 8;               
3728         case MONO_TYPE_R8:
3729                 *align = __alignof__(double);
3730                 return 8;               
3731         case MONO_TYPE_I:
3732         case MONO_TYPE_U:
3733                 *align = __alignof__(gpointer);
3734                 return sizeof (gpointer);
3735         case MONO_TYPE_STRING:
3736                 *align = __alignof__(gpointer);
3737                 return sizeof (gpointer);
3738         case MONO_TYPE_OBJECT:
3739                 *align = __alignof__(gpointer);
3740                 return sizeof (gpointer);
3741         case MONO_TYPE_VALUETYPE: {
3742                 if (t->data.klass->enumtype)
3743                         return mono_type_size (mono_class_enum_basetype (t->data.klass), align);
3744                 else
3745                         return mono_class_value_size (t->data.klass, (guint32*)align);
3746         }
3747         case MONO_TYPE_CLASS:
3748         case MONO_TYPE_SZARRAY:
3749         case MONO_TYPE_PTR:
3750         case MONO_TYPE_FNPTR:
3751         case MONO_TYPE_ARRAY:
3752                 *align = __alignof__(gpointer);
3753                 return sizeof (gpointer);
3754         case MONO_TYPE_TYPEDBYREF:
3755                 return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align);
3756         case MONO_TYPE_GENERICINST: {
3757                 MonoGenericClass *gclass = t->data.generic_class;
3758                 MonoClass *container_class = gclass->container_class;
3759
3760                 // g_assert (!gclass->inst->is_open);
3761
3762                 if (container_class->valuetype) {
3763                         if (container_class->enumtype)
3764                                 return mono_type_size (mono_class_enum_basetype (container_class), align);
3765                         else
3766                                 return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
3767                 } else {
3768                         *align = __alignof__(gpointer);
3769                         return sizeof (gpointer);
3770                 }
3771         }
3772         case MONO_TYPE_VAR:
3773         case MONO_TYPE_MVAR:
3774                 /* FIXME: Martin, this is wrong. */
3775                 *align = __alignof__(gpointer);
3776                 return sizeof (gpointer);
3777         default:
3778                 g_error ("mono_type_size: type 0x%02x unknown", t->type);
3779         }
3780         return 0;
3781 }
3782
3783 /*
3784  * mono_type_stack_size:
3785  * @t: the type to return the size it uses on the stack
3786  *
3787  * Returns: the number of bytes required to hold an instance of this
3788  * type on the runtime stack
3789  */
3790 int
3791 mono_type_stack_size (MonoType *t, int *align)
3792 {
3793         return mono_type_stack_size_internal (t, align, FALSE);
3794 }
3795
3796 int
3797 mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
3798 {
3799         int tmp;
3800 #if SIZEOF_VOID_P == SIZEOF_REGISTER
3801         int stack_slot_size = sizeof (gpointer);
3802         int stack_slot_align = __alignof__ (gpointer);
3803 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
3804         int stack_slot_size = SIZEOF_REGISTER;
3805         int stack_slot_align = SIZEOF_REGISTER;
3806 #endif
3807
3808         g_assert (t != NULL);
3809
3810         if (!align)
3811                 align = &tmp;
3812
3813         if (t->byref) {
3814                 *align = stack_slot_align;
3815                 return stack_slot_size;
3816         }
3817
3818         switch (t->type){
3819         case MONO_TYPE_BOOLEAN:
3820         case MONO_TYPE_CHAR:
3821         case MONO_TYPE_I1:
3822         case MONO_TYPE_U1:
3823         case MONO_TYPE_I2:
3824         case MONO_TYPE_U2:
3825         case MONO_TYPE_I4:
3826         case MONO_TYPE_U4:
3827         case MONO_TYPE_I:
3828         case MONO_TYPE_U:
3829         case MONO_TYPE_STRING:
3830         case MONO_TYPE_OBJECT:
3831         case MONO_TYPE_CLASS:
3832         case MONO_TYPE_SZARRAY:
3833         case MONO_TYPE_PTR:
3834         case MONO_TYPE_FNPTR:
3835         case MONO_TYPE_ARRAY:
3836                 *align = stack_slot_align;
3837                 return stack_slot_size;
3838         case MONO_TYPE_VAR:
3839         case MONO_TYPE_MVAR:
3840                 g_assert (allow_open);
3841                 *align = stack_slot_align;
3842                 return stack_slot_size;
3843         case MONO_TYPE_TYPEDBYREF:
3844                 *align = stack_slot_align;
3845                 return stack_slot_size * 3;
3846         case MONO_TYPE_R4:
3847                 *align = __alignof__(float);
3848                 return sizeof (float);          
3849         case MONO_TYPE_I8:
3850         case MONO_TYPE_U8:
3851                 *align = __alignof__(gint64);
3852                 return sizeof (gint64);         
3853         case MONO_TYPE_R8:
3854                 *align = __alignof__(double);
3855                 return sizeof (double);
3856         case MONO_TYPE_VALUETYPE: {
3857                 guint32 size;
3858
3859                 if (t->data.klass->enumtype)
3860                         return mono_type_stack_size_internal (mono_class_enum_basetype (t->data.klass), align, allow_open);
3861                 else {
3862                         size = mono_class_value_size (t->data.klass, (guint32*)align);
3863
3864                         *align = *align + stack_slot_align - 1;
3865                         *align &= ~(stack_slot_align - 1);
3866
3867                         size += stack_slot_size - 1;
3868                         size &= ~(stack_slot_size - 1);
3869
3870                         return size;
3871                 }
3872         }
3873         case MONO_TYPE_GENERICINST: {
3874                 MonoGenericClass *gclass = t->data.generic_class;
3875                 MonoClass *container_class = gclass->container_class;
3876
3877                 if (!allow_open)
3878                         g_assert (!gclass->context.class_inst->is_open);
3879
3880                 if (container_class->valuetype) {
3881                         if (container_class->enumtype)
3882                                 return mono_type_stack_size_internal (mono_class_enum_basetype (container_class), align, allow_open);
3883                         else {
3884                                 guint32 size = mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
3885
3886                                 *align = *align + stack_slot_align - 1;
3887                                 *align &= ~(stack_slot_align - 1);
3888
3889                                 size += stack_slot_size - 1;
3890                                 size &= ~(stack_slot_size - 1);
3891
3892                                 return size;
3893                         }
3894                 } else {
3895                         *align = stack_slot_align;
3896                         return stack_slot_size;
3897                 }
3898         }
3899         default:
3900                 g_error ("type 0x%02x unknown", t->type);
3901         }
3902         return 0;
3903 }
3904
3905 gboolean
3906 mono_type_generic_inst_is_valuetype (MonoType *type)
3907 {
3908         g_assert (type->type == MONO_TYPE_GENERICINST);
3909         return type->data.generic_class->container_class->valuetype;
3910 }
3911
3912 gboolean
3913 mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
3914 {
3915         return gclass->container_class->valuetype;
3916 }
3917
3918 static gboolean
3919 _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
3920 {
3921         MonoGenericInst *i1 = g1->context.class_inst;
3922         MonoGenericInst *i2 = g2->context.class_inst;
3923
3924         if (g1->is_dynamic != g2->is_dynamic)
3925                 return FALSE;
3926         if (!mono_metadata_class_equal (g1->container_class, g2->container_class, signature_only))
3927                 return FALSE;
3928         if (!mono_generic_inst_equal_full (i1, i2, signature_only))
3929                 return FALSE;
3930         return g1->is_tb_open == g2->is_tb_open;
3931 }
3932
3933 static gboolean
3934 _mono_metadata_generic_class_container_equal (const MonoGenericClass *g1, MonoClass *c2, gboolean signature_only)
3935 {
3936         MonoGenericInst *i1 = g1->context.class_inst;
3937         MonoGenericInst *i2 = c2->generic_container->context.class_inst;
3938
3939         if (!mono_metadata_class_equal (g1->container_class, c2, signature_only))
3940                 return FALSE;
3941         if (!mono_generic_inst_equal_full (i1, i2, signature_only))
3942                 return FALSE;
3943         return !g1->is_tb_open;
3944 }
3945
3946 guint
3947 mono_metadata_generic_context_hash (const MonoGenericContext *context)
3948 {
3949         /* FIXME: check if this seed is good enough */
3950         guint hash = 0xc01dfee7;
3951         if (context->class_inst)
3952                 hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->class_inst);
3953         if (context->method_inst)
3954                 hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->method_inst);
3955         return hash;
3956 }
3957
3958 gboolean
3959 mono_metadata_generic_context_equal (const MonoGenericContext *g1, const MonoGenericContext *g2)
3960 {
3961         return g1->class_inst == g2->class_inst && g1->method_inst == g2->method_inst;
3962 }
3963
3964 /*
3965  * mono_metadata_type_hash:
3966  * @t1: a type
3967  *
3968  * Computes an hash value for @t1 to be used in GHashTable.
3969  */
3970 guint
3971 mono_metadata_type_hash (MonoType *t1)
3972 {
3973         guint hash = t1->type;
3974
3975         hash |= t1->byref << 6; /* do not collide with t1->type values */
3976         switch (t1->type) {
3977         case MONO_TYPE_VALUETYPE:
3978         case MONO_TYPE_CLASS:
3979         case MONO_TYPE_SZARRAY:
3980                 /* check if the distribution is good enough */
3981                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
3982         case MONO_TYPE_PTR:
3983                 return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
3984         case MONO_TYPE_ARRAY:
3985                 return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
3986         case MONO_TYPE_GENERICINST:
3987                 return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
3988         }
3989         return hash;
3990 }
3991
3992 static gboolean
3993 mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, gboolean signature_only)
3994 {
3995         if (p1 == p2)
3996                 return TRUE;
3997         if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
3998                 return FALSE;
3999
4000         /*
4001          * We have to compare the image as well because if we didn't,
4002          * the generic_inst_cache lookup wouldn't care about the image
4003          * of generic params, so what could happen is that a generic
4004          * inst with params from image A is put into the cache, then
4005          * image B gets that generic inst from the cache, image A is
4006          * unloaded, so the inst is deleted, but image B still retains
4007          * a pointer to it.
4008          *
4009          * The AOT runtime doesn't set the image when it's decoding
4010          * types, so we only compare it when the owner is NULL.
4011          */
4012         if (mono_generic_param_owner (p1) == mono_generic_param_owner (p2) &&
4013             (mono_generic_param_owner (p1) || p1->image == p2->image))
4014                 return TRUE;
4015
4016         /*
4017          * If `signature_only' is true, we're comparing two (method) signatures.
4018          * In this case, the owner of two type parameters doesn't need to match.
4019          */
4020
4021         return signature_only;
4022 }
4023
4024 static gboolean
4025 mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only)
4026 {
4027         if (c1 == c2)
4028                 return TRUE;
4029         if (c1->generic_class && c2->generic_class)
4030                 return _mono_metadata_generic_class_equal (c1->generic_class, c2->generic_class, signature_only);
4031         if (c1->generic_class && c2->generic_container)
4032                 return _mono_metadata_generic_class_container_equal (c1->generic_class, c2, signature_only);
4033         if (c1->generic_container && c2->generic_class)
4034                 return _mono_metadata_generic_class_container_equal (c2->generic_class, c1, signature_only);
4035         if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
4036                 return mono_metadata_generic_param_equal (
4037                         c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
4038         if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR))
4039                 return mono_metadata_generic_param_equal (
4040                         c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
4041         if (signature_only &&
4042             (c1->byval_arg.type == MONO_TYPE_SZARRAY) && (c2->byval_arg.type == MONO_TYPE_SZARRAY))
4043                 return mono_metadata_class_equal (c1->byval_arg.data.klass, c2->byval_arg.data.klass, signature_only);
4044         return FALSE;
4045 }
4046
4047 static gboolean
4048 mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only)
4049 {
4050         gpointer iter1 = 0, iter2 = 0;
4051
4052         if (s1 == s2)
4053                 return TRUE;
4054         if (s1->call_convention != s2->call_convention)
4055                 return FALSE;
4056         if (s1->sentinelpos != s2->sentinelpos)
4057                 return FALSE;
4058         if (s1->hasthis != s2->hasthis)
4059                 return FALSE;
4060         if (s1->explicit_this != s2->explicit_this)
4061                 return FALSE;
4062         if (! do_mono_metadata_type_equal (s1->ret, s2->ret, signature_only))
4063                 return FALSE;
4064         if (s1->param_count != s2->param_count)
4065                 return FALSE;
4066
4067         while (TRUE) {
4068                 MonoType *t1 = mono_signature_get_params (s1, &iter1);
4069                 MonoType *t2 = mono_signature_get_params (s2, &iter2);
4070
4071                 if (t1 == NULL || t2 == NULL)
4072                         return (t1 == t2);
4073                 if (! do_mono_metadata_type_equal (t1, t2, signature_only))
4074                         return FALSE;
4075         }
4076 }
4077
4078 /*
4079  * mono_metadata_type_equal:
4080  * @t1: a type
4081  * @t2: another type
4082  *
4083  * Determine if @t1 and @t2 represent the same type.
4084  * Returns: #TRUE if @t1 and @t2 are equal.
4085  */
4086 static gboolean
4087 do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only)
4088 {
4089         if (t1->type != t2->type || t1->byref != t2->byref)
4090                 return FALSE;
4091
4092         switch (t1->type) {
4093         case MONO_TYPE_VOID:
4094         case MONO_TYPE_BOOLEAN:
4095         case MONO_TYPE_CHAR:
4096         case MONO_TYPE_I1:
4097         case MONO_TYPE_U1:
4098         case MONO_TYPE_I2:
4099         case MONO_TYPE_U2:
4100         case MONO_TYPE_I4:
4101         case MONO_TYPE_U4:
4102         case MONO_TYPE_I8:
4103         case MONO_TYPE_U8:
4104         case MONO_TYPE_R4:
4105         case MONO_TYPE_R8:
4106         case MONO_TYPE_STRING:
4107         case MONO_TYPE_I:
4108         case MONO_TYPE_U:
4109         case MONO_TYPE_OBJECT:
4110         case MONO_TYPE_TYPEDBYREF:
4111                 return TRUE;
4112         case MONO_TYPE_VALUETYPE:
4113         case MONO_TYPE_CLASS:
4114         case MONO_TYPE_SZARRAY:
4115                 return mono_metadata_class_equal (t1->data.klass, t2->data.klass, signature_only);
4116         case MONO_TYPE_PTR:
4117                 return do_mono_metadata_type_equal (t1->data.type, t2->data.type, signature_only);
4118         case MONO_TYPE_ARRAY:
4119                 if (t1->data.array->rank != t2->data.array->rank)
4120                         return FALSE;
4121                 return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass, signature_only);
4122         case MONO_TYPE_GENERICINST:
4123                 return _mono_metadata_generic_class_equal (
4124                         t1->data.generic_class, t2->data.generic_class, signature_only);
4125         case MONO_TYPE_VAR:
4126                 return mono_metadata_generic_param_equal (
4127                         t1->data.generic_param, t2->data.generic_param, signature_only);
4128         case MONO_TYPE_MVAR:
4129                 return mono_metadata_generic_param_equal (
4130                         t1->data.generic_param, t2->data.generic_param, signature_only);
4131         case MONO_TYPE_FNPTR:
4132                 return mono_metadata_fnptr_equal (t1->data.method, t2->data.method, signature_only);
4133         default:
4134                 g_error ("implement type compare for %0x!", t1->type);
4135                 return FALSE;
4136         }
4137
4138         return FALSE;
4139 }
4140
4141 gboolean
4142 mono_metadata_type_equal (MonoType *t1, MonoType *t2)
4143 {
4144         return do_mono_metadata_type_equal (t1, t2, FALSE);
4145 }
4146
4147 /**
4148  * mono_metadata_type_equal_full:
4149  * @t1: a type
4150  * @t2: another type
4151  * @signature_only: if signature only comparison should be made
4152  *
4153  * Determine if @t1 and @t2 are signature compatible if @signature_only is #TRUE, otherwise
4154  * behaves the same way as mono_metadata_type_equal.
4155  * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
4156  * Returns: #TRUE if @t1 and @t2 are equal taking @signature_only into account.
4157  */
4158 gboolean
4159 mono_metadata_type_equal_full (MonoType *t1, MonoType *t2, gboolean signature_only)
4160 {
4161         return do_mono_metadata_type_equal (t1, t2, signature_only);
4162 }
4163
4164 /**
4165  * mono_metadata_signature_equal:
4166  * @sig1: a signature
4167  * @sig2: another signature
4168  *
4169  * Determine if @sig1 and @sig2 represent the same signature, with the
4170  * same number of arguments and the same types.
4171  * Returns: #TRUE if @sig1 and @sig2 are equal.
4172  */
4173 gboolean
4174 mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
4175 {
4176         int i;
4177
4178         if (sig1->hasthis != sig2->hasthis || sig1->param_count != sig2->param_count)
4179                 return FALSE;
4180
4181         if (sig1->generic_param_count != sig2->generic_param_count)
4182                 return FALSE;
4183
4184         /*
4185          * We're just comparing the signatures of two methods here:
4186          *
4187          * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
4188          * U and V are equal here.
4189          *
4190          * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
4191          */
4192
4193         for (i = 0; i < sig1->param_count; i++) { 
4194                 MonoType *p1 = sig1->params[i];
4195                 MonoType *p2 = sig2->params[i];
4196                 
4197                 /* if (p1->attrs != p2->attrs)
4198                         return FALSE;
4199                 */
4200                 if (!do_mono_metadata_type_equal (p1, p2, TRUE))
4201                         return FALSE;
4202         }
4203
4204         if (!do_mono_metadata_type_equal (sig1->ret, sig2->ret, TRUE))
4205                 return FALSE;
4206         return TRUE;
4207 }
4208
4209 /**
4210  * mono_metadata_type_dup:
4211  * @image: image to alloc memory from
4212  * @original: type to duplicate
4213  *
4214  * Returns: copy of type allocated from the image's mempool (or from the heap, if @image is null).
4215  */
4216 MonoType *
4217 mono_metadata_type_dup (MonoImage *image, const MonoType *o)
4218 {
4219         MonoType *r = NULL;
4220         int sizeof_o = sizeof (MonoType);
4221         if (o->num_mods)
4222                 sizeof_o += (o->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
4223
4224         r = image ? mono_image_alloc0 (image, sizeof_o) : g_malloc (sizeof_o);
4225
4226         memcpy (r, o, sizeof_o);
4227
4228         if (o->type == MONO_TYPE_PTR) {
4229                 r->data.type = mono_metadata_type_dup (image, o->data.type);
4230         } else if (o->type == MONO_TYPE_ARRAY) {
4231                 r->data.array = mono_dup_array_type (image, o->data.array);
4232         } else if (o->type == MONO_TYPE_FNPTR) {
4233                 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
4234                 r->data.method = mono_metadata_signature_deep_dup (image, o->data.method);
4235         }
4236         return r;
4237 }
4238
4239 guint
4240 mono_signature_hash (MonoMethodSignature *sig)
4241 {
4242         guint i, res = sig->ret->type;
4243
4244         for (i = 0; i < sig->param_count; i++)
4245                 res = (res << 5) - res + mono_type_hash (sig->params[i]);
4246
4247         return res;
4248 }
4249
4250 /*
4251  * mono_metadata_encode_value:
4252  * @value: value to encode
4253  * @buf: buffer where to write the compressed representation
4254  * @endbuf: pointer updated to point at the end of the encoded output
4255  *
4256  * Encodes the value @value in the compressed representation used
4257  * in metadata and stores the result in @buf. @buf needs to be big
4258  * enough to hold the data (4 bytes).
4259  */
4260 void
4261 mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
4262 {
4263         char *p = buf;
4264         
4265         if (value < 0x80)
4266                 *p++ = value;
4267         else if (value < 0x4000) {
4268                 p [0] = 0x80 | (value >> 8);
4269                 p [1] = value & 0xff;
4270                 p += 2;
4271         } else {
4272                 p [0] = (value >> 24) | 0xc0;
4273                 p [1] = (value >> 16) & 0xff;
4274                 p [2] = (value >> 8) & 0xff;
4275                 p [3] = value & 0xff;
4276                 p += 4;
4277         }
4278         if (endbuf)
4279                 *endbuf = p;
4280 }
4281
4282 /*
4283  * mono_metadata_field_info:
4284  * @meta: the Image the field is defined in
4285  * @index: the index in the field table representing the field
4286  * @offset: a pointer to an integer where to store the offset that 
4287  * may have been specified for the field in a FieldLayout table
4288  * @rva: a pointer to the RVA of the field data in the image that
4289  * may have been defined in a FieldRVA table
4290  * @marshal_spec: a pointer to the marshal spec that may have been 
4291  * defined for the field in a FieldMarshal table.
4292  *
4293  * Gather info for field @index that may have been defined in the FieldLayout, 
4294  * FieldRVA and FieldMarshal tables.
4295  * Either of offset, rva and marshal_spec can be NULL if you're not interested 
4296  * in the data.
4297  */
4298 void
4299 mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
4300                           MonoMarshalSpec **marshal_spec)
4301 {
4302         mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, FALSE);
4303 }
4304
4305 void
4306 mono_metadata_field_info_with_mempool (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
4307                           MonoMarshalSpec **marshal_spec)
4308 {
4309         mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, TRUE);
4310 }
4311
4312 static void
4313 mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, 
4314                                        MonoMarshalSpec **marshal_spec, gboolean alloc_from_image)
4315 {
4316         MonoTableInfo *tdef;
4317         locator_t loc;
4318
4319         loc.idx = index + 1;
4320         if (meta->uncompressed_metadata)
4321                 loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
4322
4323         if (offset) {
4324                 tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
4325
4326                 loc.col_idx = MONO_FIELD_LAYOUT_FIELD;
4327                 loc.t = tdef;
4328
4329                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
4330                         *offset = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_LAYOUT_OFFSET);
4331                 } else {
4332                         *offset = (guint32)-1;
4333                 }
4334         }
4335         if (rva) {
4336                 tdef = &meta->tables [MONO_TABLE_FIELDRVA];
4337
4338                 loc.col_idx = MONO_FIELD_RVA_FIELD;
4339                 loc.t = tdef;
4340                 
4341                 if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
4342                         /*
4343                          * LAMESPEC: There is no signature, no nothing, just the raw data.
4344                          */
4345                         *rva = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_RVA_RVA);
4346                 } else {
4347                         *rva = 0;
4348                 }
4349         }
4350         if (marshal_spec) {
4351                 const char *p;
4352                 
4353                 if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
4354                         *marshal_spec = mono_metadata_parse_marshal_spec_full (alloc_from_image ? meta : NULL, p);
4355                 }
4356         }
4357
4358 }
4359
4360 /*
4361  * mono_metadata_get_constant_index:
4362  * @meta: the Image the field is defined in
4363  * @index: the token that may have a row defined in the constants table
4364  * @hint: possible position for the row
4365  *
4366  * @token must be a FieldDef, ParamDef or PropertyDef token.
4367  *
4368  * Returns: the index into the Constants table or 0 if not found.
4369  */
4370 guint32
4371 mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
4372 {
4373         MonoTableInfo *tdef;
4374         locator_t loc;
4375         guint32 index = mono_metadata_token_index (token);
4376
4377         tdef = &meta->tables [MONO_TABLE_CONSTANT];
4378         index <<= MONO_HASCONSTANT_BITS;
4379         switch (mono_metadata_token_table (token)) {
4380         case MONO_TABLE_FIELD:
4381                 index |= MONO_HASCONSTANT_FIEDDEF;
4382                 break;
4383         case MONO_TABLE_PARAM:
4384                 index |= MONO_HASCONSTANT_PARAM;
4385                 break;
4386         case MONO_TABLE_PROPERTY:
4387                 index |= MONO_HASCONSTANT_PROPERTY;
4388                 break;
4389         default:
4390                 g_warning ("Not a valid token for the constant table: 0x%08x", token);
4391                 return 0;
4392         }
4393         loc.idx = index;
4394         loc.col_idx = MONO_CONSTANT_PARENT;
4395         loc.t = tdef;
4396
4397         /* FIXME: Index translation */
4398
4399         if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
4400                 return hint;
4401
4402         if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
4403                 return loc.result + 1;
4404         }
4405         return 0;
4406 }
4407
4408 /*
4409  * mono_metadata_events_from_typedef:
4410  * @meta: metadata context
4411  * @index: 0-based index (in the TypeDef table) describing a type
4412  *
4413  * Returns: the 0-based index in the Event table for the events in the
4414  * type. The last event that belongs to the type (plus 1) is stored
4415  * in the @end_idx pointer.
4416  */
4417 guint32
4418 mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
4419 {
4420         locator_t loc;
4421         guint32 start, end;
4422         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_EVENTMAP];
4423
4424         *end_idx = 0;
4425         
4426         if (!tdef->base)
4427                 return 0;
4428
4429         loc.t = tdef;
4430         loc.col_idx = MONO_EVENT_MAP_PARENT;
4431         loc.idx = index + 1;
4432
4433         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4434                 return 0;
4435         
4436         start = mono_metadata_decode_row_col (tdef, loc.result, MONO_EVENT_MAP_EVENTLIST);
4437         if (loc.result + 1 < tdef->rows) {
4438                 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_EVENT_MAP_EVENTLIST) - 1;
4439         } else {
4440                 end = meta->tables [MONO_TABLE_EVENT].rows;
4441         }
4442
4443         *end_idx = end;
4444         return start - 1;
4445 }
4446
4447 /*
4448  * mono_metadata_methods_from_event:
4449  * @meta: metadata context
4450  * @index: 0-based index (in the Event table) describing a event
4451  *
4452  * Returns: the 0-based index in the MethodDef table for the methods in the
4453  * event. The last method that belongs to the event (plus 1) is stored
4454  * in the @end_idx pointer.
4455  */
4456 guint32
4457 mono_metadata_methods_from_event   (MonoImage *meta, guint32 index, guint *end_idx)
4458 {
4459         locator_t loc;
4460         guint start, end;
4461         guint32 cols [MONO_METHOD_SEMA_SIZE];
4462         MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
4463
4464         *end_idx = 0;
4465         if (!msemt->base)
4466                 return 0;
4467
4468         if (meta->uncompressed_metadata)
4469             index = search_ptr_table (meta, MONO_TABLE_EVENT_POINTER, index + 1) - 1;
4470
4471         loc.t = msemt;
4472         loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
4473         loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
4474
4475         if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
4476                 return 0;
4477
4478         start = loc.result;
4479         /*
4480          * We may end up in the middle of the rows... 
4481          */
4482         while (start > 0) {
4483                 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
4484                         start--;
4485                 else
4486                         break;
4487         }
4488         end = start + 1;
4489         while (end < msemt->rows) {
4490                 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
4491                 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
4492                         break;
4493                 ++end;
4494         }
4495         *end_idx = end;
4496         return start;
4497 }
4498
4499 /*
4500  * mono_metadata_properties_from_typedef:
4501  * @meta: metadata context
4502  * @index: 0-based index (in the TypeDef table) describing a type
4503  *
4504  * Returns: the 0-based index in the Property table for the properties in the
4505  * type. The last property that belongs to the type (plus 1) is stored
4506  * in the @end_idx pointer.
4507  */
4508 guint32
4509 mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
4510 {
4511         locator_t loc;
4512         guint32 start, end;
4513         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_PROPERTYMAP];
4514
4515         *end_idx = 0;
4516         
4517         if (!tdef->base)
4518                 return 0;
4519
4520         loc.t = tdef;
4521         loc.col_idx = MONO_PROPERTY_MAP_PARENT;
4522         loc.idx = index + 1;
4523
4524         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4525                 return 0;
4526         
4527         start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST);
4528         if (loc.result + 1 < tdef->rows) {
4529                 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_PROPERTY_MAP_PROPERTY_LIST) - 1;
4530         } else {
4531                 end = meta->tables [MONO_TABLE_PROPERTY].rows;
4532         }
4533
4534         *end_idx = end;
4535         return start - 1;
4536 }
4537
4538 /*
4539  * mono_metadata_methods_from_property:
4540  * @meta: metadata context
4541  * @index: 0-based index (in the PropertyDef table) describing a property
4542  *
4543  * Returns: the 0-based index in the MethodDef table for the methods in the
4544  * property. The last method that belongs to the property (plus 1) is stored
4545  * in the @end_idx pointer.
4546  */
4547 guint32
4548 mono_metadata_methods_from_property   (MonoImage *meta, guint32 index, guint *end_idx)
4549 {
4550         locator_t loc;
4551         guint start, end;
4552         guint32 cols [MONO_METHOD_SEMA_SIZE];
4553         MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
4554
4555         *end_idx = 0;
4556         if (!msemt->base)
4557                 return 0;
4558
4559         if (meta->uncompressed_metadata)
4560             index = search_ptr_table (meta, MONO_TABLE_PROPERTY_POINTER, index + 1) - 1;
4561
4562         loc.t = msemt;
4563         loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
4564         loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
4565
4566         if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
4567                 return 0;
4568
4569         start = loc.result;
4570         /*
4571          * We may end up in the middle of the rows... 
4572          */
4573         while (start > 0) {
4574                 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
4575                         start--;
4576                 else
4577                         break;
4578         }
4579         end = start + 1;
4580         while (end < msemt->rows) {
4581                 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
4582                 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
4583                         break;
4584                 ++end;
4585         }
4586         *end_idx = end;
4587         return start;
4588 }
4589
4590 guint32
4591 mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
4592 {
4593         locator_t loc;
4594         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_IMPLMAP];
4595
4596         if (!tdef->base)
4597                 return 0;
4598
4599         /* No index translation seems to be needed */
4600
4601         loc.t = tdef;
4602         loc.col_idx = MONO_IMPLMAP_MEMBER;
4603         loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
4604
4605         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4606                 return 0;
4607
4608         return loc.result + 1;
4609 }
4610
4611 /**
4612  * @image: context where the image is created
4613  * @type_spec:  typespec token
4614  *
4615  * Creates a MonoType representing the TypeSpec indexed by the @type_spec
4616  * token.
4617  */
4618 MonoType *
4619 mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
4620 {
4621         guint32 idx = mono_metadata_token_index (type_spec);
4622         MonoTableInfo *t;
4623         guint32 cols [MONO_TYPESPEC_SIZE];
4624         const char *ptr;
4625         guint32 len;
4626         MonoType *type, *type2;
4627
4628         mono_loader_lock ();
4629
4630         type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
4631         if (type) {
4632                 mono_loader_unlock ();
4633                 return type;
4634         }
4635
4636         t = &image->tables [MONO_TABLE_TYPESPEC];
4637
4638         mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
4639         ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
4640         len = mono_metadata_decode_value (ptr, &ptr);
4641
4642         type = mono_image_alloc0 (image, sizeof (MonoType));
4643
4644         if (*ptr == MONO_TYPE_BYREF) {
4645                 type->byref = 1;
4646                 ptr++;
4647         }
4648
4649         if (!do_mono_metadata_parse_type (type, image, NULL, ptr, &ptr)) {
4650                 mono_loader_unlock ();
4651                 return NULL;
4652         }
4653
4654         type2 = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
4655
4656         if (type2) {
4657                 mono_loader_unlock ();
4658                 return type2;
4659         }
4660
4661         g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type);
4662
4663         mono_loader_unlock ();
4664
4665         return type;
4666 }
4667
4668
4669 static char*
4670 mono_image_strndup (MonoImage *image, const char *data, guint len)
4671 {
4672         char *res;
4673         if (!image)
4674                 return g_strndup (data, len);
4675         res = mono_image_alloc (image, len + 1);
4676         memcpy (res, data, len);
4677         res [len] = 0;
4678         return res;
4679 }
4680
4681 MonoMarshalSpec *
4682 mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
4683 {
4684         return mono_metadata_parse_marshal_spec_full (NULL, ptr);
4685 }
4686
4687 MonoMarshalSpec *
4688 mono_metadata_parse_marshal_spec_full (MonoImage *image, const char *ptr)
4689 {
4690         MonoMarshalSpec *res;
4691         int len;
4692         const char *start = ptr;
4693
4694         /* fixme: this is incomplete, but I cant find more infos in the specs */
4695
4696         if (image)
4697                 res = mono_image_alloc0 (image, sizeof (MonoMarshalSpec));
4698         else
4699                 res = g_new0 (MonoMarshalSpec, 1);
4700         
4701         len = mono_metadata_decode_value (ptr, &ptr);
4702         res->native = *ptr++;
4703
4704         if (res->native == MONO_NATIVE_LPARRAY) {
4705                 res->data.array_data.param_num = -1;
4706                 res->data.array_data.num_elem = -1;
4707                 res->data.array_data.elem_mult = -1;
4708
4709                 if (ptr - start <= len)
4710                         res->data.array_data.elem_type = *ptr++;
4711                 if (ptr - start <= len)
4712                         res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr);
4713                 if (ptr - start <= len)
4714                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
4715                 if (ptr - start <= len) {
4716                         /*
4717                          * LAMESPEC: Older spec versions say this parameter comes before 
4718                          * num_elem. Never spec versions don't talk about elem_mult at
4719                          * all, but csc still emits it, and it is used to distinguish
4720                          * between param_num being 0, and param_num being omitted.
4721                          * So if (param_num == 0) && (num_elem > 0), then
4722                          * elem_mult == 0 -> the array size is num_elem
4723                          * elem_mult == 1 -> the array size is @param_num + num_elem
4724                          */
4725                         res->data.array_data.elem_mult = mono_metadata_decode_value (ptr, &ptr);
4726                 }
4727         } 
4728
4729         if (res->native == MONO_NATIVE_BYVALTSTR) {
4730                 if (ptr - start <= len)
4731                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
4732         }
4733
4734         if (res->native == MONO_NATIVE_BYVALARRAY) {
4735                 if (ptr - start <= len)
4736                         res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
4737         }
4738         
4739         if (res->native == MONO_NATIVE_CUSTOM) {
4740                 /* skip unused type guid */
4741                 len = mono_metadata_decode_value (ptr, &ptr);
4742                 ptr += len;
4743                 /* skip unused native type name */
4744                 len = mono_metadata_decode_value (ptr, &ptr);
4745                 ptr += len;
4746                 /* read custom marshaler type name */
4747                 len = mono_metadata_decode_value (ptr, &ptr);
4748                 res->data.custom_data.custom_name = mono_image_strndup (image, ptr, len);               
4749                 ptr += len;
4750                 /* read cookie string */
4751                 len = mono_metadata_decode_value (ptr, &ptr);
4752                 res->data.custom_data.cookie = mono_image_strndup (image, ptr, len);
4753         }
4754
4755         if (res->native == MONO_NATIVE_SAFEARRAY) {
4756                 res->data.safearray_data.elem_type = 0;
4757                 res->data.safearray_data.num_elem = 0;
4758                 if (ptr - start <= len)
4759                         res->data.safearray_data.elem_type = *ptr++;
4760                 if (ptr - start <= len)
4761                         res->data.safearray_data.num_elem = *ptr++;
4762         }
4763         return res;
4764 }
4765
4766 void 
4767 mono_metadata_free_marshal_spec (MonoMarshalSpec *spec)
4768 {
4769         if (spec->native == MONO_NATIVE_CUSTOM) {
4770                 g_free (spec->data.custom_data.custom_name);
4771                 g_free (spec->data.custom_data.cookie);
4772         }
4773         g_free (spec);
4774 }
4775
4776 /**
4777  * mono_type_to_unmanaged:
4778  *
4779  * Returns: A MonoMarshalNative enumeration value (MONO_NATIVE_) value
4780  * describing the underlying native reprensetation of the type.
4781  * 
4782  * In addition the value pointed by
4783  * "conv" will contain the kind of marshalling required for this
4784  * particular type one of the MONO_MARSHAL_CONV_ enumeration values.
4785  */
4786 guint32
4787 mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_field,
4788                         gboolean unicode, MonoMarshalConv *conv) 
4789 {
4790         MonoMarshalConv dummy_conv;
4791         int t = type->type;
4792
4793         if (!conv)
4794                 conv = &dummy_conv;
4795
4796         *conv = MONO_MARSHAL_CONV_NONE;
4797
4798         if (type->byref)
4799                 return MONO_NATIVE_UINT;
4800
4801 handle_enum:
4802         switch (t) {
4803         case MONO_TYPE_BOOLEAN: 
4804                 if (mspec) {
4805                         switch (mspec->native) {
4806                         case MONO_NATIVE_VARIANTBOOL:
4807                                 *conv = MONO_MARSHAL_CONV_BOOL_VARIANTBOOL;
4808                                 return MONO_NATIVE_VARIANTBOOL;
4809                         case MONO_NATIVE_BOOLEAN:
4810                                 *conv = MONO_MARSHAL_CONV_BOOL_I4;
4811                                 return MONO_NATIVE_BOOLEAN;
4812                         case MONO_NATIVE_I1:
4813                         case MONO_NATIVE_U1:
4814                                 return mspec->native;
4815                         default:
4816                                 g_error ("cant marshal bool to native type %02x", mspec->native);
4817                         }
4818                 }
4819                 *conv = MONO_MARSHAL_CONV_BOOL_I4;
4820                 return MONO_NATIVE_BOOLEAN;
4821         case MONO_TYPE_CHAR: return MONO_NATIVE_U2;
4822         case MONO_TYPE_I1: return MONO_NATIVE_I1;
4823         case MONO_TYPE_U1: return MONO_NATIVE_U1;
4824         case MONO_TYPE_I2: return MONO_NATIVE_I2;
4825         case MONO_TYPE_U2: return MONO_NATIVE_U2;
4826         case MONO_TYPE_I4: return MONO_NATIVE_I4;
4827         case MONO_TYPE_U4: return MONO_NATIVE_U4;
4828         case MONO_TYPE_I8: return MONO_NATIVE_I8;
4829         case MONO_TYPE_U8: return MONO_NATIVE_U8;
4830         case MONO_TYPE_R4: return MONO_NATIVE_R4;
4831         case MONO_TYPE_R8: return MONO_NATIVE_R8;
4832         case MONO_TYPE_STRING:
4833                 if (mspec) {
4834                         switch (mspec->native) {
4835                         case MONO_NATIVE_BSTR:
4836                                 *conv = MONO_MARSHAL_CONV_STR_BSTR;
4837                                 return MONO_NATIVE_BSTR;
4838                         case MONO_NATIVE_LPSTR:
4839                                 *conv = MONO_MARSHAL_CONV_STR_LPSTR;
4840                                 return MONO_NATIVE_LPSTR;
4841                         case MONO_NATIVE_LPWSTR:
4842                                 *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
4843                                 return MONO_NATIVE_LPWSTR;
4844                         case MONO_NATIVE_LPTSTR:
4845                                 *conv = MONO_MARSHAL_CONV_STR_LPTSTR;
4846                                 return MONO_NATIVE_LPTSTR;
4847                         case MONO_NATIVE_ANSIBSTR:
4848                                 *conv = MONO_MARSHAL_CONV_STR_ANSIBSTR;
4849                                 return MONO_NATIVE_ANSIBSTR;
4850                         case MONO_NATIVE_TBSTR:
4851                                 *conv = MONO_MARSHAL_CONV_STR_TBSTR;
4852                                 return MONO_NATIVE_TBSTR;
4853                         case MONO_NATIVE_BYVALTSTR:
4854                                 if (unicode)
4855                                         *conv = MONO_MARSHAL_CONV_STR_BYVALWSTR;
4856                                 else
4857                                         *conv = MONO_MARSHAL_CONV_STR_BYVALSTR;
4858                                 return MONO_NATIVE_BYVALTSTR;
4859                         default:
4860                                 g_error ("Can not marshal string to native type '%02x': Invalid managed/unmanaged type combination (String fields must be paired with LPStr, LPWStr, BStr or ByValTStr).", mspec->native);
4861                         }
4862                 }       
4863                 if (unicode) {
4864                         *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
4865                         return MONO_NATIVE_LPWSTR; 
4866                 }
4867                 else {
4868                         *conv = MONO_MARSHAL_CONV_STR_LPSTR;
4869                         return MONO_NATIVE_LPSTR; 
4870                 }
4871         case MONO_TYPE_PTR: return MONO_NATIVE_UINT;
4872         case MONO_TYPE_VALUETYPE: /*FIXME*/
4873                 if (type->data.klass->enumtype) {
4874                         t = mono_class_enum_basetype (type->data.klass)->type;
4875                         goto handle_enum;
4876                 }
4877                 if (type->data.klass == mono_defaults.handleref_class){
4878                         *conv = MONO_MARSHAL_CONV_HANDLEREF;
4879                         return MONO_NATIVE_INT;
4880                 }
4881                 return MONO_NATIVE_STRUCT;
4882         case MONO_TYPE_SZARRAY: 
4883         case MONO_TYPE_ARRAY: 
4884                 if (mspec) {
4885                         switch (mspec->native) {
4886                         case MONO_NATIVE_BYVALARRAY:
4887                                 if ((type->data.klass->element_class == mono_defaults.char_class) && !unicode)
4888                                         *conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY;
4889                                 else
4890                                         *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
4891                                 return MONO_NATIVE_BYVALARRAY;
4892                         case MONO_NATIVE_SAFEARRAY:
4893                                 *conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY;
4894                                 return MONO_NATIVE_SAFEARRAY;
4895                         case MONO_NATIVE_LPARRAY:                               
4896                                 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
4897                                 return MONO_NATIVE_LPARRAY;
4898                         default:
4899                                 g_error ("cant marshal array as native type %02x", mspec->native);
4900                         }
4901                 }       
4902
4903                 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
4904                 return MONO_NATIVE_LPARRAY;
4905         case MONO_TYPE_I: return MONO_NATIVE_INT;
4906         case MONO_TYPE_U: return MONO_NATIVE_UINT;
4907         case MONO_TYPE_CLASS: 
4908         case MONO_TYPE_OBJECT: {
4909                 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
4910                 if (mspec) {
4911                         switch (mspec->native) {
4912                         case MONO_NATIVE_STRUCT:
4913                                 return MONO_NATIVE_STRUCT;
4914                         case MONO_NATIVE_CUSTOM:
4915                                 return MONO_NATIVE_CUSTOM;
4916                         case MONO_NATIVE_INTERFACE:
4917                                 *conv = MONO_MARSHAL_CONV_OBJECT_INTERFACE;
4918                                 return MONO_NATIVE_INTERFACE;
4919                         case MONO_NATIVE_IDISPATCH:
4920                                 *conv = MONO_MARSHAL_CONV_OBJECT_IDISPATCH;
4921                                 return MONO_NATIVE_IDISPATCH;
4922                         case MONO_NATIVE_IUNKNOWN:
4923                                 *conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN;
4924                                 return MONO_NATIVE_IUNKNOWN;
4925                         case MONO_NATIVE_FUNC:
4926                                 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
4927                                                                                          type->data.klass == mono_defaults.delegate_class || 
4928                                                                                          type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
4929                                         *conv = MONO_MARSHAL_CONV_DEL_FTN;
4930                                         return MONO_NATIVE_FUNC;
4931                                 }
4932                                 /* Fall through */
4933                         default:
4934                                 g_error ("cant marshal object as native type %02x", mspec->native);
4935                         }
4936                 }
4937                 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
4938                                              type->data.klass == mono_defaults.delegate_class || 
4939                                              type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
4940                         *conv = MONO_MARSHAL_CONV_DEL_FTN;
4941                         return MONO_NATIVE_FUNC;
4942                 }
4943                 if (mono_defaults.safehandle_class && type->data.klass == mono_defaults.safehandle_class){
4944                         *conv = MONO_MARSHAL_CONV_SAFEHANDLE;
4945                         return MONO_NATIVE_INT;
4946                 }
4947                 *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT;
4948                 return MONO_NATIVE_STRUCT;
4949         }
4950         case MONO_TYPE_FNPTR: return MONO_NATIVE_FUNC;
4951         case MONO_TYPE_GENERICINST:
4952                 type = &type->data.generic_class->container_class->byval_arg;
4953                 t = type->type;
4954                 goto handle_enum;
4955         case MONO_TYPE_TYPEDBYREF:
4956         default:
4957                 g_error ("type 0x%02x not handled in marshal", t);
4958         }
4959         return MONO_NATIVE_MAX;
4960 }
4961
4962 const char*
4963 mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
4964 {
4965         locator_t loc;
4966         MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_FIELDMARSHAL];
4967
4968         if (!tdef->base)
4969                 return NULL;
4970
4971         loc.t = tdef;
4972         loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
4973         loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
4974
4975         /* FIXME: Index translation */
4976
4977         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4978                 return NULL;
4979
4980         return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
4981 }
4982
4983 static MonoMethod*
4984 method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
4985 {
4986         guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
4987
4988         switch (tok & MONO_METHODDEFORREF_MASK) {
4989         case MONO_METHODDEFORREF_METHODDEF:
4990                 return mono_get_method_full (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context);
4991         case MONO_METHODDEFORREF_METHODREF:
4992                 return mono_get_method_full (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context);
4993         }
4994         g_assert_not_reached ();
4995         return NULL;
4996 }
4997
4998 /*
4999  * mono_class_get_overrides_full:
5000  *
5001  *   Return the method overrides belonging to class @type_token in @overrides, and
5002  * the number of overrides in @num_overrides.
5003  *
5004  * Returns: TRUE on success, FALSE on failure.
5005  */
5006 gboolean
5007 mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides,
5008                                MonoGenericContext *generic_context)
5009 {
5010         locator_t loc;
5011         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_METHODIMPL];
5012         guint32 start, end;
5013         gint32 i, num;
5014         guint32 cols [MONO_METHODIMPL_SIZE];
5015         MonoMethod **result;
5016         gint32 ok = TRUE;
5017         
5018         *overrides = NULL;
5019         if (num_overrides)
5020                 *num_overrides = 0;
5021
5022         if (!tdef->base)
5023                 return TRUE;
5024
5025         loc.t = tdef;
5026         loc.col_idx = MONO_METHODIMPL_CLASS;
5027         loc.idx = mono_metadata_token_index (type_token);
5028
5029         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5030                 return TRUE;
5031
5032         start = loc.result;
5033         end = start + 1;
5034         /*
5035          * We may end up in the middle of the rows... 
5036          */
5037         while (start > 0) {
5038                 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_METHODIMPL_CLASS))
5039                         start--;
5040                 else
5041                         break;
5042         }
5043         while (end < tdef->rows) {
5044                 if (loc.idx == mono_metadata_decode_row_col (tdef, end, MONO_METHODIMPL_CLASS))
5045                         end++;
5046                 else
5047                         break;
5048         }
5049         num = end - start;
5050         result = g_new (MonoMethod*, num * 2);
5051         for (i = 0; i < num; ++i) {
5052                 MonoMethod *method;
5053
5054                 mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
5055                 method = method_from_method_def_or_ref (
5056                         image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
5057                 if (method == NULL)
5058                         ok = FALSE;
5059                 result [i * 2] = method;
5060                 method = method_from_method_def_or_ref (
5061                         image, cols [MONO_METHODIMPL_BODY], generic_context);
5062                 if (method == NULL)
5063                         ok = FALSE;
5064                 result [i * 2 + 1] = method;
5065         }
5066
5067         *overrides = result;
5068         if (num_overrides)
5069                 *num_overrides = num;
5070         return ok;
5071 }
5072
5073 /**
5074  * mono_guid_to_string:
5075  *
5076  * Converts a 16 byte Microsoft GUID to the standard string representation.
5077  */
5078 char *
5079 mono_guid_to_string (const guint8 *guid)
5080 {
5081         return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", 
5082                                 guid[3], guid[2], guid[1], guid[0],
5083                                 guid[5], guid[4],
5084                                 guid[7], guid[6],
5085                                 guid[8], guid[9],
5086                                 guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
5087 }
5088
5089 static gboolean
5090 get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container)
5091 {
5092         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
5093         guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
5094         guint32 i, token, found;
5095         MonoClass *klass, **res;
5096         GList *cons = NULL, *tmp;
5097         MonoGenericContext *context = &container->context;
5098
5099         *constraints = NULL;
5100         found = 0;
5101         for (i = 0; i < tdef->rows; ++i) {
5102                 mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
5103                 if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
5104                         token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
5105                         klass = mono_class_get_full (image, token, context);
5106                         cons = g_list_append (cons, klass);
5107                         ++found;
5108                 } else {
5109                         /* contiguous list finished */
5110                         if (found)
5111                                 break;
5112                 }
5113         }
5114         if (!found)
5115                 return TRUE;
5116         res = g_new0 (MonoClass*, found + 1);
5117         for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
5118                 res [i] = tmp->data;
5119         }
5120         g_list_free (cons);
5121         *constraints = res;
5122         return TRUE;
5123 }
5124
5125 /*
5126  * mono_metadata_get_generic_param_row:
5127  *
5128  * @image:
5129  * @token: TypeOrMethodDef token, owner for GenericParam
5130  * @owner: coded token, set on return
5131  * 
5132  * Returns: 1-based row-id in the GenericParam table whose
5133  * owner is @token. 0 if not found.
5134  */
5135 guint32
5136 mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *owner)
5137 {
5138         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
5139         locator_t loc;
5140
5141         g_assert (owner);
5142         if (!tdef->base)
5143                 return 0;
5144
5145         if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
5146                 *owner = MONO_TYPEORMETHOD_TYPE;
5147         else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
5148                 *owner = MONO_TYPEORMETHOD_METHOD;
5149         else {
5150                 g_error ("wrong token %x to get_generic_param_row", token);
5151                 return 0;
5152         }
5153         *owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
5154
5155         loc.idx = *owner;
5156         loc.col_idx = MONO_GENERICPARAM_OWNER;
5157         loc.t = tdef;
5158
5159         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5160                 return 0;
5161
5162         /* Find the first entry by searching backwards */
5163         while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_GENERICPARAM_OWNER) == loc.idx))
5164                 loc.result --;
5165
5166         return loc.result + 1;
5167 }
5168
5169 gboolean
5170 mono_metadata_has_generic_params (MonoImage *image, guint32 token)
5171 {
5172         guint32 owner;
5173         return mono_metadata_get_generic_param_row (image, token, &owner);
5174 }
5175
5176 /*
5177  * mono_metadata_load_generic_param_constraints:
5178  *
5179  * Load the generic parameter constraints for the newly created generic type or method
5180  * represented by @token and @container.  The @container is the new container which has
5181  * been returned by a call to mono_metadata_load_generic_params() with this @token.
5182  */
5183 void
5184 mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,
5185                                               MonoGenericContainer *container)
5186 {
5187         guint32 start_row, i, owner;
5188         if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
5189                 return;
5190         for (i = 0; i < container->type_argc; i++)
5191                 get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container);
5192 }
5193
5194 /*
5195  * mono_metadata_load_generic_params:
5196  *
5197  * Load the type parameters from the type or method definition @token.
5198  *
5199  * Use this method after parsing a type or method definition to figure out whether it's a generic
5200  * type / method.  When parsing a method definition, @parent_container points to the generic container
5201  * of the current class, if any.
5202  *
5203  * Note: This method does not load the constraints: for typedefs, this has to be done after fully
5204  *       creating the type.
5205  *
5206  * Returns: NULL if @token is not a generic type or method definition or the new generic container.
5207  *
5208  * LOCKING: Acquires the loader lock
5209  *
5210  */
5211 MonoGenericContainer *
5212 mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
5213 {
5214         MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
5215         guint32 cols [MONO_GENERICPARAM_SIZE];
5216         guint32 i, owner = 0, n;
5217         MonoGenericContainer *container;
5218         MonoGenericParamFull *params;
5219         MonoGenericContext *context;
5220
5221         if (!(i = mono_metadata_get_generic_param_row (image, token, &owner)))
5222                 return NULL;
5223         mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
5224         params = NULL;
5225         n = 0;
5226         container = mono_image_alloc0 (image, sizeof (MonoGenericContainer));
5227         do {
5228                 n++;
5229                 params = g_realloc (params, sizeof (MonoGenericParamFull) * n);
5230                 memset (&params [n - 1], 0, sizeof (MonoGenericParamFull));
5231                 params [n - 1].param.owner = container;
5232                 params [n - 1].param.num = cols [MONO_GENERICPARAM_NUMBER];
5233                 params [n - 1].info.token = i | MONO_TOKEN_GENERIC_PARAM;
5234                 params [n - 1].info.flags = cols [MONO_GENERICPARAM_FLAGS];
5235                 params [n - 1].info.name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
5236                 if (params [n - 1].param.num != n - 1)
5237                         g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i);
5238                 if (++i > tdef->rows)
5239                         break;
5240                 mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
5241         } while (cols [MONO_GENERICPARAM_OWNER] == owner);
5242
5243         container->type_argc = n;
5244         container->type_params = mono_image_alloc0 (image, sizeof (MonoGenericParamFull) * n);
5245         memcpy (container->type_params, params, sizeof (MonoGenericParamFull) * n);
5246         g_free (params);
5247         container->parent = parent_container;
5248
5249         if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
5250                 container->is_method = 1;
5251
5252         g_assert (container->parent == NULL || container->is_method);
5253
5254         context = &container->context;
5255         if (container->is_method) {
5256                 context->class_inst = container->parent ? container->parent->context.class_inst : NULL;
5257                 context->method_inst = mono_get_shared_generic_inst (container);
5258         } else {
5259                 context->class_inst = mono_get_shared_generic_inst (container);
5260         }
5261
5262         return container;
5263 }
5264
5265 MonoGenericInst *
5266 mono_get_shared_generic_inst (MonoGenericContainer *container)
5267 {
5268         MonoType **type_argv;
5269         MonoType *helper;
5270         MonoGenericInst *nginst;
5271         int i;
5272
5273         type_argv = g_new0 (MonoType *, container->type_argc);
5274         helper = g_new0 (MonoType, container->type_argc);
5275
5276         for (i = 0; i < container->type_argc; i++) {
5277                 MonoType *t = &helper [i];
5278
5279                 t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5280                 t->data.generic_param = mono_generic_container_get_param (container, i);
5281
5282                 type_argv [i] = t;
5283         }
5284
5285         nginst = mono_metadata_get_generic_inst (container->type_argc, type_argv);
5286
5287         g_free (type_argv);
5288         g_free (helper);
5289
5290         return nginst;
5291 }
5292
5293 gboolean
5294 mono_type_is_byref (MonoType *type)
5295 {
5296         return type->byref;
5297 }
5298
5299 int
5300 mono_type_get_type (MonoType *type)
5301 {
5302         return type->type;
5303 }
5304
5305 /* For MONO_TYPE_FNPTR */
5306 MonoMethodSignature*
5307 mono_type_get_signature (MonoType *type)
5308 {
5309         return type->data.method;
5310 }
5311
5312 /* For MONO_TYPE_CLASS, VALUETYPE */
5313 MonoClass*
5314 mono_type_get_class (MonoType *type)
5315 {
5316         return type->data.klass;
5317 }
5318
5319 /* For MONO_TYPE_ARRAY */
5320 MonoArrayType*
5321 mono_type_get_array_type (MonoType *type)
5322 {
5323         return type->data.array;
5324 }
5325
5326 /* For MONO_TYPE_PTR */
5327 MonoType*
5328 mono_type_get_ptr_type (MonoType *type)
5329 {
5330         return type->data.type;
5331 }
5332
5333 MonoClass*
5334 mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
5335 {
5336         /* FIXME: implement */
5337         return NULL;
5338 }
5339
5340 MonoType*
5341 mono_signature_get_return_type (MonoMethodSignature *sig)
5342 {
5343         return sig->ret;
5344 }
5345
5346 MonoType*
5347 mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
5348 {
5349         MonoType** type;
5350         if (!iter)
5351                 return NULL;
5352         if (!*iter) {
5353                 /* start from the first */
5354                 if (sig->param_count) {
5355                         *iter = &sig->params [0];
5356                         return sig->params [0];
5357                 } else {
5358                         /* no method */
5359                         return NULL;
5360                 }
5361         }
5362         type = *iter;
5363         type++;
5364         if (type < &sig->params [sig->param_count]) {
5365                 *iter = type;
5366                 return *type;
5367         }
5368         return NULL;
5369 }
5370
5371 guint32
5372 mono_signature_get_param_count (MonoMethodSignature *sig)
5373 {
5374         return sig->param_count;
5375 }
5376
5377 guint32
5378 mono_signature_get_call_conv (MonoMethodSignature *sig)
5379 {
5380         return sig->call_convention;
5381 }
5382
5383 int
5384 mono_signature_vararg_start (MonoMethodSignature *sig)
5385 {
5386         return sig->sentinelpos;
5387 }
5388
5389 gboolean
5390 mono_signature_is_instance (MonoMethodSignature *sig)
5391 {
5392         return sig->hasthis;
5393 }
5394
5395 gboolean
5396 mono_signature_explicit_this (MonoMethodSignature *sig)
5397 {
5398         return sig->explicit_this;
5399 }
5400
5401 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
5402 guint
5403 mono_aligned_addr_hash (gconstpointer ptr)
5404 {
5405         return GPOINTER_TO_UINT (ptr) >> 3;
5406 }
5407
5408 /*
5409  * If @field belongs to an inflated generic class, return the corresponding field of the
5410  * generic type definition class.
5411  */
5412 MonoClassField*
5413 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField *field)
5414 {
5415         MonoClass *gtd;
5416         int offset;
5417
5418         if (!field->parent->generic_class)
5419                 return field;
5420
5421         gtd = field->parent->generic_class->container_class;
5422         offset = field - field->parent->fields;
5423         return gtd->fields + offset;
5424 }
5425
5426 /*
5427  * If @event belongs to an inflated generic class, return the corresponding event of the
5428  * generic type definition class.
5429  */
5430 MonoEvent*
5431 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent *event)
5432 {
5433         MonoClass *gtd;
5434         int offset;
5435
5436         if (!event->parent->generic_class)
5437                 return event;
5438
5439         gtd = event->parent->generic_class->container_class;
5440         offset = event - event->parent->ext->events;
5441         return gtd->ext->events + offset;
5442 }
5443
5444 /*
5445  * If @property belongs to an inflated generic class, return the corresponding property of the
5446  * generic type definition class.
5447  */
5448 MonoProperty*
5449 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty *property)
5450 {
5451         MonoClass *gtd;
5452         int offset;
5453
5454         if (!property->parent->generic_class)
5455                 return property;
5456
5457         gtd = property->parent->generic_class->container_class;
5458         offset = property - property->parent->ext->properties;
5459         return gtd->ext->properties + offset;
5460 }
5461