Method header parsing
[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 <glib.h>
12 #include "metadata.h"
13 #include "methodheader.h"
14 #include "endian.h"
15
16 /*
17  * Encoding of the "description" argument:
18  *
19  * identifier [CODE ARG]
20  *
21  * If CODE is ':', then a lookup on table ARG is performed
22  * If CODE is '=', then a lookup in the aliased-table ARG is performed
23  * If CODE is '#', then this encodes a flag, ARG is the flag name. 
24  *
25  * Aliased table for example is `CustomAttributeType' which depending on the
26  * information might refer to different tables.
27  */
28
29 static MonoMetaTable AssemblySchema [] = {
30         { MONO_MT_UINT32,     "HashId" },
31         { MONO_MT_UINT16,     "Major" },  
32         { MONO_MT_UINT16,     "Minor" },
33         { MONO_MT_UINT16,     "BuildNumber" },
34         { MONO_MT_UINT16,     "RevisionNumber" },
35         { MONO_MT_UINT32,     "Flags" },
36         { MONO_MT_BLOB_IDX,   "PublicKey" },
37         { MONO_MT_STRING_IDX, "Name" },
38         { MONO_MT_STRING_IDX, "Culture" },
39         { MONO_MT_END, NULL }
40 };
41         
42 static MonoMetaTable AssemblyOSSchema [] = {
43         { MONO_MT_UINT32,     "OSPlatformID" },
44         { MONO_MT_UINT32,     "OSMajor" },
45         { MONO_MT_UINT32,     "OSMinor" },
46         { MONO_MT_END, NULL }
47 };
48
49 static MonoMetaTable AssemblyProcessorSchema [] = {
50         { MONO_MT_UINT32,     "Processor" },
51         { MONO_MT_END, NULL }
52 };
53
54 static MonoMetaTable AssemblyRefSchema [] = {
55         { MONO_MT_UINT16,     "Major" },
56         { MONO_MT_UINT16,     "Minor" },
57         { MONO_MT_UINT16,     "Build" },
58         { MONO_MT_UINT16,     "Revision" },
59         { MONO_MT_UINT32,     "Flags" },
60         { MONO_MT_BLOB_IDX,   "PublicKeyOrToken" },
61         { MONO_MT_STRING_IDX, "Name" },
62         { MONO_MT_STRING_IDX, "Culture" },
63         { MONO_MT_BLOB_IDX,   "HashValue" },
64         { MONO_MT_END, NULL }
65 };
66
67 static MonoMetaTable AssemblyRefOSSchema [] = {
68         { MONO_MT_UINT32,     "OSPlatformID" },
69         { MONO_MT_UINT32,     "OSMajorVersion" },
70         { MONO_MT_UINT32,     "OSMinorVersion" },
71         { MONO_MT_TABLE_IDX,  "AssemblyRef:AssemblyRef" },
72         { MONO_MT_END, NULL }
73 };
74
75 static MonoMetaTable AssemblyRefProcessorSchema [] = {
76         { MONO_MT_UINT32,     "Processor" },
77         { MONO_MT_TABLE_IDX,  "AssemblyRef:AssemblyRef" },
78         { MONO_MT_END, NULL }   
79 };
80
81 static MonoMetaTable ClassLayoutSchema [] = {
82         { MONO_MT_UINT16,     "PackingSize" },
83         { MONO_MT_UINT32,     "ClassSize" },
84         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
85         { MONO_MT_END, NULL }
86 };
87
88 static MonoMetaTable ConstantSchema [] = {
89         { MONO_MT_UINT8,      "Type" },
90         { MONO_MT_UINT8,      "PaddingZero" },
91         { MONO_MT_CONST_IDX,  "Parent" },
92         { MONO_MT_BLOB_IDX,   "Value" },
93         { MONO_MT_END, NULL }
94 };
95
96 static MonoMetaTable CustomAttributeSchema [] = {
97         { MONO_MT_HASCAT_IDX, "Parent" },
98         { MONO_MT_CAT_IDX,    "Type" },
99         { MONO_MT_BLOB_IDX,   "Value" },
100         { MONO_MT_END, NULL }
101 };
102
103 static MonoMetaTable DeclSecuritySchema [] = {
104         { MONO_MT_UINT16,     "Action" },
105         { MONO_MT_HASDEC_IDX, "Parent" },
106         { MONO_MT_BLOB_IDX,   "PermissionSet" },
107         { MONO_MT_END, NULL }   
108 };
109
110 static MonoMetaTable EventMapSchema [] = {
111         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
112         { MONO_MT_TABLE_IDX,  "EventList:Event" },
113         { MONO_MT_END, NULL }   
114 };
115
116 static MonoMetaTable EventSchema [] = {
117         { MONO_MT_UINT16,     "EventFlags#EventAttribute" },
118         { MONO_MT_STRING_IDX, "Name" },
119         { MONO_MT_TABLE_IDX,  "EventType" }, /* TypeDef or TypeRef */
120         { MONO_MT_END, NULL }   
121 };
122
123 static MonoMetaTable ExportedTypeSchema [] = {
124         { MONO_MT_UINT32,     "Flags" },
125         { MONO_MT_TABLE_IDX,  "TypeDefId" },
126         { MONO_MT_STRING_IDX, "TypeName" },
127         { MONO_MT_STRING_IDX, "TypeNameSpace" },
128         { MONO_MT_IMPL_IDX,   "Implementation" },
129         { MONO_MT_END, NULL }   
130 };
131
132 static MonoMetaTable FieldSchema [] = {
133         { MONO_MT_UINT16,     "Flags" },
134         { MONO_MT_STRING_IDX, "Name" },
135         { MONO_MT_BLOB_IDX,   "Signature" },
136         { MONO_MT_END, NULL }   
137 };
138 static MonoMetaTable FieldLayoutSchema [] = {
139         { MONO_MT_UINT32,     "Offset" },
140         { MONO_MT_TABLE_IDX,  "Field:Field" },
141         { MONO_MT_END, NULL }   
142 };
143
144 static MonoMetaTable FieldMarshalSchema [] = {
145         { MONO_MT_HFM_IDX,    "Parent" },
146         { MONO_MT_BLOB_IDX,   "NativeType" },
147         { MONO_MT_END, NULL }   
148 };
149 static MonoMetaTable FieldRVASchema [] = {
150         { MONO_MT_UINT32,     "RVA" },
151         { MONO_MT_TABLE_IDX,  "Field:Field" },
152         { MONO_MT_END, NULL }   
153 };
154
155 static MonoMetaTable FileSchema [] = {
156         { MONO_MT_UINT32,     "Flags" },
157         { MONO_MT_STRING_IDX, "Name" },
158         { MONO_MT_BLOB_IDX,   "Value" }, 
159         { MONO_MT_END, NULL }
160 };
161
162 static MonoMetaTable ImplMapSchema [] = {
163         { MONO_MT_UINT16,     "MappingFlag" },
164         { MONO_MT_MF_IDX,     "MemberForwarded" },
165         { MONO_MT_STRING_IDX, "ImportName" },
166         { MONO_MT_TABLE_IDX,  "ImportScope:ModuleRef" },
167         { MONO_MT_END, NULL }
168 };
169
170 static MonoMetaTable InterfaceImplSchema [] = {
171         { MONO_MT_TABLE_IDX,  "Class:TypeDef" }, 
172         { MONO_MT_TDOR_IDX,  "Interface=TypeDefOrRef" },
173         { MONO_MT_END, NULL }
174 };
175
176 static MonoMetaTable ManifestResourceSchema [] = {
177         { MONO_MT_UINT32,     "Offset" },
178         { MONO_MT_UINT32,     "Flags" },
179         { MONO_MT_STRING_IDX, "Name" },
180         { MONO_MT_IMPL_IDX,   "Implementation" },
181         { MONO_MT_END, NULL }
182 };
183
184 static MonoMetaTable MemberRefSchema [] = {
185         { MONO_MT_MRP_IDX,    "Class" },
186         { MONO_MT_STRING_IDX, "Name" },
187         { MONO_MT_BLOB_IDX,   "Signature" },
188         { MONO_MT_END, NULL }
189 };
190
191 static MonoMetaTable MethodSchema [] = {
192         { MONO_MT_UINT32,     "RVA" },
193         { MONO_MT_UINT16,     "ImplFlags#MethodImplAttributes" },
194         { MONO_MT_UINT16,     "Flags#MethodAttribute" },
195         { MONO_MT_STRING_IDX, "Name" },
196         { MONO_MT_BLOB_IDX,   "Signature" },
197         { MONO_MT_TABLE_IDX,  "ParamList:Param" },
198         { MONO_MT_END, NULL }
199 };
200
201 static MonoMetaTable MethodImplSchema [] = {
202         { MONO_MT_TABLE_IDX,  "Class:TypeDef" },
203         { MONO_MT_MDOR_IDX,   "MethodBody" },
204         { MONO_MT_MDOR_IDX,   "MethodDeclaration" },
205         { MONO_MT_END, NULL }
206 };
207
208 static MonoMetaTable MethodSemanticsSchema [] = {
209         { MONO_MT_UINT16,     "MethodSemantic" },
210         { MONO_MT_TABLE_IDX,  "Method:Method" },
211         { MONO_MT_HS_IDX,     "Association" },
212         { MONO_MT_END, NULL }
213 };
214
215 static MonoMetaTable ModuleSchema [] = {
216         { MONO_MT_UINT16,     "Generation" },
217         { MONO_MT_STRING_IDX, "Name" },
218         { MONO_MT_GUID_IDX,   "MVID" },
219         { MONO_MT_GUID_IDX,   "EncID" },
220         { MONO_MT_GUID_IDX,   "EncBaseID" },
221         { MONO_MT_END, NULL }
222 };
223
224 static MonoMetaTable ModuleRefSchema [] = {
225         { MONO_MT_STRING_IDX, "Name" },
226         { MONO_MT_END, NULL }
227 };
228
229 static MonoMetaTable NestedClassSchema [] = {
230         { MONO_MT_TABLE_IDX,  "NestedClass:TypeDef" },
231         { MONO_MT_TABLE_IDX,  "EnclosingClass:TypeDef" },
232         { MONO_MT_END, NULL }
233 };
234
235 static MonoMetaTable ParamSchema [] = {
236         { MONO_MT_UINT16,     "Flags" },
237         { MONO_MT_UINT16,     "Sequence" },
238         { MONO_MT_STRING_IDX, "Name" },
239         { MONO_MT_END, NULL }   
240 };
241
242 static MonoMetaTable PropertySchema [] = {
243         { MONO_MT_UINT16,     "Flags" },
244         { MONO_MT_STRING_IDX, "Name" },
245         { MONO_MT_BLOB_IDX,   "Type" },
246         { MONO_MT_END, NULL }   
247 };
248
249 static MonoMetaTable PropertyMapSchema [] = {
250         { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
251         { MONO_MT_TABLE_IDX,  "PropertyList:Property" },
252         { MONO_MT_END, NULL }
253 };
254
255 static MonoMetaTable StandaloneSigSchema [] = {
256         { MONO_MT_BLOB_IDX,   "Signature" },
257         { MONO_MT_END, NULL }
258 };
259
260 static MonoMetaTable TypeDefSchema [] = {
261         { MONO_MT_UINT32,     "Flags" },
262         { MONO_MT_STRING_IDX, "Name" },
263         { MONO_MT_STRING_IDX, "Namespace" },
264         { MONO_MT_TDOR_IDX,   "Extends" },
265         { MONO_MT_TABLE_IDX,  "FieldList:Field" },
266         { MONO_MT_TABLE_IDX,  "MethodList:Method" },
267         { MONO_MT_END, NULL }
268 };
269
270 static MonoMetaTable TypeRefSchema [] = {
271         { MONO_MT_RS_IDX,     "ResolutionScope=ResolutionScope" },
272         { MONO_MT_STRING_IDX, "Name" },
273         { MONO_MT_STRING_IDX, "Namespace" },
274         { MONO_MT_END, NULL }
275 };
276
277 static MonoMetaTable TypeSpecSchema [] = {
278         { MONO_MT_BLOB_IDX,   "Signature" },
279         { MONO_MT_END, NULL }
280 };
281
282 static struct {
283         MonoMetaTable *table;
284         const char    *name;
285 } tables [] = {
286         /*  0 */ { ModuleSchema,               "Module" },
287         /*  1 */ { TypeRefSchema,              "TypeRef" },
288         /*  2 */ { TypeDefSchema,              "TypeDef" },
289         /*  3 */ { NULL,                       NULL },
290         /*  4 */ { FieldSchema,                "Field" },
291         /*  5 */ { NULL,                       NULL },
292         /*  6 */ { MethodSchema,               "Method" },
293         /*  7 */ { NULL,                       NULL },
294         /*  8 */ { ParamSchema,                "Param" },
295         /*  9 */ { InterfaceImplSchema,        "InterfaceImpl" },
296         /*  A */ { MemberRefSchema,            "MemberRef" },
297         /*  B */ { ConstantSchema,             "Constant" },
298         /*  C */ { CustomAttributeSchema,      "CustomAttribute" },
299         /*  D */ { FieldMarshalSchema,         "FieldMarshal" },
300         /*  E */ { DeclSecuritySchema,         "DeclSecurity" },
301         /*  F */ { ClassLayoutSchema,          "ClassLayout" },
302         /* 10 */ { FieldLayoutSchema,          "FieldLayout" },
303         /* 11 */ { StandaloneSigSchema,        "StandaloneSig" },
304         /* 12 */ { EventMapSchema,             "EventMap" },
305         /* 13 */ { NULL,                       NULL },
306         /* 14 */ { EventSchema,                "Event" },
307         /* 15 */ { PropertyMapSchema,          "PropertyMap" },
308         /* 16 */ { NULL,                       NULL },
309         /* 17 */ { PropertySchema,             "PropertyTable" },
310         /* 18 */ { MethodSemanticsSchema,      "MethodSemantics" },
311         /* 19 */ { MethodImplSchema,           "MethodImpl" },
312         /* 1A */ { ModuleRefSchema,            "ModuleRef" },
313         /* 1B */ { TypeSpecSchema,             "TypeSpec" },
314         /* 1C */ { ImplMapSchema,              "ImplMap" },
315         /* 1D */ { FieldRVASchema,             "FieldRVA" },
316         /* 1E */ { NULL,                       NULL },
317         /* 1F */ { NULL,                       NULL },
318         /* 20 */ { AssemblySchema,             "Assembly" },
319         /* 21 */ { AssemblyProcessorSchema,    "AssemblyProcessor" },
320         /* 22 */ { AssemblyOSSchema,           "AssemblyOS" },
321         /* 23 */ { AssemblyRefSchema,          "AssemblyRef" },
322         /* 24 */ { AssemblyRefProcessorSchema, "AssemblyRefProcessor" },
323         /* 25 */ { AssemblyRefOSSchema,        "AssemblyRefOS" },
324         /* 26 */ { FileSchema,                 "File" },
325         /* 27 */ { ExportedTypeSchema,         "ExportedType" },
326         /* 28 */ { ManifestResourceSchema,     "ManifestResource" },
327         /* 29 */ { NestedClassSchema,          "NestedClass" },
328         /* 2A */ { NULL,                       NULL },
329         /* 2B */ { NULL,                       NULL },
330 };
331
332 /**
333  * mono_meta_table_name:
334  * @table: table index
335  *
336  * Returns the name for the @table index
337  */
338 const char *
339 mono_meta_table_name (int table)
340 {
341         if ((table < 0) || (table > 0x29))
342                 return "";
343         
344         return tables [table].name;
345 }
346
347 #define rtsize(s,b) (((s) > (1 << (b)) ? 4 : 2))
348                  
349 static int
350 compute_size (metadata_t *meta, MonoMetaTable *table, int rowcount, guint32 *result_bitfield)
351 {
352         guint32 bitfield = 0;
353         int tsize =  rowcount > 65536 ? 4 : 2;
354         int size = 0, field_size;
355         int i, n, code;
356         int shift = 0;
357
358         for (i = 0; (code = table [i].code) != MONO_MT_END; i++){
359                 switch (code){
360                 case MONO_MT_UINT32:
361                         field_size = 4; break;
362                         
363                 case MONO_MT_UINT16:
364                         field_size = 2; break;
365                         
366                 case MONO_MT_UINT8:
367                         field_size = 1; break;
368                         
369                 case MONO_MT_BLOB_IDX:
370                         field_size = meta->idx_blob_wide ? 4 : 2; break;
371                         
372                 case MONO_MT_STRING_IDX:
373                         field_size = meta->idx_string_wide ? 4 : 2; break;
374                         
375                 case MONO_MT_GUID_IDX:
376                         field_size = meta->idx_string_wide ? 4 : 2; break;
377
378                 case MONO_MT_TABLE_IDX:
379                         field_size = tsize; break;
380
381                         /*
382                          * HasConstant: ParamDef, FieldDef, Property
383                          */
384                 case MONO_MT_CONST_IDX:
385                         n = MAX (meta->tables [META_TABLE_PARAM].rows,
386                                  meta->tables [META_TABLE_FIELD].rows);
387                         n = MAX (n, meta->tables [META_TABLE_PROPERTY].rows);
388
389                         /* 2 bits to encode tag */
390                         field_size = rtsize (n, 16-2);
391                         break;
392
393                         /*
394                          * HasCustomAttribute: points to any table but
395                          * itself.
396                          */
397                 case MONO_MT_HASCAT_IDX:
398                         /*
399                          * We believe that since the signature and
400                          * permission are indexing the Blob heap,
401                          * we should consider the blob size first
402                          */
403                         if (meta->idx_blob_wide){
404                                 field_size = 4;
405                                 break;
406                         }
407                         
408                         n = MAX (meta->tables [META_TABLE_METHOD].rows,
409                                  meta->tables [META_TABLE_FIELD].rows);
410                         n = MAX (n, meta->tables [META_TABLE_TYPEREF].rows);
411                         n = MAX (n, meta->tables [META_TABLE_TYPEDEF].rows);
412                         n = MAX (n, meta->tables [META_TABLE_PARAM].rows);
413                         n = MAX (n, meta->tables [META_TABLE_INTERFACEIMPL].rows);
414                         n = MAX (n, meta->tables [META_TABLE_MEMBERREF].rows);
415                         n = MAX (n, meta->tables [META_TABLE_MODULE].rows);
416                         /* Permission seems to be a blob heap pointer */
417                         n = MAX (n, meta->tables [META_TABLE_PROPERTY].rows);
418                         n = MAX (n, meta->tables [META_TABLE_EVENT].rows);
419                         /* Signature seems to be a blob heap pointer */
420                         n = MAX (n, meta->tables [META_TABLE_MODULEREF].rows);
421                         n = MAX (n, meta->tables [META_TABLE_TYPESPEC].rows);
422                         n = MAX (n, meta->tables [META_TABLE_ASSEMBLY].rows);
423                         n = MAX (n, meta->tables [META_TABLE_ASSEMBLYREF].rows);
424                         n = MAX (n, meta->tables [META_TABLE_FILE].rows);
425                         n = MAX (n, meta->tables [META_TABLE_EXPORTEDTYPE].rows);
426                         n = MAX (n, meta->tables [META_TABLE_MANIFESTRESOURCE].rows);
427
428                         /* 5 bits to encode */
429                         field_size = rtsize (n, 16-5);
430                         break;
431
432                         /*
433                          * CustomAttributeType: TypeDef, TypeRef, MethodDef, 
434                          * MemberRef and String.  
435                          */
436                 case MONO_MT_CAT_IDX:
437                         /* String is a heap, if it is wide, we know the size */
438                         if (meta->idx_string_wide){
439                                 field_size = 4;
440                                 break;
441                         }
442                         
443                         n = MAX (meta->tables [META_TABLE_TYPEREF].rows,
444                                  meta->tables [META_TABLE_TYPEDEF].rows);
445                         n = MAX (n, meta->tables [META_TABLE_METHOD].rows);
446                         n = MAX (n, meta->tables [META_TABLE_MEMBERREF].rows);
447
448                         /* 3 bits to encode */
449                         field_size = rtsize (n, 16-3);
450                         break;
451
452                         /*
453                          * HasDeclSecurity: Typedef, MethodDef, Assembly
454                          */
455                 case MONO_MT_HASDEC_IDX:
456                         n = MAX (meta->tables [META_TABLE_TYPEDEF].rows,
457                                  meta->tables [META_TABLE_METHOD].rows);
458                         n = MAX (n, meta->tables [META_TABLE_ASSEMBLY].rows);
459
460                         /* 2 bits to encode */
461                         field_size = rtsize (n, 16-2);
462                         break;
463
464                         /*
465                          * Implementation: File, AssemblyRef, ExportedType
466                          */
467                 case MONO_MT_IMPL_IDX:
468                         n = MAX (meta->tables [META_TABLE_FILE].rows,
469                                  meta->tables [META_TABLE_ASSEMBLYREF].rows);
470                         n = MAX (n, meta->tables [META_TABLE_EXPORTEDTYPE].rows);
471
472                         /* 2 bits to encode tag */
473                         field_size = rtsize (n, 16-2);
474                         break;
475
476                         /*
477                          * HasFieldMarshall: FieldDef, ParamDef
478                          */
479                 case MONO_MT_HFM_IDX:
480                         n = MAX (meta->tables [META_TABLE_FIELD].rows,
481                                  meta->tables [META_TABLE_PARAM].rows);
482
483                         /* 1 bit used to encode tag */
484                         field_size = rtsize (n, 16-1);
485                         break;
486
487                         /*
488                          * MemberForwarded: FieldDef, MethodDef
489                          */
490                 case MONO_MT_MF_IDX:
491                         n = MAX (meta->tables [META_TABLE_FIELD].rows,
492                                  meta->tables [META_TABLE_METHOD].rows);
493
494                         /* 1 bit used to encode tag */
495                         field_size = rtsize (n, 16-1);
496                         break;
497
498                         /*
499                          * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
500                          */
501                 case MONO_MT_TDOR_IDX:
502                         n = MAX (meta->tables [META_TABLE_TYPEDEF].rows,
503                                  meta->tables [META_TABLE_PARAM].rows);
504                         n = MAX (n, meta->tables [META_TABLE_TYPESPEC].rows);
505
506                         /* 2 bits to encode */
507                         field_size = rtsize (n, 16-2);
508                         break;
509
510                         /*
511                          * MemberRefParent: TypeDef, TypeRef, ModuleDef, ModuleRef, TypeSpec
512                          */
513                 case MONO_MT_MRP_IDX:
514                         n = MAX (meta->tables [META_TABLE_TYPEDEF].rows,
515                                  meta->tables [META_TABLE_TYPEREF].rows);
516                         n = MAX (n, meta->tables [META_TABLE_MODULE].rows);
517                         n = MAX (n, meta->tables [META_TABLE_MODULEREF].rows);
518                         n = MAX (n, meta->tables [META_TABLE_TYPESPEC].rows);
519
520                         /* 3 bits to encode */
521                         field_size = rtsize (n, 16 - 3);
522                         break;
523                         
524                 case MONO_MT_MDOR_IDX:
525
526                         /*
527                          * MethodDefOrRef: MethodDef, MemberRef
528                          */
529                 case MONO_MT_HS_IDX:
530                         n = MAX (meta->tables [META_TABLE_METHOD].rows,
531                                  meta->tables [META_TABLE_MEMBERREF].rows);
532
533                         /* 1 bit used to encode tag */
534                         field_size = rtsize (n, 16-1);
535                         break;
536
537                         /*
538                          * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
539                          */
540                 case MONO_MT_RS_IDX:
541                         n = MAX (meta->tables [META_TABLE_MODULE].rows,
542                                  meta->tables [META_TABLE_MODULEREF].rows);
543                         n = MAX (n, meta->tables [META_TABLE_ASSEMBLYREF].rows);
544                         n = MAX (n, meta->tables [META_TABLE_TYPEREF].rows);
545
546                         /* 3 bits used to encode tag */
547                         field_size = rtsize (n, 16 - 3);
548                         break;
549                 }
550
551                 /*
552                  * encode field size as follows (we just need to
553                  * distinguish them).
554                  *
555                  * 4 -> 3
556                  * 2 -> 1
557                  * 1 -> 0
558                  */
559                 bitfield |= (field_size-1) << shift;
560                 shift += 2;
561                 size += field_size;
562         }
563
564         *result_bitfield = (i << 24) | bitfield;
565         return size;
566 }
567
568 /**
569  * mono_metadata_compute_table_bases:
570  * @meta: metadata context to compute table values
571  *
572  * Computes the table bases for the metadata structure.
573  * This is an internal function used by the image loader code.
574  */
575 void
576 mono_metadata_compute_table_bases (metadata_t *meta)
577 {
578         int i;
579         char *base = meta->tables_base;
580         
581         for (i = 0; i < 64; i++){
582                 if (meta->tables [i].rows == 0)
583                         continue;
584
585                 meta->tables [i].row_size = compute_size (
586                         meta, tables [i].table, meta->tables [i].rows,
587                         &meta->tables [i].size_bitfield);
588                 meta->tables [i].base = base;
589                 base += meta->tables [i].rows * meta->tables [i].row_size;
590         }
591 }
592
593 /**
594  * mono_metadata_locate:
595  * @meta: metadata context
596  * @table: table code.
597  * @idx: index of element to retrieve from @table.
598  *
599  * Returns a pointer to the @idx element in the metadata table
600  * whose code is @table.
601  */
602 char *
603 mono_metadata_locate (metadata_t *meta, int table, int idx)
604 {
605         /* idx == 0 refers always to NULL */
606            
607         return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
608 }
609
610 char *
611 mono_metadata_locate_token (metadata_t *meta, guint32 token)
612 {
613         return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
614 }
615
616 /**
617  * mono_metadata_get_table:
618  * @table: table to retrieve
619  *
620  * Returns the MonoMetaTable structure for table @table
621  */
622 MonoMetaTable *
623 mono_metadata_get_table (MetaTableEnum table)
624 {
625         int x = (int) table;
626
627         g_return_val_if_fail ((x > 0) && (x <= META_TABLE_LAST), NULL);
628
629         return tables [table].table;
630 }
631
632 /**
633  * mono_metadata_string_heap:
634  * @meta: metadata context
635  * @index: index into the string heap.
636  *
637  * Returns: an in-memory pointer to the @index in the string heap.
638  */
639 const char *
640 mono_metadata_string_heap (metadata_t *meta, guint32 index)
641 {
642         return meta->raw_metadata + meta->heap_strings.sh_offset + index;
643 }
644
645 /**
646  * mono_metadata_blob_heap:
647  * @meta: metadata context
648  * @index: index into the blob.
649  *
650  * Returns: an in-memory pointer to the @index in the Blob heap.
651  */
652 const char *
653 mono_metadata_blob_heap (metadata_t *meta, guint32 index)
654 {
655         return meta->raw_metadata + meta->heap_blob.sh_offset + index;
656 }
657
658 static const char *
659 dword_align (const char *ptr)
660 {
661         return (const char *) (((guint32) (ptr + 3)) & ~3);
662 }
663       
664 MonoMetaMethodHeader *
665 mono_metadata_parse_mh (const char *ptr)
666 {
667         MonoMetaMethodHeader *mh;
668         unsigned char flags = *(unsigned char *) ptr;
669         unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
670         guint16 fat_flags;
671         unsigned char sect_data_flags;
672         int hsize, sect_data_len;
673         
674         g_return_val_if_fail (ptr != NULL, NULL);
675         g_return_val_if_fail (mh != NULL, NULL);
676
677         mh = g_new0 (MonoMetaMethodHeader, 1);
678         switch (format){
679         case METHOD_HEADER_TINY_FORMAT:
680                 ptr++;
681                 mh->max_stack = 8;
682                 mh->local_var_sig_tok = 0;
683                 mh->code_size = flags >> 2;
684                 mh->code = ptr;
685                 break;
686                 
687         case METHOD_HEADER_TINY_FORMAT1:
688                 ptr++;
689                 mh->max_stack = 8;
690                 mh->local_var_sig_tok = 0;
691                 mh->code_size = flags >> 3;
692                 mh->code = ptr;
693                 break;
694                 
695         case METHOD_HEADER_FAT_FORMAT:
696                 fat_flags = read16 (ptr);
697                 ptr += 2;
698                 hsize = (fat_flags >> 12) & 0xf;
699                 mh->max_stack = *(guint16 *) ptr;
700                 ptr += 2;
701                 mh->code_size = *(guint32 *) ptr;
702                 ptr += 4;
703                 mh->local_var_sig_tok = *(guint32 *) ptr;
704                 ptr += 4;
705
706                 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
707                         mh->init_locals = 1;
708                 else
709                         mh->init_locals = 0;
710
711                 mh->code = ptr;
712
713                 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
714                         return mh;
715
716                 /*
717                  * There are more sections
718                  */
719                 ptr = mh->code + mh->code_size;
720
721                 /* align on 32-bit boundary */
722                 /* FIXME: not 64-bit clean code */
723                 ptr = dword_align (ptr); 
724                 
725                 sect_data_flags = *ptr;
726                 ptr++;
727                 
728                 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS){
729                         g_error ("Can not deal with more sections");
730                 }
731                 
732                 if (sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT){
733                         sect_data_len = (ptr [0] << 16) | (ptr [1] << 8) | ptr [2];
734                         ptr += 3;
735                 } else {
736                         sect_data_len = ptr [0];
737                         ptr++;
738                 }
739                 
740                 if (!(sect_data_flags & METHOD_HEADER_SECTION_EHTABLE))
741                         return mh;
742
743                 ptr = dword_align (ptr);
744                 
745                 break;
746                 
747         default:
748                 return NULL;
749         }
750                        
751         return mh;
752 }
753
754 void
755 mono_metadata_free_mh (MonoMetaMethodHeader *mh)
756 {
757         g_free (mh);
758 }