2 * metadata.c: Routines for accessing the metadata
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
14 #include "tabledefs.h"
19 * Encoding of the "description" argument:
21 * identifier [CODE ARG]
23 * If CODE is ':', then a lookup on table ARG is performed
24 * If CODE is '=', then a lookup in the aliased-table ARG is performed
25 * If CODE is '#', then this encodes a flag, ARG is the flag name.
27 * Aliased table for example is `CustomAttributeType' which depending on the
28 * information might refer to different tables.
31 static MonoMetaTable AssemblySchema [] = {
32 { MONO_MT_UINT32, "HashId" },
33 { MONO_MT_UINT16, "Major" },
34 { MONO_MT_UINT16, "Minor" },
35 { MONO_MT_UINT16, "BuildNumber" },
36 { MONO_MT_UINT16, "RevisionNumber" },
37 { MONO_MT_UINT32, "Flags" },
38 { MONO_MT_BLOB_IDX, "PublicKey" },
39 { MONO_MT_STRING_IDX, "Name" },
40 { MONO_MT_STRING_IDX, "Culture" },
44 static MonoMetaTable AssemblyOSSchema [] = {
45 { MONO_MT_UINT32, "OSPlatformID" },
46 { MONO_MT_UINT32, "OSMajor" },
47 { MONO_MT_UINT32, "OSMinor" },
51 static MonoMetaTable AssemblyProcessorSchema [] = {
52 { MONO_MT_UINT32, "Processor" },
56 static MonoMetaTable AssemblyRefSchema [] = {
57 { MONO_MT_UINT16, "Major" },
58 { MONO_MT_UINT16, "Minor" },
59 { MONO_MT_UINT16, "Build" },
60 { MONO_MT_UINT16, "Revision" },
61 { MONO_MT_UINT32, "Flags" },
62 { MONO_MT_BLOB_IDX, "PublicKeyOrToken" },
63 { MONO_MT_STRING_IDX, "Name" },
64 { MONO_MT_STRING_IDX, "Culture" },
65 { MONO_MT_BLOB_IDX, "HashValue" },
69 static MonoMetaTable AssemblyRefOSSchema [] = {
70 { MONO_MT_UINT32, "OSPlatformID" },
71 { MONO_MT_UINT32, "OSMajorVersion" },
72 { MONO_MT_UINT32, "OSMinorVersion" },
73 { MONO_MT_TABLE_IDX, "AssemblyRef:AssemblyRef" },
77 static MonoMetaTable AssemblyRefProcessorSchema [] = {
78 { MONO_MT_UINT32, "Processor" },
79 { MONO_MT_TABLE_IDX, "AssemblyRef:AssemblyRef" },
83 static MonoMetaTable ClassLayoutSchema [] = {
84 { MONO_MT_UINT16, "PackingSize" },
85 { MONO_MT_UINT32, "ClassSize" },
86 { MONO_MT_TABLE_IDX, "Parent:TypeDef" },
90 static MonoMetaTable ConstantSchema [] = {
91 { MONO_MT_UINT8, "Type" },
92 { MONO_MT_UINT8, "PaddingZero" },
93 { MONO_MT_CONST_IDX, "Parent" },
94 { MONO_MT_BLOB_IDX, "Value" },
98 static MonoMetaTable CustomAttributeSchema [] = {
99 { MONO_MT_HASCAT_IDX, "Parent" },
100 { MONO_MT_CAT_IDX, "Type" },
101 { MONO_MT_BLOB_IDX, "Value" },
102 { MONO_MT_END, NULL }
105 static MonoMetaTable DeclSecuritySchema [] = {
106 { MONO_MT_UINT16, "Action" },
107 { MONO_MT_HASDEC_IDX, "Parent" },
108 { MONO_MT_BLOB_IDX, "PermissionSet" },
109 { MONO_MT_END, NULL }
112 static MonoMetaTable EventMapSchema [] = {
113 { MONO_MT_TABLE_IDX, "Parent:TypeDef" },
114 { MONO_MT_TABLE_IDX, "EventList:Event" },
115 { MONO_MT_END, NULL }
118 static MonoMetaTable EventSchema [] = {
119 { MONO_MT_UINT16, "EventFlags#EventAttribute" },
120 { MONO_MT_STRING_IDX, "Name" },
121 { MONO_MT_TABLE_IDX, "EventType" }, /* TypeDef or TypeRef */
122 { MONO_MT_END, NULL }
125 static MonoMetaTable ExportedTypeSchema [] = {
126 { MONO_MT_UINT32, "Flags" },
127 { MONO_MT_TABLE_IDX, "TypeDefId" },
128 { MONO_MT_STRING_IDX, "TypeName" },
129 { MONO_MT_STRING_IDX, "TypeNameSpace" },
130 { MONO_MT_IMPL_IDX, "Implementation" },
131 { MONO_MT_END, NULL }
134 static MonoMetaTable FieldSchema [] = {
135 { MONO_MT_UINT16, "Flags" },
136 { MONO_MT_STRING_IDX, "Name" },
137 { MONO_MT_BLOB_IDX, "Signature" },
138 { MONO_MT_END, NULL }
140 static MonoMetaTable FieldLayoutSchema [] = {
141 { MONO_MT_UINT32, "Offset" },
142 { MONO_MT_TABLE_IDX, "Field:Field" },
143 { MONO_MT_END, NULL }
146 static MonoMetaTable FieldMarshalSchema [] = {
147 { MONO_MT_HFM_IDX, "Parent" },
148 { MONO_MT_BLOB_IDX, "NativeType" },
149 { MONO_MT_END, NULL }
151 static MonoMetaTable FieldRVASchema [] = {
152 { MONO_MT_UINT32, "RVA" },
153 { MONO_MT_TABLE_IDX, "Field:Field" },
154 { MONO_MT_END, NULL }
157 static MonoMetaTable FileSchema [] = {
158 { MONO_MT_UINT32, "Flags" },
159 { MONO_MT_STRING_IDX, "Name" },
160 { MONO_MT_BLOB_IDX, "Value" },
161 { MONO_MT_END, NULL }
164 static MonoMetaTable ImplMapSchema [] = {
165 { MONO_MT_UINT16, "MappingFlag" },
166 { MONO_MT_MF_IDX, "MemberForwarded" },
167 { MONO_MT_STRING_IDX, "ImportName" },
168 { MONO_MT_TABLE_IDX, "ImportScope:ModuleRef" },
169 { MONO_MT_END, NULL }
172 static MonoMetaTable InterfaceImplSchema [] = {
173 { MONO_MT_TABLE_IDX, "Class:TypeDef" },
174 { MONO_MT_TDOR_IDX, "Interface=TypeDefOrRef" },
175 { MONO_MT_END, NULL }
178 static MonoMetaTable ManifestResourceSchema [] = {
179 { MONO_MT_UINT32, "Offset" },
180 { MONO_MT_UINT32, "Flags" },
181 { MONO_MT_STRING_IDX, "Name" },
182 { MONO_MT_IMPL_IDX, "Implementation" },
183 { MONO_MT_END, NULL }
186 static MonoMetaTable MemberRefSchema [] = {
187 { MONO_MT_MRP_IDX, "Class" },
188 { MONO_MT_STRING_IDX, "Name" },
189 { MONO_MT_BLOB_IDX, "Signature" },
190 { MONO_MT_END, NULL }
193 static MonoMetaTable MethodSchema [] = {
194 { MONO_MT_UINT32, "RVA" },
195 { MONO_MT_UINT16, "ImplFlags#MethodImplAttributes" },
196 { MONO_MT_UINT16, "Flags#MethodAttribute" },
197 { MONO_MT_STRING_IDX, "Name" },
198 { MONO_MT_BLOB_IDX, "Signature" },
199 { MONO_MT_TABLE_IDX, "ParamList:Param" },
200 { MONO_MT_END, NULL }
203 static MonoMetaTable MethodImplSchema [] = {
204 { MONO_MT_TABLE_IDX, "Class:TypeDef" },
205 { MONO_MT_MDOR_IDX, "MethodBody" },
206 { MONO_MT_MDOR_IDX, "MethodDeclaration" },
207 { MONO_MT_END, NULL }
210 static MonoMetaTable MethodSemanticsSchema [] = {
211 { MONO_MT_UINT16, "MethodSemantic" },
212 { MONO_MT_TABLE_IDX, "Method:Method" },
213 { MONO_MT_HS_IDX, "Association" },
214 { MONO_MT_END, NULL }
217 static MonoMetaTable ModuleSchema [] = {
218 { MONO_MT_UINT16, "Generation" },
219 { MONO_MT_STRING_IDX, "Name" },
220 { MONO_MT_GUID_IDX, "MVID" },
221 { MONO_MT_GUID_IDX, "EncID" },
222 { MONO_MT_GUID_IDX, "EncBaseID" },
223 { MONO_MT_END, NULL }
226 static MonoMetaTable ModuleRefSchema [] = {
227 { MONO_MT_STRING_IDX, "Name" },
228 { MONO_MT_END, NULL }
231 static MonoMetaTable NestedClassSchema [] = {
232 { MONO_MT_TABLE_IDX, "NestedClass:TypeDef" },
233 { MONO_MT_TABLE_IDX, "EnclosingClass:TypeDef" },
234 { MONO_MT_END, NULL }
237 static MonoMetaTable ParamSchema [] = {
238 { MONO_MT_UINT16, "Flags" },
239 { MONO_MT_UINT16, "Sequence" },
240 { MONO_MT_STRING_IDX, "Name" },
241 { MONO_MT_END, NULL }
244 static MonoMetaTable PropertySchema [] = {
245 { MONO_MT_UINT16, "Flags" },
246 { MONO_MT_STRING_IDX, "Name" },
247 { MONO_MT_BLOB_IDX, "Type" },
248 { MONO_MT_END, NULL }
251 static MonoMetaTable PropertyMapSchema [] = {
252 { MONO_MT_TABLE_IDX, "Parent:TypeDef" },
253 { MONO_MT_TABLE_IDX, "PropertyList:Property" },
254 { MONO_MT_END, NULL }
257 static MonoMetaTable StandaloneSigSchema [] = {
258 { MONO_MT_BLOB_IDX, "Signature" },
259 { MONO_MT_END, NULL }
262 static MonoMetaTable TypeDefSchema [] = {
263 { MONO_MT_UINT32, "Flags" },
264 { MONO_MT_STRING_IDX, "Name" },
265 { MONO_MT_STRING_IDX, "Namespace" },
266 { MONO_MT_TDOR_IDX, "Extends" },
267 { MONO_MT_TABLE_IDX, "FieldList:Field" },
268 { MONO_MT_TABLE_IDX, "MethodList:Method" },
269 { MONO_MT_END, NULL }
272 static MonoMetaTable TypeRefSchema [] = {
273 { MONO_MT_RS_IDX, "ResolutionScope=ResolutionScope" },
274 { MONO_MT_STRING_IDX, "Name" },
275 { MONO_MT_STRING_IDX, "Namespace" },
276 { MONO_MT_END, NULL }
279 static MonoMetaTable TypeSpecSchema [] = {
280 { MONO_MT_BLOB_IDX, "Signature" },
281 { MONO_MT_END, NULL }
285 MonoMetaTable *table;
288 /* 0 */ { ModuleSchema, "Module" },
289 /* 1 */ { TypeRefSchema, "TypeRef" },
290 /* 2 */ { TypeDefSchema, "TypeDef" },
291 /* 3 */ { NULL, NULL },
292 /* 4 */ { FieldSchema, "Field" },
293 /* 5 */ { NULL, NULL },
294 /* 6 */ { MethodSchema, "Method" },
295 /* 7 */ { NULL, NULL },
296 /* 8 */ { ParamSchema, "Param" },
297 /* 9 */ { InterfaceImplSchema, "InterfaceImpl" },
298 /* A */ { MemberRefSchema, "MemberRef" },
299 /* B */ { ConstantSchema, "Constant" },
300 /* C */ { CustomAttributeSchema, "CustomAttribute" },
301 /* D */ { FieldMarshalSchema, "FieldMarshal" },
302 /* E */ { DeclSecuritySchema, "DeclSecurity" },
303 /* F */ { ClassLayoutSchema, "ClassLayout" },
304 /* 10 */ { FieldLayoutSchema, "FieldLayout" },
305 /* 11 */ { StandaloneSigSchema, "StandaloneSig" },
306 /* 12 */ { EventMapSchema, "EventMap" },
307 /* 13 */ { NULL, NULL },
308 /* 14 */ { EventSchema, "Event" },
309 /* 15 */ { PropertyMapSchema, "PropertyMap" },
310 /* 16 */ { NULL, NULL },
311 /* 17 */ { PropertySchema, "PropertyTable" },
312 /* 18 */ { MethodSemanticsSchema, "MethodSemantics" },
313 /* 19 */ { MethodImplSchema, "MethodImpl" },
314 /* 1A */ { ModuleRefSchema, "ModuleRef" },
315 /* 1B */ { TypeSpecSchema, "TypeSpec" },
316 /* 1C */ { ImplMapSchema, "ImplMap" },
317 /* 1D */ { FieldRVASchema, "FieldRVA" },
318 /* 1E */ { NULL, NULL },
319 /* 1F */ { NULL, NULL },
320 /* 20 */ { AssemblySchema, "Assembly" },
321 /* 21 */ { AssemblyProcessorSchema, "AssemblyProcessor" },
322 /* 22 */ { AssemblyOSSchema, "AssemblyOS" },
323 /* 23 */ { AssemblyRefSchema, "AssemblyRef" },
324 /* 24 */ { AssemblyRefProcessorSchema, "AssemblyRefProcessor" },
325 /* 25 */ { AssemblyRefOSSchema, "AssemblyRefOS" },
326 /* 26 */ { FileSchema, "File" },
327 /* 27 */ { ExportedTypeSchema, "ExportedType" },
328 /* 28 */ { ManifestResourceSchema, "ManifestResource" },
329 /* 29 */ { NestedClassSchema, "NestedClass" },
330 /* 2A */ { NULL, NULL },
331 /* 2B */ { NULL, NULL },
335 * mono_meta_table_name:
336 * @table: table index
338 * Returns the name for the @table index
341 mono_meta_table_name (int table)
343 if ((table < 0) || (table > 0x29))
346 return tables [table].name;
349 /* The guy who wrote the spec for this should not be allowed near a
352 If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
353 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
354 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
355 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
356 inverse of this mapping.
359 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
360 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
362 /* Reference: Partition II - 23.2.6 */
364 compute_size (metadata_t *meta, MonoMetaTable *table, int tableindex, guint32 *result_bitfield)
366 guint32 bitfield = 0;
367 int size = 0, field_size;
371 for (i = 0; (code = table [i].code) != MONO_MT_END; i++){
374 field_size = 4; break;
377 field_size = 2; break;
380 field_size = 1; break;
382 case MONO_MT_BLOB_IDX:
383 field_size = meta->idx_blob_wide ? 4 : 2; break;
385 case MONO_MT_STRING_IDX:
386 field_size = meta->idx_string_wide ? 4 : 2; break;
388 case MONO_MT_GUID_IDX:
389 field_size = meta->idx_guid_wide ? 4 : 2; break;
391 case MONO_MT_TABLE_IDX:
392 /* Uhm, a table index can point to other tables besides the current one
393 * so, it's not correct to use the rowcount of the current table to
394 * get the size for this column - lupus
396 switch (tableindex) {
397 case META_TABLE_ASSEMBLYREFOS:
399 field_size = idx_size (META_TABLE_ASSEMBLYREF); break;
400 case META_TABLE_ASSEMBLYPROCESSOR:
402 field_size = idx_size (META_TABLE_ASSEMBLYREF); break;
403 case META_TABLE_CLASSLAYOUT:
405 field_size = idx_size (META_TABLE_TYPEDEF); break;
406 case META_TABLE_EVENTMAP:
407 g_assert (i == 0 || i == 1);
408 field_size = i ? idx_size (META_TABLE_EVENT):
409 idx_size(META_TABLE_TYPEDEF);
411 case META_TABLE_EVENT:
413 field_size = MAX (idx_size (META_TABLE_TYPEDEF), idx_size(META_TABLE_TYPEREF));
414 field_size = MAX (field_size, idx_size(META_TABLE_TYPESPEC));
416 case META_TABLE_EXPORTEDTYPE:
418 field_size = idx_size (META_TABLE_TYPEDEF); break;
419 case META_TABLE_FIELDLAYOUT:
421 field_size = idx_size (META_TABLE_FIELD); break;
422 case META_TABLE_FIELDRVA:
424 field_size = idx_size (META_TABLE_FIELD); break;
425 case META_TABLE_IMPLMAP:
427 field_size = idx_size (META_TABLE_MODULEREF); break;
428 case META_TABLE_INTERFACEIMPL:
430 field_size = idx_size (META_TABLE_TYPEDEF); break;
431 case META_TABLE_METHOD:
433 field_size = idx_size (META_TABLE_PARAM); break;
434 case META_TABLE_METHODIMPL:
436 field_size = idx_size (META_TABLE_TYPEDEF); break;
437 case META_TABLE_METHODSEMANTICS:
439 field_size = idx_size (META_TABLE_METHOD); break;
440 case META_TABLE_NESTEDCLASS:
441 g_assert (i == 0 || i == 1);
442 field_size = idx_size (META_TABLE_TYPEDEF); break;
443 case META_TABLE_PROPERTYMAP:
444 g_assert (i == 0 || i == 1);
445 field_size = i ? idx_size (META_TABLE_PROPERTY):
446 idx_size(META_TABLE_TYPEDEF);
448 case META_TABLE_TYPEDEF:
449 g_assert (i == 4 || i == 5);
450 field_size = i == 4 ? idx_size (META_TABLE_FIELD):
451 idx_size(META_TABLE_METHOD);
454 g_assert_not_reached ();
456 if (field_size != idx_size (tableindex))
457 g_warning ("size changed (%d to %d)", idx_size (tableindex), field_size);
462 * HasConstant: ParamDef, FieldDef, Property
464 case MONO_MT_CONST_IDX:
465 n = MAX (meta->tables [META_TABLE_PARAM].rows,
466 meta->tables [META_TABLE_FIELD].rows);
467 n = MAX (n, meta->tables [META_TABLE_PROPERTY].rows);
469 /* 2 bits to encode tag */
470 field_size = rtsize (n, 16-2);
474 * HasCustomAttribute: points to any table but
477 case MONO_MT_HASCAT_IDX:
479 * We believe that since the signature and
480 * permission are indexing the Blob heap,
481 * we should consider the blob size first
483 /* I'm not a believer - lupus
484 if (meta->idx_blob_wide){
489 n = MAX (meta->tables [META_TABLE_METHOD].rows,
490 meta->tables [META_TABLE_FIELD].rows);
491 n = MAX (n, meta->tables [META_TABLE_TYPEREF].rows);
492 n = MAX (n, meta->tables [META_TABLE_TYPEDEF].rows);
493 n = MAX (n, meta->tables [META_TABLE_PARAM].rows);
494 n = MAX (n, meta->tables [META_TABLE_INTERFACEIMPL].rows);
495 n = MAX (n, meta->tables [META_TABLE_MEMBERREF].rows);
496 n = MAX (n, meta->tables [META_TABLE_MODULE].rows);
497 /* Permission seems to be a blob heap pointer */
498 n = MAX (n, meta->tables [META_TABLE_PROPERTY].rows);
499 n = MAX (n, meta->tables [META_TABLE_EVENT].rows);
500 /* Signature seems to be a blob heap pointer */
501 n = MAX (n, meta->tables [META_TABLE_MODULEREF].rows);
502 n = MAX (n, meta->tables [META_TABLE_TYPESPEC].rows);
503 n = MAX (n, meta->tables [META_TABLE_ASSEMBLY].rows);
504 n = MAX (n, meta->tables [META_TABLE_ASSEMBLYREF].rows);
505 n = MAX (n, meta->tables [META_TABLE_FILE].rows);
506 n = MAX (n, meta->tables [META_TABLE_EXPORTEDTYPE].rows);
507 n = MAX (n, meta->tables [META_TABLE_MANIFESTRESOURCE].rows);
509 /* 5 bits to encode */
510 field_size = rtsize (n, 16-5);
514 * CustomAttributeType: TypeDef, TypeRef, MethodDef,
515 * MemberRef and String.
517 case MONO_MT_CAT_IDX:
518 /* String is a heap, if it is wide, we know the size */
520 if (meta->idx_string_wide){
525 n = MAX (meta->tables [META_TABLE_TYPEREF].rows,
526 meta->tables [META_TABLE_TYPEDEF].rows);
527 n = MAX (n, meta->tables [META_TABLE_METHOD].rows);
528 n = MAX (n, meta->tables [META_TABLE_MEMBERREF].rows);
530 /* 3 bits to encode */
531 field_size = rtsize (n, 16-3);
535 * HasDeclSecurity: Typedef, MethodDef, Assembly
537 case MONO_MT_HASDEC_IDX:
538 n = MAX (meta->tables [META_TABLE_TYPEDEF].rows,
539 meta->tables [META_TABLE_METHOD].rows);
540 n = MAX (n, meta->tables [META_TABLE_ASSEMBLY].rows);
542 /* 2 bits to encode */
543 field_size = rtsize (n, 16-2);
547 * Implementation: File, AssemblyRef, ExportedType
549 case MONO_MT_IMPL_IDX:
550 n = MAX (meta->tables [META_TABLE_FILE].rows,
551 meta->tables [META_TABLE_ASSEMBLYREF].rows);
552 n = MAX (n, meta->tables [META_TABLE_EXPORTEDTYPE].rows);
554 /* 2 bits to encode tag */
555 field_size = rtsize (n, 16-2);
559 * HasFieldMarshall: FieldDef, ParamDef
561 case MONO_MT_HFM_IDX:
562 n = MAX (meta->tables [META_TABLE_FIELD].rows,
563 meta->tables [META_TABLE_PARAM].rows);
565 /* 1 bit used to encode tag */
566 field_size = rtsize (n, 16-1);
570 * MemberForwarded: FieldDef, MethodDef
573 n = MAX (meta->tables [META_TABLE_FIELD].rows,
574 meta->tables [META_TABLE_METHOD].rows);
576 /* 1 bit used to encode tag */
577 field_size = rtsize (n, 16-1);
581 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
583 case MONO_MT_TDOR_IDX:
584 n = MAX (meta->tables [META_TABLE_TYPEDEF].rows,
585 meta->tables [META_TABLE_PARAM].rows);
586 n = MAX (n, meta->tables [META_TABLE_TYPESPEC].rows);
588 /* 2 bits to encode */
589 field_size = rtsize (n, 16-2);
593 * MemberRefParent: TypeDef, TypeRef, ModuleDef, ModuleRef, TypeSpec
595 case MONO_MT_MRP_IDX:
596 n = MAX (meta->tables [META_TABLE_TYPEDEF].rows,
597 meta->tables [META_TABLE_TYPEREF].rows);
598 n = MAX (n, meta->tables [META_TABLE_MODULE].rows);
599 n = MAX (n, meta->tables [META_TABLE_MODULEREF].rows);
600 n = MAX (n, meta->tables [META_TABLE_TYPESPEC].rows);
602 /* 3 bits to encode */
603 field_size = rtsize (n, 16 - 3);
606 case MONO_MT_MDOR_IDX:
609 * MethodDefOrRef: MethodDef, MemberRef
612 n = MAX (meta->tables [META_TABLE_METHOD].rows,
613 meta->tables [META_TABLE_MEMBERREF].rows);
615 /* 1 bit used to encode tag */
616 field_size = rtsize (n, 16-1);
620 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
623 n = MAX (meta->tables [META_TABLE_MODULE].rows,
624 meta->tables [META_TABLE_MODULEREF].rows);
625 n = MAX (n, meta->tables [META_TABLE_ASSEMBLYREF].rows);
626 n = MAX (n, meta->tables [META_TABLE_TYPEREF].rows);
628 /* 2 bits used to encode tag (ECMA spec claims 3) */
629 field_size = rtsize (n, 16 - 2);
634 * encode field size as follows (we just need to
641 bitfield |= (field_size-1) << shift;
644 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
647 *result_bitfield = (i << 24) | bitfield;
652 * mono_metadata_compute_table_bases:
653 * @meta: metadata context to compute table values
655 * Computes the table bases for the metadata structure.
656 * This is an internal function used by the image loader code.
659 mono_metadata_compute_table_bases (metadata_t *meta)
662 char *base = meta->tables_base;
664 for (i = 0; i < 64; i++){
665 if (meta->tables [i].rows == 0)
668 meta->tables [i].row_size = compute_size (
669 meta, tables [i].table, i,
670 &meta->tables [i].size_bitfield);
671 meta->tables [i].base = base;
672 base += meta->tables [i].rows * meta->tables [i].row_size;
677 * mono_metadata_locate:
678 * @meta: metadata context
679 * @table: table code.
680 * @idx: index of element to retrieve from @table.
682 * Returns a pointer to the @idx element in the metadata table
683 * whose code is @table.
686 mono_metadata_locate (metadata_t *meta, int table, int idx)
688 /* idx == 0 refers always to NULL */
689 g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, "");
691 return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
695 mono_metadata_locate_token (metadata_t *meta, guint32 token)
697 return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
701 * mono_metadata_get_table:
702 * @table: table to retrieve
704 * Returns the MonoMetaTable structure for table @table
707 mono_metadata_get_table (MetaTableEnum table)
711 g_return_val_if_fail ((x > 0) && (x <= META_TABLE_LAST), NULL);
713 return tables [table].table;
717 * mono_metadata_string_heap:
718 * @meta: metadata context
719 * @index: index into the string heap.
721 * Returns: an in-memory pointer to the @index in the string heap.
724 mono_metadata_string_heap (metadata_t *meta, guint32 index)
726 g_return_val_if_fail (index < meta->heap_strings.sh_size, "");
727 return meta->raw_metadata + meta->heap_strings.sh_offset + index;
731 mono_metadata_user_string (metadata_t *meta, guint32 index)
733 g_return_val_if_fail (index < meta->heap_us.sh_size, "");
734 return meta->raw_metadata + meta->heap_us.sh_offset + index;
738 * mono_metadata_blob_heap:
739 * @meta: metadata context
740 * @index: index into the blob.
742 * Returns: an in-memory pointer to the @index in the Blob heap.
745 mono_metadata_blob_heap (metadata_t *meta, guint32 index)
747 g_return_val_if_fail (index < meta->heap_blob.sh_size, "");
748 return meta->raw_metadata + meta->heap_blob.sh_offset + index;
752 dword_align (const char *ptr)
754 return (const char *) (((guint32) (ptr + 3)) & ~3);
757 static MonoMetaExceptionHandler *
758 parse_exception_handler (const char *ptr, gboolean is_fat)
760 MonoMetaExceptionHandler *eh = g_new0 (MonoMetaExceptionHandler, 1);
763 eh->kind = (MonoMetaExceptionEnum) *ptr;
766 size = (ptr [0] << 16) | (ptr [1] << 8) | ptr [2];
768 size = (unsigned char) ptr [0];
774 g_assert ((((guint32) ptr) & 3) == 0);
777 printf ("Records: %d (%d)\n", size / 12, size);
780 printf ("Records: %d (%d)\n", size / 12, size);
788 * mono_metadata_decode_row:
789 * @t: table to extract information from.
790 * @idx: index in table.
791 * @res: array of @res_size cols to store the results in
793 * This decompresses the metadata element @idx in table @t
794 * into the guint32 @res array that has res_size elements
797 mono_metadata_decode_row (metadata_tableinfo_t *t, int idx, guint32 *res, int res_size)
799 guint32 bitfield = t->size_bitfield;
800 int i, count = meta_table_count (bitfield);
801 char *data = t->base + idx * t->row_size;
803 g_assert (res_size == count);
805 for (i = 0; i < count; i++){
806 int n = meta_table_size (bitfield, i);
810 res [i] = *data; break;
812 res [i] = read16 (data); break;
815 res [i] = read32 (data); break;
818 g_assert_not_reached ();
825 * mono_metadata_decode_blob_size:
826 * @ptr: pointer to a blob object
827 * @size: where we return the size of the object
829 * This decodes a compressed size as described by 23.1.4
831 * Returns: the position to start decoding a blob or user string object
835 mono_metadata_decode_blob_size (const char *xptr, int *size)
837 const unsigned char *ptr = xptr;
839 if ((*ptr & 0x80) == 0){
840 *size = ptr [0] & 0x7f;
842 } else if ((*ptr & 0x40) == 0){
843 *size = ((ptr [0] & 0x3f) << 8) + ptr [1];
846 *size = ((ptr [0] & 0x1f) << 24) +
858 * mono_metadata_decode_value:
859 * @ptr: pointer to decode from
860 * @len: result value is stored here.
862 * This routine decompresses 32-bit values as specified in the "Blob and
863 * Signature" section (22.2)
865 * Returns: updated pointer location
868 mono_metadata_decode_value (const char *_ptr, guint32 *len)
870 const unsigned char *ptr = (unsigned char *) _ptr;
871 unsigned char b = *ptr;
873 if ((b & 0x80) == 0){
876 } else if ((b & 0x40) == 0){
877 *len = ((b & 0x3f) << 8 | ptr [1]);
880 *len = ((b & 0x1f) << 24) |
889 mono_metadata_parse_typedef_or_ref (metadata_t *m, const char *ptr, const char **rptr)
893 ptr = mono_metadata_decode_value (ptr, &token);
895 switch (table & 0x03) {
896 case 0: table = META_TABLE_TYPEDEF; break;
897 case 1: table = META_TABLE_TYPEREF; break;
898 case 2: table = META_TABLE_TYPESPEC; break;
899 default: g_error ("Unhandled encoding for typedef-or-ref coded index");
903 return (token >> 2) | table << 24;
907 mono_metadata_parse_custom_mod (metadata_t *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
910 if ((*ptr == ELEMENT_TYPE_CMOD_OPT) ||
911 (*ptr == ELEMENT_TYPE_CMOD_REQD)) {
915 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
922 mono_metadata_parse_array (metadata_t *m, const char *ptr, const char **rptr)
925 MonoArray *array = g_new0(MonoArray, 1);
927 array->type = mono_metadata_parse_type (m, ptr, &ptr);
928 ptr = mono_metadata_decode_value (ptr, &array->rank);
930 ptr = mono_metadata_decode_value (ptr, &array->numsizes);
932 array->sizes = g_new0(int, array->numsizes);
933 for (i = 0; i < array->numsizes; ++i)
934 ptr = mono_metadata_decode_value (ptr, &(array->sizes[i]));
936 ptr = mono_metadata_decode_value (ptr, &array->numlobounds);
937 if (array->numlobounds)
938 array->lobounds = g_new0(int, array->numlobounds);
939 for (i = 0; i < array->numlobounds; ++i)
940 ptr = mono_metadata_decode_value (ptr, &(array->lobounds[i]));
948 mono_metadata_free_array (MonoArray *array)
950 mono_metadata_free_type (array->type);
951 g_free (array->sizes);
952 g_free (array->lobounds);
957 mono_metadata_parse_param (metadata_t *m, int rettype, const char *ptr, const char **rptr)
959 const char *tmp_ptr = ptr;
964 /* count the modifiers */
965 while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
967 param = g_malloc0(sizeof(MonoParam)+(count-1)*sizeof(MonoCustomMod));
968 param->num_modifiers = count;
969 /* save them this time */
971 while (mono_metadata_parse_custom_mod (m, &(param->modifiers[count]), ptr, &ptr))
974 case ELEMENT_TYPE_TYPEDBYREF:
975 param->typedbyref = 1;
978 case ELEMENT_TYPE_VOID:
980 g_error ("void not allowed in param");
983 case ELEMENT_TYPE_BYREF:
988 param->type = mono_metadata_parse_type (m, ptr, &ptr);
989 param->type->byref = byref;
998 mono_metadata_free_param (MonoParam *param)
1001 mono_metadata_free_type (param->type);
1005 MonoMethodSignature *
1006 mono_metadata_parse_method_signature (metadata_t *m, int def, const char *ptr, const char **rptr)
1008 MonoMethodSignature *method = g_new0(MonoMethodSignature, 1);
1012 method->hasthis = 1;
1014 method->explicit_this = 1;
1015 method->call_convention = *ptr & 0x0F;
1017 ptr = mono_metadata_decode_value (ptr, &method->param_count);
1018 method->ret = mono_metadata_parse_param (m, 1, ptr, &ptr);
1020 method->params = g_new0(MonoParam*, method->param_count);
1021 method->sentinelpos = -1;
1022 for (i = 0; i < method->param_count; ++i) {
1023 if (*ptr == ELEMENT_TYPE_SENTINEL) {
1024 if (method->call_convention != MONO_CALL_VARARG || def)
1025 g_error ("found sentinel for methoddef or no vararg method");
1026 method->sentinelpos = i;
1029 method->params[i] = mono_metadata_parse_param (m, 0, ptr, &ptr);
1038 mono_metadata_free_method_signature (MonoMethodSignature *method)
1041 mono_metadata_free_param (method->ret);
1042 for (i = 0; i < method->param_count; ++i)
1043 mono_metadata_free_param (method->params[i]);
1045 g_free (method->params);
1051 mono_metadata_parse_type (metadata_t *m, const char *ptr, const char **rptr)
1053 /* should probably be allocated in a memchunk */
1054 MonoType *type = g_new0(MonoType, 1);
1057 ptr = mono_metadata_decode_value (ptr, &val);
1060 switch (type->type){
1061 case ELEMENT_TYPE_BOOLEAN:
1062 case ELEMENT_TYPE_CHAR:
1063 case ELEMENT_TYPE_I1:
1064 case ELEMENT_TYPE_U1:
1065 case ELEMENT_TYPE_I2:
1066 case ELEMENT_TYPE_U2:
1067 case ELEMENT_TYPE_I4:
1068 case ELEMENT_TYPE_U4:
1069 case ELEMENT_TYPE_I8:
1070 case ELEMENT_TYPE_U8:
1071 case ELEMENT_TYPE_R4:
1072 case ELEMENT_TYPE_R8:
1073 case ELEMENT_TYPE_I:
1074 case ELEMENT_TYPE_U:
1075 case ELEMENT_TYPE_STRING:
1076 case ELEMENT_TYPE_OBJECT:
1078 case ELEMENT_TYPE_VALUETYPE:
1079 case ELEMENT_TYPE_CLASS:
1080 type->data.token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
1082 case ELEMENT_TYPE_SZARRAY:
1083 case ELEMENT_TYPE_PTR:
1084 if (mono_metadata_parse_custom_mod (m, NULL, ptr, NULL)) {
1085 const char *tmp_ptr = ptr;
1086 MonoModifiedType *mtype;
1089 type->custom_mod = 1;
1090 /* count the modifiers */
1091 while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
1093 type->data.mtype = mtype = g_malloc0(sizeof(MonoModifiedType)+(count-1)*sizeof(MonoCustomMod));
1094 mtype->num_modifiers = count;
1096 /* save them this time */
1097 while (mono_metadata_parse_custom_mod (m, &(mtype->modifiers[count]), ptr, &ptr))
1099 /* FIXME: mono_metadata_decode_value ... */
1100 if (*ptr == ELEMENT_TYPE_VOID) {
1104 mtype->type = mono_metadata_parse_type (m, ptr, &ptr);
1107 /* FIXME: mono_metadata_decode_value ... */
1108 if (*ptr == ELEMENT_TYPE_VOID) {
1109 type->data.type = NULL;
1112 type->data.type = mono_metadata_parse_type (m, ptr, &ptr);
1116 case ELEMENT_TYPE_FNPTR:
1117 type->data.method = mono_metadata_parse_method_signature (m, 0, ptr, &ptr);
1119 case ELEMENT_TYPE_ARRAY:
1120 type->data.array = mono_metadata_parse_array (m, ptr, &ptr);
1123 g_error ("type 0x%02x not handled in mono_metadata_parse_type", type->type);
1132 mono_metadata_free_type (MonoType *type)
1134 switch (type->type){
1135 case ELEMENT_TYPE_SZARRAY:
1136 case ELEMENT_TYPE_PTR:
1137 if (!type->custom_mod)
1138 mono_metadata_free_type (type->data.type);
1140 mono_metadata_free_type (type->data.mtype->type);
1141 g_free (type->data.mtype);
1144 case ELEMENT_TYPE_FNPTR:
1145 mono_metadata_free_method_signature (type->data.method);
1147 case ELEMENT_TYPE_ARRAY:
1148 mono_metadata_free_array (type->data.array);
1155 * @mh: The Method header
1156 * @ptr: Points to the beginning of the Section Data (25.3)
1159 parse_section_data (MonoMetaMethodHeader *mh, const char *ptr)
1162 while ((*ptr) & METHOD_HEADER_SECTION_MORE_SECTS){
1163 /* align on 32-bit boundary */
1164 /* FIXME: not 64-bit clean code */
1165 ptr = dword_align (ptr);
1167 sect_data_flags = *ptr;
1170 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS){
1171 g_error ("Can not deal with more sections");
1174 if (sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT){
1177 sect_data_len = ptr [0];
1181 if (!(sect_data_flags & METHOD_HEADER_SECTION_EHTABLE))
1184 ptr = dword_align (ptr);
1189 MonoMetaMethodHeader *
1190 mono_metadata_parse_mh (metadata_t *m, const char *ptr)
1192 MonoMetaMethodHeader *mh;
1193 unsigned char flags = *(unsigned char *) ptr;
1194 unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
1198 g_return_val_if_fail (ptr != NULL, NULL);
1200 mh = g_new0 (MonoMetaMethodHeader, 1);
1202 case METHOD_HEADER_TINY_FORMAT:
1205 mh->local_var_sig_tok = 0;
1206 mh->code_size = flags >> 2;
1210 case METHOD_HEADER_TINY_FORMAT1:
1213 mh->local_var_sig_tok = 0;
1216 // The spec claims 3 bits, but the Beta2 is
1219 mh->code_size = flags >> 2;
1223 case METHOD_HEADER_FAT_FORMAT:
1224 fat_flags = read16 (ptr);
1226 hsize = (fat_flags >> 12) & 0xf;
1227 mh->max_stack = *(guint16 *) ptr;
1229 mh->code_size = *(guint32 *) ptr;
1231 mh->local_var_sig_tok = *(guint32 *) ptr;
1234 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
1235 mh->init_locals = 1;
1237 mh->init_locals = 0;
1241 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
1245 * There are more sections
1247 ptr = mh->code + mh->code_size;
1249 parse_section_data (mh, ptr);
1257 if (mh->local_var_sig_tok) {
1258 metadata_tableinfo_t *t = &m->tables [META_TABLE_STANDALONESIG];
1261 int len=0, i, bsize;
1263 mono_metadata_decode_row (t, (mh->local_var_sig_tok & 0xffffff)-1, cols, 1);
1264 ptr = mono_metadata_blob_heap (m, cols [0]);
1265 ptr = mono_metadata_decode_blob_size (ptr, &bsize);
1267 g_warning ("wrong signature for locals blob");
1269 ptr = mono_metadata_decode_value (ptr, &len);
1270 mh->num_locals = len;
1271 mh->locals = g_new (MonoType*, len);
1272 for (i = 0; i < len; ++i) {
1274 const char *p = ptr;
1275 ptr = mono_metadata_decode_blob_size (ptr, &val);
1276 /* FIXME: store pinned/byref values */
1277 if (val == ELEMENT_TYPE_PINNED) {
1279 ptr = mono_metadata_decode_blob_size (ptr, &val);
1281 if (val == ELEMENT_TYPE_BYREF) {
1284 mh->locals [i] = mono_metadata_parse_type (m, p, &ptr);
1291 mono_metadata_free_mh (MonoMetaMethodHeader *mh)
1294 for (i = 0; i < mh->num_locals; ++i)
1295 mono_metadata_free_type (mh->locals[i]);
1296 g_free (mh->locals);