57d578a9d86cb3ff1f83a0cdcaa33a1d11f41cb1
[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 /**
760  * mono_metadata_decode_row:
761  * @t: table to extract information from.
762  * @idx: index in table.
763  * @res: array of @res_size cols to store the results in
764  *
765  * This decompresses the metadata element @idx in table @t
766  * into the guint32 @res array that has res_size elements
767  */
768 void
769 mono_metadata_decode_row (metadata_tableinfo_t *t, int idx, guint32 *res, int res_size)
770 {
771         guint32 bitfield = t->size_bitfield;
772         int i, count = meta_table_count (bitfield);
773         char *data = t->base + idx * t->row_size;
774         
775         g_assert (res_size == count);
776         
777         for (i = 0; i < count; i++){
778                 int n = meta_table_size (bitfield, i);
779
780                 switch (n){
781                 case 1:
782                         res [i] = *data; break;
783                 case 2:
784                         res [i] = read16 (data); break;
785                         
786                 case 4:
787                         res [i] = read32 (data); break;
788                         
789                 default:
790                         g_assert_not_reached ();
791                 }
792                 data += n;
793         }
794 }
795
796 /**
797  * mono_metadata_decode_blob_size:
798  * @ptr: pointer to a blob object
799  * @rptr: the new position of the pointer
800  *
801  * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
802  *
803  * Returns: the size of the blob object
804  */
805 guint32
806 mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
807 {
808         const unsigned char *ptr = xptr;
809         guint32 size;
810         
811         if ((*ptr & 0x80) == 0){
812                 size = ptr [0] & 0x7f;
813                 ptr++;
814         } else if ((*ptr & 0x40) == 0){
815                 size = ((ptr [0] & 0x3f) << 8) + ptr [1];
816                 ptr += 2;
817         } else {
818                 size = ((ptr [0] & 0x1f) << 24) +
819                         (ptr [1] << 16) +
820                         (ptr [2] << 8) +
821                         ptr [3];
822                 ptr += 4;
823         }
824         if (rptr)
825                 *rptr = ptr;
826         return size;
827 }
828
829
830 /**
831  * mono_metadata_decode_value:
832  * @ptr: pointer to decode from
833  * @rptr: the new position of the pointer
834  *
835  * This routine decompresses 32-bit values as specified in the "Blob and
836  * Signature" section (22.2)
837  *
838  * Returns: the decoded value
839  */
840 guint32
841 mono_metadata_decode_value (const char *_ptr, const char **rptr)
842 {
843         const unsigned char *ptr = (unsigned char *) _ptr;
844         unsigned char b = *ptr;
845         guint32 len;
846         
847         if ((b & 0x80) == 0){
848                 len = b;
849                 ++ptr;
850         } else if ((b & 0x40) == 0){
851                 len = ((b & 0x3f) << 8 | ptr [1]);
852                 ptr += 2;
853         } else {
854                 len = ((b & 0x1f) << 24) |
855                         (ptr [1] << 16) |
856                         (ptr [2] << 8) |
857                         ptr [3];
858                 ptr += 4;
859         }
860         if (rptr)
861                 *rptr = ptr;
862         
863         return len;
864 }
865
866 guint32
867 mono_metadata_parse_typedef_or_ref (metadata_t *m, const char *ptr, const char **rptr)
868 {
869         guint32 token;
870         guint table;
871         token = mono_metadata_decode_value (ptr, &ptr);
872
873         switch (table & 0x03) {
874         case 0: table = META_TABLE_TYPEDEF; break;
875         case 1: table = META_TABLE_TYPEREF; break;
876         case 2: table = META_TABLE_TYPESPEC; break;
877         default: g_error ("Unhandled encoding for typedef-or-ref coded index");
878         }
879         if (rptr)
880                 *rptr = ptr;
881         return (token >> 2) | table << 24;
882 }
883
884 int
885 mono_metadata_parse_custom_mod (metadata_t *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
886 {
887         MonoCustomMod local;
888         if ((*ptr == ELEMENT_TYPE_CMOD_OPT) ||
889             (*ptr == ELEMENT_TYPE_CMOD_REQD)) {
890                 if (!dest)
891                         dest = &local;
892                 dest->mod = *ptr++;
893                 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
894                 return TRUE;
895         }
896         return FALSE;
897 }
898
899 MonoArray *
900 mono_metadata_parse_array (metadata_t *m, const char *ptr, const char **rptr)
901 {
902         int i;
903         MonoArray *array = g_new0 (MonoArray, 1);
904         
905         array->type = mono_metadata_parse_type (m, ptr, &ptr);
906         array->rank = mono_metadata_decode_value (ptr, &ptr);
907
908         array->numsizes = mono_metadata_decode_value (ptr, &ptr);
909         if (array->numsizes)
910                 array->sizes = g_new0 (int, array->numsizes);
911         for (i = 0; i < array->numsizes; ++i)
912                 array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
913
914         array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
915         if (array->numlobounds)
916                 array->lobounds = g_new0 (int, array->numlobounds);
917         for (i = 0; i < array->numlobounds; ++i)
918                 array->lobounds [i] = mono_metadata_decode_value (ptr, &ptr);
919
920         if (rptr)
921                 *rptr = ptr;
922         return array;
923 }
924
925 void
926 mono_metadata_free_array (MonoArray *array)
927 {
928         mono_metadata_free_type (array->type);
929         g_free (array->sizes);
930         g_free (array->lobounds);
931         g_free (array);
932 }
933
934 MonoParam *
935 mono_metadata_parse_param (metadata_t *m, int rettype, const char *ptr, const char **rptr)
936 {
937         const char *tmp_ptr = ptr;
938         MonoParam *param;
939         int count = 0;
940         int byref = 0;
941
942         /* count the modifiers */
943         while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
944                 count++;
945         param = g_malloc0(sizeof(MonoParam)+(count-MONO_ZERO_LEN_ARRAY)*sizeof(MonoCustomMod));
946         param->num_modifiers = count;
947         /* save them this time */
948         count = 0;
949         while (mono_metadata_parse_custom_mod (m, &(param->modifiers[count]), ptr, &ptr))
950                 count++;
951         switch (*ptr) {
952         case ELEMENT_TYPE_TYPEDBYREF: 
953                 param->typedbyref = 1; 
954                 ptr++; 
955                 break;
956         case ELEMENT_TYPE_VOID: 
957                 if (!rettype)
958                         g_error ("void not allowed in param");
959                 ptr++;
960                 break;
961         case ELEMENT_TYPE_BYREF: 
962                 byref = 1; 
963                 ptr++;
964                 /* follow through */
965         default:
966                 param->type = mono_metadata_parse_type (m, ptr, &ptr);
967                 param->type->byref = byref;
968                 break;
969         }
970         if (rptr)
971                 *rptr = ptr;
972         return param;
973 }
974
975 void
976 mono_metadata_free_param (MonoParam *param)
977 {
978         if (param->type)
979                 mono_metadata_free_type (param->type);
980         g_free (param);
981 }
982
983 MonoMethodSignature *
984 mono_metadata_parse_method_signature (metadata_t *m, int def, const char *ptr, const char **rptr)
985 {
986         MonoMethodSignature *method = g_new0(MonoMethodSignature, 1);
987         int i;
988
989         if (*ptr & 0x20)
990                 method->hasthis = 1;
991         if (*ptr & 0x40)
992                 method->explicit_this = 1;
993         method->call_convention = *ptr & 0x0F;
994         ptr++;
995         method->param_count = mono_metadata_decode_value (ptr, &ptr);
996         method->ret = mono_metadata_parse_param (m, 1, ptr, &ptr);
997
998         method->params = g_new0(MonoParam*, method->param_count);
999         method->sentinelpos = -1;
1000         for (i = 0; i < method->param_count; ++i) {
1001                 if (*ptr == ELEMENT_TYPE_SENTINEL) {
1002                         if (method->call_convention != MONO_CALL_VARARG || def)
1003                                         g_error ("found sentinel for methoddef or no vararg method");
1004                         method->sentinelpos = i;
1005                         ptr++;
1006                 }
1007                 method->params[i] = mono_metadata_parse_param (m, 0, ptr, &ptr);
1008         }
1009         
1010         if (rptr)
1011                 *rptr = ptr;
1012         return method;
1013 }
1014
1015 void
1016 mono_metadata_free_method_signature (MonoMethodSignature *method)
1017 {
1018         int i;
1019         mono_metadata_free_param (method->ret);
1020         for (i = 0; i < method->param_count; ++i)
1021                 mono_metadata_free_param (method->params[i]);
1022
1023         g_free (method->params);
1024         g_free (method);
1025 }
1026
1027 /* 
1028  * do_mono_metadata_parse_type:
1029  * @type: MonoType to be filled in with the return value
1030  * @
1031  * Internal routine used to "fill" the contents of @type from an 
1032  * allocated pointer.  This is done this way to avoid doing too
1033  * many mini-allocations (particularly for the MonoFieldType which
1034  * most of the time is just a MonoType, but sometimes might be augmented).
1035  *
1036  * This routine is used by mono_metadata_parse_type and
1037  * mono_metadata_parse_field_type
1038  *
1039  * This extracts a Type as specified in Partition II (22.2.12) 
1040  */
1041 static void
1042 do_mono_metadata_parse_type (MonoType *type, metadata_t *m, const char *ptr, const char **rptr)
1043 {
1044         type->type = mono_metadata_decode_value (ptr, &ptr);
1045         
1046         switch (type->type){
1047         case ELEMENT_TYPE_BOOLEAN:
1048         case ELEMENT_TYPE_CHAR:
1049         case ELEMENT_TYPE_I1:
1050         case ELEMENT_TYPE_U1:
1051         case ELEMENT_TYPE_I2:
1052         case ELEMENT_TYPE_U2:
1053         case ELEMENT_TYPE_I4:
1054         case ELEMENT_TYPE_U4:
1055         case ELEMENT_TYPE_I8:
1056         case ELEMENT_TYPE_U8:
1057         case ELEMENT_TYPE_R4:
1058         case ELEMENT_TYPE_R8:
1059         case ELEMENT_TYPE_I:
1060         case ELEMENT_TYPE_U:
1061         case ELEMENT_TYPE_STRING:
1062         case ELEMENT_TYPE_OBJECT:
1063                 break;
1064         case ELEMENT_TYPE_VALUETYPE:
1065         case ELEMENT_TYPE_CLASS:
1066                 type->data.token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
1067                 break;
1068         case ELEMENT_TYPE_SZARRAY:
1069         case ELEMENT_TYPE_PTR:
1070                 if (mono_metadata_parse_custom_mod (m, NULL, ptr, NULL)) {
1071                         const char *tmp_ptr = ptr;
1072                         MonoModifiedType *mtype;
1073                         int count = 0;
1074
1075                         type->custom_mod = 1;
1076                         /* count the modifiers */
1077                         while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
1078                                 count++;
1079                         type->data.mtype = mtype = g_malloc0(sizeof(MonoModifiedType)+(count-MONO_ZERO_LEN_ARRAY)*sizeof(MonoCustomMod));
1080                         mtype->num_modifiers = count;
1081                         count = 0;
1082                         
1083                         /* save them this time */
1084                         while (mono_metadata_parse_custom_mod (m, &(mtype->modifiers[count]), ptr, &ptr))
1085                                 count++;
1086                         /* FIXME: mono_metadata_decode_value ... */
1087                         if (*ptr == ELEMENT_TYPE_VOID) {
1088                                 mtype->type = NULL;
1089                                 ptr++;
1090                         } else {
1091                                 mtype->type = mono_metadata_parse_type (m, ptr, &ptr);
1092                         }
1093                 } else {
1094                         /* FIXME: mono_metadata_decode_value ... */
1095                         if (*ptr == ELEMENT_TYPE_VOID) {
1096                                 type->data.type = NULL;
1097                                 ptr++;
1098                         } else {
1099                                 type->data.type = mono_metadata_parse_type (m, ptr, &ptr);
1100                         }
1101                 }
1102                 break;
1103         case ELEMENT_TYPE_FNPTR:
1104                 type->data.method = mono_metadata_parse_method_signature (m, 0, ptr, &ptr);
1105                 break;
1106         case ELEMENT_TYPE_ARRAY:
1107                 type->data.array = mono_metadata_parse_array (m, ptr, &ptr);
1108                 break;
1109         default:
1110                 g_error ("type 0x%02x not handled in mono_metadata_parse_type", type->type);
1111         }
1112         
1113         if (rptr)
1114                 *rptr = ptr;
1115 }
1116
1117 /**
1118  * mono_metadata_parse_type:
1119  * @m: metadata context to scan
1120  * @ptr: pointer to encoded Type stream.
1121  * @rptr: the new position in the stream after parsing the type
1122  *
1123  * Returns: A MonoType structure that has the parsed information
1124  * from the type stored at @ptr in the metadata table @m.
1125  */
1126 MonoType *
1127 mono_metadata_parse_type (metadata_t *m, const char *ptr, const char **rptr)
1128 {
1129         /* should probably be allocated in a memchunk */
1130         MonoType *type = g_new0(MonoType, 1);
1131
1132         do_mono_metadata_parse_type (type, m, ptr, rptr);
1133
1134         return type;
1135 }
1136
1137 void
1138 mono_metadata_free_type (MonoType *type)
1139 {
1140         switch (type->type){
1141         case ELEMENT_TYPE_SZARRAY:
1142         case ELEMENT_TYPE_PTR:
1143                 if (!type->custom_mod) {
1144                         if (type->data.type)
1145                                 mono_metadata_free_type (type->data.type);
1146                 } else if (type->data.mtype) {
1147                         mono_metadata_free_type (type->data.mtype->type);
1148                         g_free (type->data.mtype);
1149                 }
1150                 break;
1151         case ELEMENT_TYPE_FNPTR:
1152                 mono_metadata_free_method_signature (type->data.method);
1153                 break;
1154         case ELEMENT_TYPE_ARRAY:
1155                 mono_metadata_free_array (type->data.array);
1156                 break;
1157         }
1158         g_free (type);
1159 }
1160
1161 static void
1162 hex_dump (const char *buffer, int base, int count)
1163 {
1164         int show_header = 1;
1165         int i;
1166
1167         if (count < 0){
1168                 count = -count;
1169                 show_header = 0;
1170         }
1171         
1172         for (i = 0; i < count; i++){
1173                 if (show_header)
1174                         if ((i % 16) == 0)
1175                                 printf ("\n0x%08x: ", (unsigned char) base + i);
1176
1177                 printf ("%02x ", (unsigned char) (buffer [i]));
1178         }
1179         fflush (stdout);
1180 }
1181
1182 /** 
1183  * @mh: The Method header
1184  * @ptr: Points to the beginning of the Section Data (25.3)
1185  */
1186 static void
1187 parse_section_data (MonoMetaMethodHeader *mh, const unsigned char *ptr)
1188 {
1189         unsigned char sect_data_flags;
1190         const unsigned char *sptr;
1191         int is_fat;
1192         guint32 sect_data_len;
1193         
1194         while (1) {
1195                 /* align on 32-bit boundary */
1196                 /* FIXME: not 64-bit clean code */
1197                 sptr = ptr = dword_align (ptr); 
1198                 sect_data_flags = *ptr;
1199                 ptr++;
1200                 
1201                 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
1202                 if (is_fat) {
1203                         sect_data_len = (ptr [0] << 16) | (ptr [1] << 8) | ptr [0];
1204                         ptr += 3;
1205                 } else {
1206                         sect_data_len = ptr [0];
1207                         ++ptr;
1208                 }
1209                 /*
1210                 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
1211                 hex_dump (sptr, 0, sect_data_len+8);
1212                 g_print ("\nheader: ");
1213                 hex_dump (sptr-4, 0, 4);
1214                 g_print ("\n");
1215                 */
1216                 
1217                 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
1218                         const unsigned char *p = dword_align (ptr);
1219                         int i;
1220                         mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
1221                         /* we could just store a pointer if we don't need to byteswap */
1222                         mh->clauses = g_new0 (MonoExceptionClause, mh->num_clauses);
1223                         for (i = 0; i < mh->num_clauses; ++i) {
1224                                 MonoExceptionClause *ec = &mh->clauses [i];
1225                                 if (is_fat) {
1226                                         /* we could memcpy and byteswap */
1227                                         ec->flags = read32 (p);
1228                                         p += 4;
1229                                         ec->try_offset = read32 (p);
1230                                         p += 4;
1231                                         ec->try_len = read32 (p);
1232                                         p += 4;
1233                                         ec->handler_offset = read32 (p);
1234                                         p += 4;
1235                                         ec->handler_len = read32 (p);
1236                                         p += 4;
1237                                         ec->token_or_filter = read32 (p);
1238                                         p += 4;
1239                                 } else {
1240                                         ec->flags = read16 (p);
1241                                         p += 2;
1242                                         ec->try_offset = read16 (p);
1243                                         p += 2;
1244                                         ec->try_len = *p;
1245                                         ++p;
1246                                         ec->handler_offset = read16 (p);
1247                                         p += 2;
1248                                         ec->handler_len = *p;
1249                                         ++p;
1250                                         ec->token_or_filter = read32 (p);
1251                                         p += 4;
1252                                 }
1253                                 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
1254                         }
1255                 }
1256                 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
1257                         ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
1258                 else
1259                         return;
1260         }
1261 }
1262
1263 MonoMetaMethodHeader *
1264 mono_metadata_parse_mh (metadata_t *m, const char *ptr)
1265 {
1266         MonoMetaMethodHeader *mh;
1267         unsigned char flags = *(unsigned char *) ptr;
1268         unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
1269         guint16 fat_flags;
1270         int hsize;
1271         
1272         g_return_val_if_fail (ptr != NULL, NULL);
1273
1274         mh = g_new0 (MonoMetaMethodHeader, 1);
1275         switch (format){
1276         case METHOD_HEADER_TINY_FORMAT:
1277                 ptr++;
1278                 mh->max_stack = 8;
1279                 mh->local_var_sig_tok = 0;
1280                 mh->code_size = flags >> 2;
1281                 mh->code = ptr;
1282                 break;
1283                 
1284         case METHOD_HEADER_TINY_FORMAT1:
1285                 ptr++;
1286                 mh->max_stack = 8;
1287                 mh->local_var_sig_tok = 0;
1288
1289                 //
1290                 // The spec claims 3 bits, but the Beta2 is
1291                 // incorrect
1292                 //
1293                 mh->code_size = flags >> 2;
1294                 mh->code = ptr;
1295                 break;
1296                 
1297         case METHOD_HEADER_FAT_FORMAT:
1298                 fat_flags = read16 (ptr);
1299                 ptr += 2;
1300                 hsize = (fat_flags >> 12) & 0xf;
1301                 mh->max_stack = *(guint16 *) ptr;
1302                 ptr += 2;
1303                 mh->code_size = *(guint32 *) ptr;
1304                 ptr += 4;
1305                 mh->local_var_sig_tok = *(guint32 *) ptr;
1306                 ptr += 4;
1307
1308                 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
1309                         mh->init_locals = 1;
1310                 else
1311                         mh->init_locals = 0;
1312
1313                 mh->code = ptr;
1314
1315                 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
1316                         break;
1317
1318                 /*
1319                  * There are more sections
1320                  */
1321                 ptr = mh->code + mh->code_size;
1322                 
1323                 parse_section_data (mh, (const unsigned char*)ptr);
1324                 break;
1325                 
1326         default:
1327                 g_free (mh);
1328                 return NULL;
1329         }
1330                        
1331         if (mh->local_var_sig_tok) {
1332                 metadata_tableinfo_t *t = &m->tables [META_TABLE_STANDALONESIG];
1333                 const char *ptr;
1334                 guint32 cols[1];
1335                 int len=0, i, bsize;
1336
1337                 mono_metadata_decode_row (t, (mh->local_var_sig_tok & 0xffffff)-1, cols, 1);
1338                 ptr = mono_metadata_blob_heap (m, cols [0]);
1339                 bsize = mono_metadata_decode_blob_size (ptr, &ptr);
1340                 if (*ptr != 0x07)
1341                         g_warning ("wrong signature for locals blob");
1342                 ptr++;
1343                 len = mono_metadata_decode_value (ptr, &ptr);
1344                 mh->num_locals = len;
1345                 mh->locals = g_new (MonoType*, len);
1346                 for (i = 0; i < len; ++i) {
1347                         int val;
1348                         const char *p = ptr;
1349                         val = mono_metadata_decode_blob_size (ptr, &ptr);
1350                         /* FIXME: store pinned/byref values */
1351                         if (val == ELEMENT_TYPE_PINNED) {
1352                                 p = ptr;
1353                                 val = mono_metadata_decode_blob_size (ptr, &ptr);
1354                         }
1355                         if (val == ELEMENT_TYPE_BYREF) {
1356                                 p = ptr;
1357                         }
1358                         mh->locals [i] = mono_metadata_parse_type (m, p, &ptr);
1359                 }
1360         }
1361         return mh;
1362 }
1363
1364 void
1365 mono_metadata_free_mh (MonoMetaMethodHeader *mh)
1366 {
1367         int i;
1368         for (i = 0; i < mh->num_locals; ++i)
1369                 mono_metadata_free_type (mh->locals[i]);
1370         g_free (mh->locals);
1371         g_free (mh->clauses);
1372         g_free (mh);
1373 }
1374
1375 /**
1376  * mono_metadata_parse_field_type:
1377  * @m: metadata context to extract information from
1378  * @ptr: pointer to the field signature
1379  *
1380  * Parses the field signature, and returns the type information for it. 
1381  *
1382  * Returns: The MonoFieldType that was extracted from @ptr.
1383  */
1384 MonoFieldType *
1385 mono_metadata_parse_field_type (metadata_t *m, const char *ptr, const char **rptr)
1386 {
1387         return mono_metadata_parse_param (m, 0, ptr, rptr);
1388 }
1389
1390 /*
1391  * mono_metadata_token_from_dor:
1392  * @dor_token: A TypeDefOrRef coded index
1393  *
1394  * dor_token is a TypeDefOrRef coded index: it contains either
1395  * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
1396  * bits contain an index into the table.
1397  *
1398  * Returns: an expanded token
1399  */
1400 guint32
1401 mono_metadata_token_from_dor (guint32 dor_index)
1402 {
1403         int table, idx;
1404
1405         table = dor_index & 0x03;
1406         idx = dor_index >> 2;
1407
1408         switch (table){
1409         case 0: /* TypeDef */
1410                 return TOKEN_TYPE_TYPE_DEF | idx;
1411
1412         case 1: /* TypeRef */
1413                 return TOKEN_TYPE_TYPE_REF | idx;
1414
1415         case 2: /* TypeSpec */
1416                 return TOKEN_TYPE_TYPE_SPEC | idx;
1417
1418         default:
1419                 g_assert_not_reached ();
1420         }
1421
1422         return 0;
1423 }
1424
1425 /*
1426  * We use this to pass context information to the typedef locator
1427  */
1428 typedef struct {
1429         int idx;                 /* The index that we are trying to locate */
1430         int col_idx;             /* The index in the row where idx is stored */
1431         metadata_t *m;           /* the metadata context */
1432         metadata_tableinfo_t *t; /* pointer to the typedef table */
1433         guint32 result;
1434 } locator_t;
1435
1436 #define CSIZE(x) (sizeof (x) / 4)
1437
1438 static int
1439 typedef_locator (const void *a, const void *b)
1440 {
1441         locator_t *loc = (locator_t *) a;
1442         char *bb = (char *) b;
1443         int typedef_index = (bb - loc->t->base) / loc->t->row_size;
1444         guint32 cols [6], cols_next [6];
1445
1446         mono_metadata_decode_row (loc->t, typedef_index, cols, CSIZE (cols));
1447
1448         if (loc->idx < cols [loc->col_idx])
1449                 return -1;
1450
1451         /*
1452          * Need to check that the next row is valid.
1453          */
1454         if (typedef_index + 1 < loc->t->rows) {
1455                 mono_metadata_decode_row (loc->t, typedef_index + 1, cols_next, CSIZE (cols_next));
1456                 if (loc->idx >= cols_next [loc->col_idx])
1457                         return 1;
1458
1459                 if (cols [loc->col_idx] == cols_next [loc->col_idx])
1460                         return 1; 
1461         }
1462
1463         loc->result = typedef_index;
1464         
1465         return 0;
1466 }
1467
1468 #define FIELD_INDEX 4
1469 #define METHOD_INDEX 5
1470
1471 guint32
1472 mono_metadata_typedef_from_field (metadata_t *meta, guint32 index)
1473 {
1474         metadata_tableinfo_t *tdef = &meta->tables [META_TABLE_TYPEDEF];
1475         locator_t loc;
1476         
1477         loc.idx = mono_metadata_token_index (index);
1478         loc.col_idx = FIELD_INDEX;
1479         loc.t = tdef;
1480
1481         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1482                 g_assert_not_reached ();
1483
1484         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1485         return loc.result + 1;
1486 }
1487
1488 guint32
1489 mono_metadata_typedef_from_method (metadata_t *meta, guint32 index)
1490 {
1491         metadata_tableinfo_t *tdef = &meta->tables [META_TABLE_TYPEDEF];
1492         locator_t loc;
1493         
1494         loc.idx = mono_metadata_token_index (index);
1495         loc.col_idx = METHOD_INDEX;
1496         loc.t = tdef;
1497
1498         if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1499                 g_assert_not_reached ();
1500
1501         /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1502         return loc.result + 1;
1503 }
1504