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