Reorganization
[mono.git] / mono / metadata / metadata.c
1 /*
2  * metadata.c: Routines for accessing the metadata
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #include <stdio.h> 
12 #include <glib.h>
13 #include "metadata.h"
14 #include "tabledefs.h"
15 #include "endian.h"
16 #include "cil-coff.h"
17
18 /*
19  * Encoding of the "description" argument:
20  *
21  * identifier [CODE ARG]
22  *
23  * If CODE is ':', then a lookup on table ARG is performed
24  * If CODE is '=', then a lookup in the aliased-table ARG is performed
25  * If CODE is '#', then this encodes a flag, ARG is the flag name. 
26  *
27  * Aliased table for example is `CustomAttributeType' which depending on the
28  * information might refer to different tables.
29  */
30
31 static MonoMetaTable AssemblySchema [] = {
32         { MONO_MT_UINT32,     "HashId" },
33         { MONO_MT_UINT16,     "Major" },  
34         { MONO_MT_UINT16,     "Minor" },
35         { MONO_MT_UINT16,     "BuildNumber" },
36         { MONO_MT_UINT16,     "RevisionNumber" },
37         { MONO_MT_UINT32,     "Flags" },
38         { MONO_MT_BLOB_IDX,   "PublicKey" },
39         { MONO_MT_STRING_IDX, "Name" },
40         { MONO_MT_STRING_IDX, "Culture" },
41         { MONO_MT_END, NULL }
42 };
43         
44 static MonoMetaTable AssemblyOSSchema [] = {
45         { MONO_MT_UINT32,     "OSPlatformID" },
46         { MONO_MT_UINT32,     "OSMajor" },
47         { MONO_MT_UINT32,     "OSMinor" },
48         { MONO_MT_END, NULL }
49 };
50
51 static MonoMetaTable AssemblyProcessorSchema [] = {
52         { MONO_MT_UINT32,     "Processor" },
53         { MONO_MT_END, NULL }
54 };
55
56 static MonoMetaTable AssemblyRefSchema [] = {
57         { MONO_MT_UINT16,     "Major" },
58         { MONO_MT_UINT16,     "Minor" },
59         { MONO_MT_UINT16,     "Build" },
60         { MONO_MT_UINT16,     "Revision" },
61         { MONO_MT_UINT32,     "Flags" },
62         { MONO_MT_BLOB_IDX,   "PublicKeyOrToken" },
63         { MONO_MT_STRING_IDX, "Name" },
64         { MONO_MT_STRING_IDX, "Culture" },
65         { MONO_MT_BLOB_IDX,   "HashValue" },
66         { MONO_MT_END, NULL }
67 };
68
69 static MonoMetaTable AssemblyRefOSSchema [] = {
70         { MONO_MT_UINT32,     "OSPlatformID" },
71         { MONO_MT_UINT32,     "OSMajorVersion" },
72         { MONO_MT_UINT32,     "OSMinorVersion" },
73         { MONO_MT_TABLE_IDX,  "AssemblyRef:AssemblyRef" },
74         { MONO_MT_END, NULL }
75 };
76
77 static MonoMetaTable AssemblyRefProcessorSchema [] = {
78         { MONO_MT_UINT32,     "Processor" },
79         { MONO_MT_TABLE_IDX,  "AssemblyRef:AssemblyRef" },
80         { MONO_MT_END, NULL }   
81 };
82
83 static MonoMetaTable ClassLayoutSchema [] = {
84         { MONO_MT_UINT16,     "PackingSize" },
85         { MONO_MT_UINT32,     "ClassSize" },
86         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
87         { MONO_MT_END, NULL }
88 };
89
90 static MonoMetaTable ConstantSchema [] = {
91         { MONO_MT_UINT8,      "Type" },
92         { MONO_MT_UINT8,      "PaddingZero" },
93         { MONO_MT_CONST_IDX,  "Parent" },
94         { MONO_MT_BLOB_IDX,   "Value" },
95         { MONO_MT_END, NULL }
96 };
97
98 static MonoMetaTable CustomAttributeSchema [] = {
99         { MONO_MT_HASCAT_IDX, "Parent" },
100         { MONO_MT_CAT_IDX,    "Type" },
101         { MONO_MT_BLOB_IDX,   "Value" },
102         { MONO_MT_END, NULL }
103 };
104
105 static MonoMetaTable DeclSecuritySchema [] = {
106         { MONO_MT_UINT16,     "Action" },
107         { MONO_MT_HASDEC_IDX, "Parent" },
108         { MONO_MT_BLOB_IDX,   "PermissionSet" },
109         { MONO_MT_END, NULL }   
110 };
111
112 static MonoMetaTable EventMapSchema [] = {
113         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
114         { MONO_MT_TABLE_IDX,  "EventList:Event" },
115         { MONO_MT_END, NULL }   
116 };
117
118 static MonoMetaTable EventSchema [] = {
119         { MONO_MT_UINT16,     "EventFlags#EventAttribute" },
120         { MONO_MT_STRING_IDX, "Name" },
121         { MONO_MT_TABLE_IDX,  "EventType" }, /* TypeDef or TypeRef */
122         { MONO_MT_END, NULL }   
123 };
124
125 static MonoMetaTable ExportedTypeSchema [] = {
126         { MONO_MT_UINT32,     "Flags" },
127         { MONO_MT_TABLE_IDX,  "TypeDefId" },
128         { MONO_MT_STRING_IDX, "TypeName" },
129         { MONO_MT_STRING_IDX, "TypeNameSpace" },
130         { MONO_MT_IMPL_IDX,   "Implementation" },
131         { MONO_MT_END, NULL }   
132 };
133
134 static MonoMetaTable FieldSchema [] = {
135         { MONO_MT_UINT16,     "Flags" },
136         { MONO_MT_STRING_IDX, "Name" },
137         { MONO_MT_BLOB_IDX,   "Signature" },
138         { MONO_MT_END, NULL }   
139 };
140 static MonoMetaTable FieldLayoutSchema [] = {
141         { MONO_MT_UINT32,     "Offset" },
142         { MONO_MT_TABLE_IDX,  "Field:Field" },
143         { MONO_MT_END, NULL }   
144 };
145
146 static MonoMetaTable FieldMarshalSchema [] = {
147         { MONO_MT_HFM_IDX,    "Parent" },
148         { MONO_MT_BLOB_IDX,   "NativeType" },
149         { MONO_MT_END, NULL }   
150 };
151 static MonoMetaTable FieldRVASchema [] = {
152         { MONO_MT_UINT32,     "RVA" },
153         { MONO_MT_TABLE_IDX,  "Field:Field" },
154         { MONO_MT_END, NULL }   
155 };
156
157 static MonoMetaTable FileSchema [] = {
158         { MONO_MT_UINT32,     "Flags" },
159         { MONO_MT_STRING_IDX, "Name" },
160         { MONO_MT_BLOB_IDX,   "Value" }, 
161         { MONO_MT_END, NULL }
162 };
163
164 static MonoMetaTable ImplMapSchema [] = {
165         { MONO_MT_UINT16,     "MappingFlag" },
166         { MONO_MT_MF_IDX,     "MemberForwarded" },
167         { MONO_MT_STRING_IDX, "ImportName" },
168         { MONO_MT_TABLE_IDX,  "ImportScope:ModuleRef" },
169         { MONO_MT_END, NULL }
170 };
171
172 static MonoMetaTable InterfaceImplSchema [] = {
173         { MONO_MT_TABLE_IDX,  "Class:TypeDef" }, 
174         { MONO_MT_TDOR_IDX,  "Interface=TypeDefOrRef" },
175         { MONO_MT_END, NULL }
176 };
177
178 static MonoMetaTable ManifestResourceSchema [] = {
179         { MONO_MT_UINT32,     "Offset" },
180         { MONO_MT_UINT32,     "Flags" },
181         { MONO_MT_STRING_IDX, "Name" },
182         { MONO_MT_IMPL_IDX,   "Implementation" },
183         { MONO_MT_END, NULL }
184 };
185
186 static MonoMetaTable MemberRefSchema [] = {
187         { MONO_MT_MRP_IDX,    "Class" },
188         { MONO_MT_STRING_IDX, "Name" },
189         { MONO_MT_BLOB_IDX,   "Signature" },
190         { MONO_MT_END, NULL }
191 };
192
193 static MonoMetaTable MethodSchema [] = {
194         { MONO_MT_UINT32,     "RVA" },
195         { MONO_MT_UINT16,     "ImplFlags#MethodImplAttributes" },
196         { MONO_MT_UINT16,     "Flags#MethodAttribute" },
197         { MONO_MT_STRING_IDX, "Name" },
198         { MONO_MT_BLOB_IDX,   "Signature" },
199         { MONO_MT_TABLE_IDX,  "ParamList:Param" },
200         { MONO_MT_END, NULL }
201 };
202
203 static MonoMetaTable MethodImplSchema [] = {
204         { MONO_MT_TABLE_IDX,  "Class:TypeDef" },
205         { MONO_MT_MDOR_IDX,   "MethodBody" },
206         { MONO_MT_MDOR_IDX,   "MethodDeclaration" },
207         { MONO_MT_END, NULL }
208 };
209
210 static MonoMetaTable MethodSemanticsSchema [] = {
211         { MONO_MT_UINT16,     "MethodSemantic" },
212         { MONO_MT_TABLE_IDX,  "Method:Method" },
213         { MONO_MT_HS_IDX,     "Association" },
214         { MONO_MT_END, NULL }
215 };
216
217 static MonoMetaTable ModuleSchema [] = {
218         { MONO_MT_UINT16,     "Generation" },
219         { MONO_MT_STRING_IDX, "Name" },
220         { MONO_MT_GUID_IDX,   "MVID" },
221         { MONO_MT_GUID_IDX,   "EncID" },
222         { MONO_MT_GUID_IDX,   "EncBaseID" },
223         { MONO_MT_END, NULL }
224 };
225
226 static MonoMetaTable ModuleRefSchema [] = {
227         { MONO_MT_STRING_IDX, "Name" },
228         { MONO_MT_END, NULL }
229 };
230
231 static MonoMetaTable NestedClassSchema [] = {
232         { MONO_MT_TABLE_IDX,  "NestedClass:TypeDef" },
233         { MONO_MT_TABLE_IDX,  "EnclosingClass:TypeDef" },
234         { MONO_MT_END, NULL }
235 };
236
237 static MonoMetaTable ParamSchema [] = {
238         { MONO_MT_UINT16,     "Flags" },
239         { MONO_MT_UINT16,     "Sequence" },
240         { MONO_MT_STRING_IDX, "Name" },
241         { MONO_MT_END, NULL }   
242 };
243
244 static MonoMetaTable PropertySchema [] = {
245         { MONO_MT_UINT16,     "Flags" },
246         { MONO_MT_STRING_IDX, "Name" },
247         { MONO_MT_BLOB_IDX,   "Type" },
248         { MONO_MT_END, NULL }   
249 };
250
251 static MonoMetaTable PropertyMapSchema [] = {
252         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
253         { MONO_MT_TABLE_IDX,  "PropertyList:Property" },
254         { MONO_MT_END, NULL }
255 };
256
257 static MonoMetaTable StandaloneSigSchema [] = {
258         { MONO_MT_BLOB_IDX,   "Signature" },
259         { MONO_MT_END, NULL }
260 };
261
262 static MonoMetaTable TypeDefSchema [] = {
263         { MONO_MT_UINT32,     "Flags" },
264         { MONO_MT_STRING_IDX, "Name" },
265         { MONO_MT_STRING_IDX, "Namespace" },
266         { MONO_MT_TDOR_IDX,   "Extends" },
267         { MONO_MT_TABLE_IDX,  "FieldList:Field" },
268         { MONO_MT_TABLE_IDX,  "MethodList:Method" },
269         { MONO_MT_END, NULL }
270 };
271
272 static MonoMetaTable TypeRefSchema [] = {
273         { MONO_MT_RS_IDX,     "ResolutionScope=ResolutionScope" },
274         { MONO_MT_STRING_IDX, "Name" },
275         { MONO_MT_STRING_IDX, "Namespace" },
276         { MONO_MT_END, NULL }
277 };
278
279 static MonoMetaTable TypeSpecSchema [] = {
280         { MONO_MT_BLOB_IDX,   "Signature" },
281         { MONO_MT_END, NULL }
282 };
283
284 static struct {
285         MonoMetaTable *table;
286         const char    *name;
287 } tables [] = {
288         /*  0 */ { ModuleSchema,               "Module" },
289         /*  1 */ { TypeRefSchema,              "TypeRef" },
290         /*  2 */ { TypeDefSchema,              "TypeDef" },
291         /*  3 */ { NULL,                       NULL },
292         /*  4 */ { FieldSchema,                "Field" },
293         /*  5 */ { NULL,                       NULL },
294         /*  6 */ { MethodSchema,               "Method" },
295         /*  7 */ { NULL,                       NULL },
296         /*  8 */ { ParamSchema,                "Param" },
297         /*  9 */ { InterfaceImplSchema,        "InterfaceImpl" },
298         /*  A */ { MemberRefSchema,            "MemberRef" },
299         /*  B */ { ConstantSchema,             "Constant" },
300         /*  C */ { CustomAttributeSchema,      "CustomAttribute" },
301         /*  D */ { FieldMarshalSchema,         "FieldMarshal" },
302         /*  E */ { DeclSecuritySchema,         "DeclSecurity" },
303         /*  F */ { ClassLayoutSchema,          "ClassLayout" },
304         /* 10 */ { FieldLayoutSchema,          "FieldLayout" },
305         /* 11 */ { StandaloneSigSchema,        "StandaloneSig" },
306         /* 12 */ { EventMapSchema,             "EventMap" },
307         /* 13 */ { NULL,                       NULL },
308         /* 14 */ { EventSchema,                "Event" },
309         /* 15 */ { PropertyMapSchema,          "PropertyMap" },
310         /* 16 */ { NULL,                       NULL },
311         /* 17 */ { PropertySchema,             "PropertyTable" },
312         /* 18 */ { MethodSemanticsSchema,      "MethodSemantics" },
313         /* 19 */ { MethodImplSchema,           "MethodImpl" },
314         /* 1A */ { ModuleRefSchema,            "ModuleRef" },
315         /* 1B */ { TypeSpecSchema,             "TypeSpec" },
316         /* 1C */ { ImplMapSchema,              "ImplMap" },
317         /* 1D */ { FieldRVASchema,             "FieldRVA" },
318         /* 1E */ { NULL,                       NULL },
319         /* 1F */ { NULL,                       NULL },
320         /* 20 */ { AssemblySchema,             "Assembly" },
321         /* 21 */ { AssemblyProcessorSchema,    "AssemblyProcessor" },
322         /* 22 */ { AssemblyOSSchema,           "AssemblyOS" },
323         /* 23 */ { AssemblyRefSchema,          "AssemblyRef" },
324         /* 24 */ { AssemblyRefProcessorSchema, "AssemblyRefProcessor" },
325         /* 25 */ { AssemblyRefOSSchema,        "AssemblyRefOS" },
326         /* 26 */ { FileSchema,                 "File" },
327         /* 27 */ { ExportedTypeSchema,         "ExportedType" },
328         /* 28 */ { ManifestResourceSchema,     "ManifestResource" },
329         /* 29 */ { NestedClassSchema,          "NestedClass" },
330         /* 2A */ { NULL,                       NULL },
331         /* 2B */ { NULL,                       NULL },
332 };
333
334 /**
335  * mono_meta_table_name:
336  * @table: table index
337  *
338  * Returns the name for the @table index
339  */
340 const char *
341 mono_meta_table_name (int table)
342 {
343         if ((table < 0) || (table > 0x29))
344                 return "";
345         
346         return tables [table].name;
347 }
348
349 /* The guy who wrote the spec for this should not be allowed near a
350  * computer again.
351  
352 If  e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1, 
353 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of 
354 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of 
355 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the 
356 inverse of this mapping.
357
358  */
359 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
360 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
361
362 /* Reference: Partition II - 23.2.6 */
363 static int
364 compute_size (metadata_t *meta, MonoMetaTable *table, int tableindex, guint32 *result_bitfield)
365 {
366         guint32 bitfield = 0;
367         int size = 0, field_size;
368         int i, n, code;
369         int shift = 0;
370
371         for (i = 0; (code = table [i].code) != MONO_MT_END; i++){
372                 switch (code){
373                 case MONO_MT_UINT32:
374                         field_size = 4; break;
375                         
376                 case MONO_MT_UINT16:
377                         field_size = 2; break;
378                         
379                 case MONO_MT_UINT8:
380                         field_size = 1; break;
381                         
382                 case MONO_MT_BLOB_IDX:
383                         field_size = meta->idx_blob_wide ? 4 : 2; break;
384                         
385                 case MONO_MT_STRING_IDX:
386                         field_size = meta->idx_string_wide ? 4 : 2; break;
387                         
388                 case MONO_MT_GUID_IDX:
389                         field_size = meta->idx_guid_wide ? 4 : 2; break;
390
391                 case MONO_MT_TABLE_IDX:
392                         /* Uhm, a table index can point to other tables besides the current one
393                          * so, it's not correct to use the rowcount of the current table to
394                          * get the size for this column - lupus 
395                          */
396                         switch (tableindex) {
397                         case META_TABLE_ASSEMBLYREFOS:
398                                 g_assert (i == 3);
399                                 field_size = idx_size (META_TABLE_ASSEMBLYREF); break;
400                         case META_TABLE_ASSEMBLYPROCESSOR:
401                                 g_assert (i == 1);
402                                 field_size = idx_size (META_TABLE_ASSEMBLYREF); break;
403                         case META_TABLE_CLASSLAYOUT:
404                                 g_assert (i == 2);
405                                 field_size = idx_size (META_TABLE_TYPEDEF); break;
406                         case META_TABLE_EVENTMAP:
407                                 g_assert (i == 0 || i == 1);
408                                 field_size = i ? idx_size (META_TABLE_EVENT):
409                                         idx_size(META_TABLE_TYPEDEF); 
410                                 break;
411                         case META_TABLE_EVENT:
412                                 g_assert (i == 2);
413                                 field_size = MAX (idx_size (META_TABLE_TYPEDEF), idx_size(META_TABLE_TYPEREF));
414                                 field_size = MAX (field_size, idx_size(META_TABLE_TYPESPEC));
415                                 break;
416                         case META_TABLE_EXPORTEDTYPE:
417                                 g_assert (i == 1);
418                                 field_size = idx_size (META_TABLE_TYPEDEF); break;
419                         case META_TABLE_FIELDLAYOUT:
420                                 g_assert (i == 1);
421                                 field_size = idx_size (META_TABLE_FIELD); break;
422                         case META_TABLE_FIELDRVA:
423                                 g_assert (i == 1);
424                                 field_size = idx_size (META_TABLE_FIELD); break;
425                         case META_TABLE_IMPLMAP:
426                                 g_assert (i == 3);
427                                 field_size = idx_size (META_TABLE_MODULEREF); break;
428                         case META_TABLE_INTERFACEIMPL:
429                                 g_assert (i == 0);
430                                 field_size = idx_size (META_TABLE_TYPEDEF); break;
431                         case META_TABLE_METHOD:
432                                 g_assert (i == 5);
433                                 field_size = idx_size (META_TABLE_PARAM); break;
434                         case META_TABLE_METHODIMPL:
435                                 g_assert (i == 0);
436                                 field_size = idx_size (META_TABLE_TYPEDEF); break;
437                         case META_TABLE_METHODSEMANTICS:
438                                 g_assert (i == 1);
439                                 field_size = idx_size (META_TABLE_METHOD); break;
440                         case META_TABLE_NESTEDCLASS:
441                                 g_assert (i == 0 || i == 1);
442                                 field_size = idx_size (META_TABLE_TYPEDEF); break;
443                         case META_TABLE_PROPERTYMAP:
444                                 g_assert (i == 0 || i == 1);
445                                 field_size = i ? idx_size (META_TABLE_PROPERTY):
446                                         idx_size(META_TABLE_TYPEDEF); 
447                                 break;
448                         case META_TABLE_TYPEDEF:
449                                 g_assert (i == 4 || i == 5);
450                                 field_size = i == 4 ? idx_size (META_TABLE_FIELD):
451                                         idx_size(META_TABLE_METHOD); 
452                                 break;
453                         default:
454                                 g_assert_not_reached ();
455                         }
456                         if (field_size != idx_size (tableindex))
457                                 g_warning ("size changed (%d to %d)", idx_size (tableindex), field_size);
458                         
459                         break;
460
461                         /*
462                          * HasConstant: ParamDef, FieldDef, Property
463                          */
464                 case MONO_MT_CONST_IDX:
465                         n = MAX (meta->tables [META_TABLE_PARAM].rows,
466                                  meta->tables [META_TABLE_FIELD].rows);
467                         n = MAX (n, meta->tables [META_TABLE_PROPERTY].rows);
468
469                         /* 2 bits to encode tag */
470                         field_size = rtsize (n, 16-2);
471                         break;
472
473                         /*
474                          * HasCustomAttribute: points to any table but
475                          * itself.
476                          */
477                 case MONO_MT_HASCAT_IDX:
478                         /*
479                          * We believe that since the signature and
480                          * permission are indexing the Blob heap,
481                          * we should consider the blob size first
482                          */
483                         /* I'm not a believer - lupus
484                         if (meta->idx_blob_wide){
485                                 field_size = 4;
486                                 break;
487                         }*/
488                         
489                         n = MAX (meta->tables [META_TABLE_METHOD].rows,
490                                  meta->tables [META_TABLE_FIELD].rows);
491                         n = MAX (n, meta->tables [META_TABLE_TYPEREF].rows);
492                         n = MAX (n, meta->tables [META_TABLE_TYPEDEF].rows);
493                         n = MAX (n, meta->tables [META_TABLE_PARAM].rows);
494                         n = MAX (n, meta->tables [META_TABLE_INTERFACEIMPL].rows);
495                         n = MAX (n, meta->tables [META_TABLE_MEMBERREF].rows);
496                         n = MAX (n, meta->tables [META_TABLE_MODULE].rows);
497                         /* Permission seems to be a blob heap pointer */
498                         n = MAX (n, meta->tables [META_TABLE_PROPERTY].rows);
499                         n = MAX (n, meta->tables [META_TABLE_EVENT].rows);
500                         /* Signature seems to be a blob heap pointer */
501                         n = MAX (n, meta->tables [META_TABLE_MODULEREF].rows);
502                         n = MAX (n, meta->tables [META_TABLE_TYPESPEC].rows);
503                         n = MAX (n, meta->tables [META_TABLE_ASSEMBLY].rows);
504                         n = MAX (n, meta->tables [META_TABLE_ASSEMBLYREF].rows);
505                         n = MAX (n, meta->tables [META_TABLE_FILE].rows);
506                         n = MAX (n, meta->tables [META_TABLE_EXPORTEDTYPE].rows);
507                         n = MAX (n, meta->tables [META_TABLE_MANIFESTRESOURCE].rows);
508
509                         /* 5 bits to encode */
510                         field_size = rtsize (n, 16-5);
511                         break;
512
513                         /*
514                          * CustomAttributeType: TypeDef, TypeRef, MethodDef, 
515                          * MemberRef and String.  
516                          */
517                 case MONO_MT_CAT_IDX:
518                         /* String is a heap, if it is wide, we know the size */
519                         /* See above, nope. 
520                         if (meta->idx_string_wide){
521                                 field_size = 4;
522                                 break;
523                         }*/
524                         
525                         n = MAX (meta->tables [META_TABLE_TYPEREF].rows,
526                                  meta->tables [META_TABLE_TYPEDEF].rows);
527                         n = MAX (n, meta->tables [META_TABLE_METHOD].rows);
528                         n = MAX (n, meta->tables [META_TABLE_MEMBERREF].rows);
529
530                         /* 3 bits to encode */
531                         field_size = rtsize (n, 16-3);
532                         break;
533
534                         /*
535                          * HasDeclSecurity: Typedef, MethodDef, Assembly
536                          */
537                 case MONO_MT_HASDEC_IDX:
538                         n = MAX (meta->tables [META_TABLE_TYPEDEF].rows,
539                                  meta->tables [META_TABLE_METHOD].rows);
540                         n = MAX (n, meta->tables [META_TABLE_ASSEMBLY].rows);
541
542                         /* 2 bits to encode */
543                         field_size = rtsize (n, 16-2);
544                         break;
545
546                         /*
547                          * Implementation: File, AssemblyRef, ExportedType
548                          */
549                 case MONO_MT_IMPL_IDX:
550                         n = MAX (meta->tables [META_TABLE_FILE].rows,
551                                  meta->tables [META_TABLE_ASSEMBLYREF].rows);
552                         n = MAX (n, meta->tables [META_TABLE_EXPORTEDTYPE].rows);
553
554                         /* 2 bits to encode tag */
555                         field_size = rtsize (n, 16-2);
556                         break;
557
558                         /*
559                          * HasFieldMarshall: FieldDef, ParamDef
560                          */
561                 case MONO_MT_HFM_IDX:
562                         n = MAX (meta->tables [META_TABLE_FIELD].rows,
563                                  meta->tables [META_TABLE_PARAM].rows);
564
565                         /* 1 bit used to encode tag */
566                         field_size = rtsize (n, 16-1);
567                         break;
568
569                         /*
570                          * MemberForwarded: FieldDef, MethodDef
571                          */
572                 case MONO_MT_MF_IDX:
573                         n = MAX (meta->tables [META_TABLE_FIELD].rows,
574                                  meta->tables [META_TABLE_METHOD].rows);
575
576                         /* 1 bit used to encode tag */
577                         field_size = rtsize (n, 16-1);
578                         break;
579
580                         /*
581                          * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
582                          */
583                 case MONO_MT_TDOR_IDX:
584                         n = MAX (meta->tables [META_TABLE_TYPEDEF].rows,
585                                  meta->tables [META_TABLE_PARAM].rows);
586                         n = MAX (n, meta->tables [META_TABLE_TYPESPEC].rows);
587
588                         /* 2 bits to encode */
589                         field_size = rtsize (n, 16-2);
590                         break;
591
592                         /*
593                          * MemberRefParent: TypeDef, TypeRef, ModuleDef, ModuleRef, TypeSpec
594                          */
595                 case MONO_MT_MRP_IDX:
596                         n = MAX (meta->tables [META_TABLE_TYPEDEF].rows,
597                                  meta->tables [META_TABLE_TYPEREF].rows);
598                         n = MAX (n, meta->tables [META_TABLE_MODULE].rows);
599                         n = MAX (n, meta->tables [META_TABLE_MODULEREF].rows);
600                         n = MAX (n, meta->tables [META_TABLE_TYPESPEC].rows);
601
602                         /* 3 bits to encode */
603                         field_size = rtsize (n, 16 - 3);
604                         break;
605                         
606                 case MONO_MT_MDOR_IDX:
607
608                         /*
609                          * MethodDefOrRef: MethodDef, MemberRef
610                          */
611                 case MONO_MT_HS_IDX:
612                         n = MAX (meta->tables [META_TABLE_METHOD].rows,
613                                  meta->tables [META_TABLE_MEMBERREF].rows);
614
615                         /* 1 bit used to encode tag */
616                         field_size = rtsize (n, 16-1);
617                         break;
618
619                         /*
620                          * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
621                          */
622                 case MONO_MT_RS_IDX:
623                         n = MAX (meta->tables [META_TABLE_MODULE].rows,
624                                  meta->tables [META_TABLE_MODULEREF].rows);
625                         n = MAX (n, meta->tables [META_TABLE_ASSEMBLYREF].rows);
626                         n = MAX (n, meta->tables [META_TABLE_TYPEREF].rows);
627
628                         /* 2 bits used to encode tag (ECMA spec claims 3) */
629                         field_size = rtsize (n, 16 - 2);
630                         break;
631                 }
632
633                 /*
634                  * encode field size as follows (we just need to
635                  * distinguish them).
636                  *
637                  * 4 -> 3
638                  * 2 -> 1
639                  * 1 -> 0
640                  */
641                 bitfield |= (field_size-1) << shift;
642                 shift += 2;
643                 size += field_size;
644                 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
645         }
646
647         *result_bitfield = (i << 24) | bitfield;
648         return size;
649 }
650
651 /**
652  * mono_metadata_compute_table_bases:
653  * @meta: metadata context to compute table values
654  *
655  * Computes the table bases for the metadata structure.
656  * This is an internal function used by the image loader code.
657  */
658 void
659 mono_metadata_compute_table_bases (metadata_t *meta)
660 {
661         int i;
662         char *base = meta->tables_base;
663         
664         for (i = 0; i < 64; i++){
665                 if (meta->tables [i].rows == 0)
666                         continue;
667
668                 meta->tables [i].row_size = compute_size (
669                         meta, tables [i].table, i,
670                         &meta->tables [i].size_bitfield);
671                 meta->tables [i].base = base;
672                 base += meta->tables [i].rows * meta->tables [i].row_size;
673         }
674 }
675
676 /**
677  * mono_metadata_locate:
678  * @meta: metadata context
679  * @table: table code.
680  * @idx: index of element to retrieve from @table.
681  *
682  * Returns a pointer to the @idx element in the metadata table
683  * whose code is @table.
684  */
685 char *
686 mono_metadata_locate (metadata_t *meta, int table, int idx)
687 {
688         /* idx == 0 refers always to NULL */
689         g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, "");
690            
691         return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
692 }
693
694 char *
695 mono_metadata_locate_token (metadata_t *meta, guint32 token)
696 {
697         return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
698 }
699
700 /**
701  * mono_metadata_get_table:
702  * @table: table to retrieve
703  *
704  * Returns the MonoMetaTable structure for table @table
705  */
706 MonoMetaTable *
707 mono_metadata_get_table (MetaTableEnum table)
708 {
709         int x = (int) table;
710
711         g_return_val_if_fail ((x > 0) && (x <= META_TABLE_LAST), NULL);
712
713         return tables [table].table;
714 }
715
716 /**
717  * mono_metadata_string_heap:
718  * @meta: metadata context
719  * @index: index into the string heap.
720  *
721  * Returns: an in-memory pointer to the @index in the string heap.
722  */
723 const char *
724 mono_metadata_string_heap (metadata_t *meta, guint32 index)
725 {
726         g_return_val_if_fail (index < meta->heap_strings.sh_size, "");
727         return meta->raw_metadata + meta->heap_strings.sh_offset + index;
728 }
729
730 const char *
731 mono_metadata_user_string (metadata_t *meta, guint32 index)
732 {
733         g_return_val_if_fail (index < meta->heap_us.sh_size, "");
734         return meta->raw_metadata + meta->heap_us.sh_offset + index;
735 }
736
737 /**
738  * mono_metadata_blob_heap:
739  * @meta: metadata context
740  * @index: index into the blob.
741  *
742  * Returns: an in-memory pointer to the @index in the Blob heap.
743  */
744 const char *
745 mono_metadata_blob_heap (metadata_t *meta, guint32 index)
746 {
747         g_return_val_if_fail (index < meta->heap_blob.sh_size, "");
748         return meta->raw_metadata + meta->heap_blob.sh_offset + index;
749 }
750
751 static const char *
752 dword_align (const char *ptr)
753 {
754         return (const char *) (((guint32) (ptr + 3)) & ~3);
755 }
756
757 static MonoMetaExceptionHandler *
758 parse_exception_handler (const char *ptr, gboolean is_fat)
759 {
760         MonoMetaExceptionHandler *eh = g_new0 (MonoMetaExceptionHandler, 1);
761         int size;
762         
763         eh->kind = (MonoMetaExceptionEnum) *ptr;
764         ptr++;
765         if (is_fat)
766                 size = (ptr [0] << 16) | (ptr [1] << 8) | ptr [2];
767         else
768                 size = (unsigned char) ptr [0];
769
770         /*
771          * It must be aligned
772          */
773         ptr += 4;
774         g_assert ((((guint32) ptr) & 3) == 0);
775
776         if (is_fat){
777                 printf ("Records: %d (%d)\n", size / 12, size);
778                 
779         } else {
780                 printf ("Records: %d (%d)\n", size / 12, size);
781         
782         }
783
784         return eh;
785 }
786
787 /**
788  * mono_metadata_decode_row:
789  * @t: table to extract information from.
790  * @idx: index in table.
791  * @res: array of @res_size cols to store the results in
792  *
793  * This decompresses the metadata element @idx in table @t
794  * into the guint32 @res array that has res_size elements
795  */
796 void
797 mono_metadata_decode_row (metadata_tableinfo_t *t, int idx, guint32 *res, int res_size)
798 {
799         guint32 bitfield = t->size_bitfield;
800         int i, count = meta_table_count (bitfield);
801         char *data = t->base + idx * t->row_size;
802         
803         g_assert (res_size == count);
804         
805         for (i = 0; i < count; i++){
806                 int n = meta_table_size (bitfield, i);
807
808                 switch (n){
809                 case 1:
810                         res [i] = *data; break;
811                 case 2:
812                         res [i] = read16 (data); break;
813                         
814                 case 4:
815                         res [i] = read32 (data); break;
816                         
817                 default:
818                         g_assert_not_reached ();
819                 }
820                 data += n;
821         }
822 }
823
824 /**
825  * mono_metadata_decode_blob_size:
826  * @ptr: pointer to a blob object
827  * @size: where we return the size of the object
828  *
829  * This decodes a compressed size as described by 23.1.4
830  *
831  * Returns: the position to start decoding a blob or user string object
832  * from. 
833  */
834 const char *
835 mono_metadata_decode_blob_size (const char *xptr, int *size)
836 {
837         const unsigned char *ptr = xptr;
838         
839         if ((*ptr & 0x80) == 0){
840                 *size = ptr [0] & 0x7f;
841                 ptr++;
842         } else if ((*ptr & 0x40) == 0){
843                 *size = ((ptr [0] & 0x3f) << 8) + ptr [1];
844                 ptr += 2;
845         } else {
846                 *size = ((ptr [0] & 0x1f) << 24) +
847                         (ptr [1] << 16) +
848                         (ptr [2] << 8) +
849                         ptr [3];
850                 ptr += 4;
851         }
852
853         return (char *) ptr;
854 }
855
856
857 /**
858  * mono_metadata_decode_value:
859  * @ptr: pointer to decode from
860  * @len: result value is stored here.
861  *
862  * This routine decompresses 32-bit values as specified in the "Blob and
863  * Signature" section (22.2)
864  *
865  * Returns: updated pointer location
866  */
867 const char *
868 mono_metadata_decode_value (const char *_ptr, guint32 *len)
869 {
870         const unsigned char *ptr = (unsigned char *) _ptr;
871         unsigned char b = *ptr;
872         
873         if ((b & 0x80) == 0){
874                 *len = b;
875                 return ptr+1;
876         } else if ((b & 0x40) == 0){
877                 *len = ((b & 0x3f) << 8 | ptr [1]);
878                 return ptr + 2;
879         }
880         *len = ((b & 0x1f) << 24) |
881                 (ptr [1] << 16) |
882                 (ptr [2] << 8) |
883                 ptr [3];
884         
885         return ptr + 4;
886 }
887
888 guint32
889 mono_metadata_parse_typedef_or_ref (metadata_t *m, const char *ptr, const char **rptr)
890 {
891         guint32 token;
892         guint table;
893         ptr = mono_metadata_decode_value (ptr, &token);
894
895         switch (table & 0x03) {
896         case 0: table = META_TABLE_TYPEDEF; break;
897         case 1: table = META_TABLE_TYPEREF; break;
898         case 2: table = META_TABLE_TYPESPEC; break;
899         default: g_error ("Unhandled encoding for typedef-or-ref coded index");
900         }
901         if (rptr)
902                 *rptr = ptr;
903         return (token >> 2) | table << 24;
904 }
905
906 int
907 mono_metadata_parse_custom_mod (metadata_t *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
908 {
909         MonoCustomMod local;
910         if ((*ptr == ELEMENT_TYPE_CMOD_OPT) ||
911             (*ptr == ELEMENT_TYPE_CMOD_REQD)) {
912                 if (!dest)
913                         dest = &local;
914                 dest->mod = *ptr++;
915                 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
916                 return TRUE;
917         }
918         return FALSE;
919 }
920
921 MonoArray *
922 mono_metadata_parse_array (metadata_t *m, const char *ptr, const char **rptr)
923 {
924         int i;
925         MonoArray *array = g_new0(MonoArray, 1);
926         
927         array->type = mono_metadata_parse_type (m, ptr, &ptr);
928         ptr = mono_metadata_decode_value (ptr, &array->rank);
929
930         ptr = mono_metadata_decode_value (ptr, &array->numsizes);
931         if (array->numsizes)
932                 array->sizes = g_new0(int, array->numsizes);
933         for (i = 0; i < array->numsizes; ++i)
934                 ptr = mono_metadata_decode_value (ptr, &(array->sizes[i]));
935
936         ptr = mono_metadata_decode_value (ptr, &array->numlobounds);
937         if (array->numlobounds)
938                 array->lobounds = g_new0(int, array->numlobounds);
939         for (i = 0; i < array->numlobounds; ++i)
940                 ptr = mono_metadata_decode_value (ptr, &(array->lobounds[i]));
941
942         if (rptr)
943                 *rptr = ptr;
944         return array;
945 }
946
947 void
948 mono_metadata_free_array (MonoArray *array)
949 {
950         mono_metadata_free_type (array->type);
951         g_free (array->sizes);
952         g_free (array->lobounds);
953         g_free (array);
954 }
955
956 MonoParam *
957 mono_metadata_parse_param (metadata_t *m, int rettype, const char *ptr, const char **rptr)
958 {
959         const char *tmp_ptr = ptr;
960         MonoParam *param;
961         int count = 0;
962         int byref = 0;
963
964         /* count the modifiers */
965         while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
966                 count++;
967         param = g_malloc0(sizeof(MonoParam)+(count-1)*sizeof(MonoCustomMod));
968         param->num_modifiers = count;
969         /* save them this time */
970         count = 0;
971         while (mono_metadata_parse_custom_mod (m, &(param->modifiers[count]), ptr, &ptr))
972                 count++;
973         switch (*ptr) {
974         case ELEMENT_TYPE_TYPEDBYREF: 
975                 param->typedbyref = 1; 
976                 ptr++; 
977                 break;
978         case ELEMENT_TYPE_VOID: 
979                 if (!rettype)
980                         g_error ("void not allowed in param");
981                 ptr++;
982                 break;
983         case ELEMENT_TYPE_BYREF: 
984                 byref = 1; 
985                 ptr++;
986                 /* follow through */
987         default:
988                 param->type = mono_metadata_parse_type (m, ptr, &ptr);
989                 param->type->byref = byref;
990                 break;
991         }
992         if (rptr)
993                 *rptr = ptr;
994         return param;
995 }
996
997 void
998 mono_metadata_free_param (MonoParam *param)
999 {
1000         if (param->type)
1001                 mono_metadata_free_type (param->type);
1002         g_free (param);
1003 }
1004
1005 MonoMethodSignature *
1006 mono_metadata_parse_method_signature (metadata_t *m, int def, const char *ptr, const char **rptr)
1007 {
1008         MonoMethodSignature *method = g_new0(MonoMethodSignature, 1);
1009         int i;
1010
1011         if (*ptr & 0x20)
1012                 method->hasthis = 1;
1013         if (*ptr & 0x40)
1014                 method->explicit_this = 1;
1015         method->call_convention = *ptr & 0x0F;
1016         ptr++;
1017         ptr = mono_metadata_decode_value (ptr, &method->param_count);
1018         method->ret = mono_metadata_parse_param (m, 1, ptr, &ptr);
1019
1020         method->params = g_new0(MonoParam*, method->param_count);
1021         method->sentinelpos = -1;
1022         for (i = 0; i < method->param_count; ++i) {
1023                 if (*ptr == ELEMENT_TYPE_SENTINEL) {
1024                         if (method->call_convention != MONO_CALL_VARARG || def)
1025                                         g_error ("found sentinel for methoddef or no vararg method");
1026                         method->sentinelpos = i;
1027                         ptr++;
1028                 }
1029                 method->params[i] = mono_metadata_parse_param (m, 0, ptr, &ptr);
1030         }
1031         
1032         if (rptr)
1033                 *rptr = ptr;
1034         return method;
1035 }
1036
1037 void
1038 mono_metadata_free_method_signature (MonoMethodSignature *method)
1039 {
1040         int i;
1041         mono_metadata_free_param (method->ret);
1042         for (i = 0; i < method->param_count; ++i)
1043                 mono_metadata_free_param (method->params[i]);
1044
1045         g_free (method->params);
1046         g_free (method);
1047 }
1048
1049 /* II 22.2.12 */
1050 MonoType *
1051 mono_metadata_parse_type (metadata_t *m, const char *ptr, const char **rptr)
1052 {
1053         /* should probably be allocated in a memchunk */
1054         MonoType *type = g_new0(MonoType, 1);
1055         int val;
1056         
1057         ptr = mono_metadata_decode_value (ptr, &val);
1058         type->type = val;
1059         
1060         switch (type->type){
1061         case ELEMENT_TYPE_BOOLEAN:
1062         case ELEMENT_TYPE_CHAR:
1063         case ELEMENT_TYPE_I1:
1064         case ELEMENT_TYPE_U1:
1065         case ELEMENT_TYPE_I2:
1066         case ELEMENT_TYPE_U2:
1067         case ELEMENT_TYPE_I4:
1068         case ELEMENT_TYPE_U4:
1069         case ELEMENT_TYPE_I8:
1070         case ELEMENT_TYPE_U8:
1071         case ELEMENT_TYPE_R4:
1072         case ELEMENT_TYPE_R8:
1073         case ELEMENT_TYPE_I:
1074         case ELEMENT_TYPE_U:
1075         case ELEMENT_TYPE_STRING:
1076         case ELEMENT_TYPE_OBJECT:
1077                 break;
1078         case ELEMENT_TYPE_VALUETYPE:
1079         case ELEMENT_TYPE_CLASS:
1080                 type->data.token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
1081                 break;
1082         case ELEMENT_TYPE_SZARRAY:
1083         case ELEMENT_TYPE_PTR:
1084                 if (mono_metadata_parse_custom_mod (m, NULL, ptr, NULL)) {
1085                         const char *tmp_ptr = ptr;
1086                         MonoModifiedType *mtype;
1087                         int count = 0;
1088
1089                         type->custom_mod = 1;
1090                         /* count the modifiers */
1091                         while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
1092                                 count++;
1093                         type->data.mtype = mtype = g_malloc0(sizeof(MonoModifiedType)+(count-1)*sizeof(MonoCustomMod));
1094                         mtype->num_modifiers = count;
1095                         count = 0;
1096                         /* save them this time */
1097                         while (mono_metadata_parse_custom_mod (m, &(mtype->modifiers[count]), ptr, &ptr))
1098                                 count++;
1099                         /* FIXME: mono_metadata_decode_value ... */
1100                         if (*ptr == ELEMENT_TYPE_VOID) {
1101                                 mtype->type = NULL;
1102                                 ptr++;
1103                         } else {
1104                                 mtype->type = mono_metadata_parse_type (m, ptr, &ptr);
1105                         }
1106                 } else {
1107                         /* FIXME: mono_metadata_decode_value ... */
1108                         if (*ptr == ELEMENT_TYPE_VOID) {
1109                                 type->data.type = NULL;
1110                                 ptr++;
1111                         } else {
1112                                 type->data.type = mono_metadata_parse_type (m, ptr, &ptr);
1113                         }
1114                 }
1115                 break;
1116         case ELEMENT_TYPE_FNPTR:
1117                 type->data.method = mono_metadata_parse_method_signature (m, 0, ptr, &ptr);
1118                 break;
1119         case ELEMENT_TYPE_ARRAY:
1120                 type->data.array = mono_metadata_parse_array (m, ptr, &ptr);
1121                 break;
1122         default:
1123                 g_error ("type 0x%02x not handled in mono_metadata_parse_type", type->type);
1124         }
1125         
1126         if (rptr)
1127                 *rptr = ptr;
1128         return type;
1129 }
1130
1131 void
1132 mono_metadata_free_type (MonoType *type)
1133 {
1134         switch (type->type){
1135         case ELEMENT_TYPE_SZARRAY:
1136         case ELEMENT_TYPE_PTR:
1137                 if (!type->custom_mod)
1138                         mono_metadata_free_type (type->data.type);
1139                 else {
1140                         mono_metadata_free_type (type->data.mtype->type);
1141                         g_free (type->data.mtype);
1142                 }
1143                 break;
1144         case ELEMENT_TYPE_FNPTR:
1145                 mono_metadata_free_method_signature (type->data.method);
1146                 break;
1147         case ELEMENT_TYPE_ARRAY:
1148                 mono_metadata_free_array (type->data.array);
1149                 break;
1150         }
1151         g_free (type);
1152 }
1153
1154 /** 
1155  * @mh: The Method header
1156  * @ptr: Points to the beginning of the Section Data (25.3)
1157  */
1158 static void
1159 parse_section_data (MonoMetaMethodHeader *mh, const char *ptr)
1160 {
1161 #if 0
1162         while ((*ptr) &  METHOD_HEADER_SECTION_MORE_SECTS){
1163                 /* align on 32-bit boundary */
1164                 /* FIXME: not 64-bit clean code */
1165                 ptr = dword_align (ptr); 
1166                 
1167                 sect_data_flags = *ptr;
1168                 ptr++;
1169                 
1170                 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS){
1171                         g_error ("Can not deal with more sections");
1172                 }
1173                 
1174                 if (sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT){
1175                         sect_data_len = 
1176                                 } else {
1177                                         sect_data_len = ptr [0];
1178                                         ptr++;
1179                                 }
1180                 
1181                 if (!(sect_data_flags & METHOD_HEADER_SECTION_EHTABLE))
1182                         return mh;
1183                 
1184                 ptr = dword_align (ptr);
1185         }
1186 #endif
1187 }
1188
1189 MonoMetaMethodHeader *
1190 mono_metadata_parse_mh (metadata_t *m, const char *ptr)
1191 {
1192         MonoMetaMethodHeader *mh;
1193         unsigned char flags = *(unsigned char *) ptr;
1194         unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
1195         guint16 fat_flags;
1196         int hsize;
1197         
1198         g_return_val_if_fail (ptr != NULL, NULL);
1199
1200         mh = g_new0 (MonoMetaMethodHeader, 1);
1201         switch (format){
1202         case METHOD_HEADER_TINY_FORMAT:
1203                 ptr++;
1204                 mh->max_stack = 8;
1205                 mh->local_var_sig_tok = 0;
1206                 mh->code_size = flags >> 2;
1207                 mh->code = ptr;
1208                 break;
1209                 
1210         case METHOD_HEADER_TINY_FORMAT1:
1211                 ptr++;
1212                 mh->max_stack = 8;
1213                 mh->local_var_sig_tok = 0;
1214
1215                 //
1216                 // The spec claims 3 bits, but the Beta2 is
1217                 // incorrect
1218                 //
1219                 mh->code_size = flags >> 2;
1220                 mh->code = ptr;
1221                 break;
1222                 
1223         case METHOD_HEADER_FAT_FORMAT:
1224                 fat_flags = read16 (ptr);
1225                 ptr += 2;
1226                 hsize = (fat_flags >> 12) & 0xf;
1227                 mh->max_stack = *(guint16 *) ptr;
1228                 ptr += 2;
1229                 mh->code_size = *(guint32 *) ptr;
1230                 ptr += 4;
1231                 mh->local_var_sig_tok = *(guint32 *) ptr;
1232                 ptr += 4;
1233
1234                 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
1235                         mh->init_locals = 1;
1236                 else
1237                         mh->init_locals = 0;
1238
1239                 mh->code = ptr;
1240
1241                 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
1242                         break;
1243
1244                 /*
1245                  * There are more sections
1246                  */
1247                 ptr = mh->code + mh->code_size;
1248                 
1249                 parse_section_data (mh, ptr);
1250                 break;
1251                 
1252         default:
1253                 g_free (mh);
1254                 return NULL;
1255         }
1256                        
1257         if (mh->local_var_sig_tok) {
1258                 metadata_tableinfo_t *t = &m->tables [META_TABLE_STANDALONESIG];
1259                 const char *ptr;
1260                 guint32 cols[1];
1261                 int len=0, i, bsize;
1262
1263                 mono_metadata_decode_row (t, (mh->local_var_sig_tok & 0xffffff)-1, cols, 1);
1264                 ptr = mono_metadata_blob_heap (m, cols [0]);
1265                 ptr = mono_metadata_decode_blob_size (ptr, &bsize);
1266                 if (*ptr != 0x07)
1267                         g_warning ("wrong signature for locals blob");
1268                 ptr++;
1269                 ptr = mono_metadata_decode_value (ptr, &len);
1270                 mh->num_locals = len;
1271                 mh->locals = g_new (MonoType*, len);
1272                 for (i = 0; i < len; ++i) {
1273                         int val;
1274                         const char *p = ptr;
1275                         ptr = mono_metadata_decode_blob_size (ptr, &val);
1276                         /* FIXME: store pinned/byref values */
1277                         if (val == ELEMENT_TYPE_PINNED) {
1278                                 p = ptr;
1279                                 ptr = mono_metadata_decode_blob_size (ptr, &val);
1280                         }
1281                         if (val == ELEMENT_TYPE_BYREF) {
1282                                 p = ptr;
1283                         }
1284                         mh->locals [i] = mono_metadata_parse_type (m, p, &ptr);
1285                 }
1286         }
1287         return mh;
1288 }
1289
1290 void
1291 mono_metadata_free_mh (MonoMetaMethodHeader *mh)
1292 {
1293         int i;
1294         for (i = 0; i < mh->num_locals; ++i)
1295                 mono_metadata_free_type (mh->locals[i]);
1296         g_free (mh->locals);
1297         g_free (mh);
1298 }
1299