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