2 * metadata.c: Routines for accessing the metadata
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
15 #include "tabledefs.h"
18 #include "tokentype.h"
21 * Encoding of the "description" argument:
23 * identifier [CODE ARG]
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.
29 * Aliased table for example is `CustomAttributeType' which depending on the
30 * information might refer to different tables.
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" },
46 static MonoMetaTable AssemblyOSSchema [] = {
47 { MONO_MT_UINT32, "OSPlatformID" },
48 { MONO_MT_UINT32, "OSMajor" },
49 { MONO_MT_UINT32, "OSMinor" },
53 static MonoMetaTable AssemblyProcessorSchema [] = {
54 { MONO_MT_UINT32, "Processor" },
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" },
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" },
79 static MonoMetaTable AssemblyRefProcessorSchema [] = {
80 { MONO_MT_UINT32, "Processor" },
81 { MONO_MT_TABLE_IDX, "AssemblyRef:AssemblyRef" },
85 static MonoMetaTable ClassLayoutSchema [] = {
86 { MONO_MT_UINT16, "PackingSize" },
87 { MONO_MT_UINT32, "ClassSize" },
88 { MONO_MT_TABLE_IDX, "Parent:TypeDef" },
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" },
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 }
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 }
114 static MonoMetaTable EventMapSchema [] = {
115 { MONO_MT_TABLE_IDX, "Parent:TypeDef" },
116 { MONO_MT_TABLE_IDX, "EventList:Event" },
117 { MONO_MT_END, NULL }
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 }
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 }
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 }
142 static MonoMetaTable FieldLayoutSchema [] = {
143 { MONO_MT_UINT32, "Offset" },
144 { MONO_MT_TABLE_IDX, "Field:Field" },
145 { MONO_MT_END, NULL }
148 static MonoMetaTable FieldMarshalSchema [] = {
149 { MONO_MT_HFM_IDX, "Parent" },
150 { MONO_MT_BLOB_IDX, "NativeType" },
151 { MONO_MT_END, NULL }
153 static MonoMetaTable FieldRVASchema [] = {
154 { MONO_MT_UINT32, "RVA" },
155 { MONO_MT_TABLE_IDX, "Field:Field" },
156 { MONO_MT_END, NULL }
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 }
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 }
174 static MonoMetaTable InterfaceImplSchema [] = {
175 { MONO_MT_TABLE_IDX, "Class:TypeDef" },
176 { MONO_MT_TDOR_IDX, "Interface=TypeDefOrRef" },
177 { MONO_MT_END, NULL }
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 }
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 }
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 }
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 }
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 }
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 }
228 static MonoMetaTable ModuleRefSchema [] = {
229 { MONO_MT_STRING_IDX, "Name" },
230 { MONO_MT_END, NULL }
233 static MonoMetaTable NestedClassSchema [] = {
234 { MONO_MT_TABLE_IDX, "NestedClass:TypeDef" },
235 { MONO_MT_TABLE_IDX, "EnclosingClass:TypeDef" },
236 { MONO_MT_END, NULL }
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 }
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 }
253 static MonoMetaTable PropertyMapSchema [] = {
254 { MONO_MT_TABLE_IDX, "Parent:TypeDef" },
255 { MONO_MT_TABLE_IDX, "PropertyList:Property" },
256 { MONO_MT_END, NULL }
259 static MonoMetaTable StandaloneSigSchema [] = {
260 { MONO_MT_BLOB_IDX, "Signature" },
261 { MONO_MT_END, NULL }
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 }
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 }
281 static MonoMetaTable TypeSpecSchema [] = {
282 { MONO_MT_BLOB_IDX, "Signature" },
283 { MONO_MT_END, NULL }
287 MonoMetaTable *table;
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 },
337 * mono_meta_table_name:
338 * @table: table index
340 * Returns the name for the @table index
343 mono_meta_table_name (int table)
345 if ((table < 0) || (table > 0x29))
348 return tables [table].name;
351 /* The guy who wrote the spec for this should not be allowed near a
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.
361 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
362 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
364 /* Reference: Partition II - 23.2.6 */
366 compute_size (metadata_t *meta, MonoMetaTable *table, int tableindex, guint32 *result_bitfield)
368 guint32 bitfield = 0;
369 int size = 0, field_size;
373 for (i = 0; (code = table [i].code) != MONO_MT_END; i++){
376 field_size = 4; break;
379 field_size = 2; break;
382 field_size = 1; break;
384 case MONO_MT_BLOB_IDX:
385 field_size = meta->idx_blob_wide ? 4 : 2; break;
387 case MONO_MT_STRING_IDX:
388 field_size = meta->idx_string_wide ? 4 : 2; break;
390 case MONO_MT_GUID_IDX:
391 field_size = meta->idx_guid_wide ? 4 : 2; break;
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
398 switch (tableindex) {
399 case META_TABLE_ASSEMBLYREFOS:
401 field_size = idx_size (META_TABLE_ASSEMBLYREF); break;
402 case META_TABLE_ASSEMBLYPROCESSOR:
404 field_size = idx_size (META_TABLE_ASSEMBLYREF); break;
405 case META_TABLE_CLASSLAYOUT:
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);
413 case META_TABLE_EVENT:
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));
418 case META_TABLE_EXPORTEDTYPE:
420 field_size = idx_size (META_TABLE_TYPEDEF); break;
421 case META_TABLE_FIELDLAYOUT:
423 field_size = idx_size (META_TABLE_FIELD); break;
424 case META_TABLE_FIELDRVA:
426 field_size = idx_size (META_TABLE_FIELD); break;
427 case META_TABLE_IMPLMAP:
429 field_size = idx_size (META_TABLE_MODULEREF); break;
430 case META_TABLE_INTERFACEIMPL:
432 field_size = idx_size (META_TABLE_TYPEDEF); break;
433 case META_TABLE_METHOD:
435 field_size = idx_size (META_TABLE_PARAM); break;
436 case META_TABLE_METHODIMPL:
438 field_size = idx_size (META_TABLE_TYPEDEF); break;
439 case META_TABLE_METHODSEMANTICS:
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);
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);
456 g_assert_not_reached ();
458 if (field_size != idx_size (tableindex))
459 g_warning ("size changed (%d to %d)", idx_size (tableindex), field_size);
464 * HasConstant: ParamDef, FieldDef, Property
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);
471 /* 2 bits to encode tag */
472 field_size = rtsize (n, 16-2);
476 * HasCustomAttribute: points to any table but
479 case MONO_MT_HASCAT_IDX:
481 * We believe that since the signature and
482 * permission are indexing the Blob heap,
483 * we should consider the blob size first
485 /* I'm not a believer - lupus
486 if (meta->idx_blob_wide){
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);
511 /* 5 bits to encode */
512 field_size = rtsize (n, 16-5);
516 * CustomAttributeType: TypeDef, TypeRef, MethodDef,
517 * MemberRef and String.
519 case MONO_MT_CAT_IDX:
520 /* String is a heap, if it is wide, we know the size */
522 if (meta->idx_string_wide){
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);
532 /* 3 bits to encode */
533 field_size = rtsize (n, 16-3);
537 * HasDeclSecurity: Typedef, MethodDef, Assembly
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);
544 /* 2 bits to encode */
545 field_size = rtsize (n, 16-2);
549 * Implementation: File, AssemblyRef, ExportedType
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);
556 /* 2 bits to encode tag */
557 field_size = rtsize (n, 16-2);
561 * HasFieldMarshall: FieldDef, ParamDef
563 case MONO_MT_HFM_IDX:
564 n = MAX (meta->tables [META_TABLE_FIELD].rows,
565 meta->tables [META_TABLE_PARAM].rows);
567 /* 1 bit used to encode tag */
568 field_size = rtsize (n, 16-1);
572 * MemberForwarded: FieldDef, MethodDef
575 n = MAX (meta->tables [META_TABLE_FIELD].rows,
576 meta->tables [META_TABLE_METHOD].rows);
578 /* 1 bit used to encode tag */
579 field_size = rtsize (n, 16-1);
583 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
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);
590 /* 2 bits to encode */
591 field_size = rtsize (n, 16-2);
595 * MemberRefParent: TypeDef, TypeRef, ModuleDef, ModuleRef, TypeSpec
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);
604 /* 3 bits to encode */
605 field_size = rtsize (n, 16 - 3);
608 case MONO_MT_MDOR_IDX:
611 * MethodDefOrRef: MethodDef, MemberRef
614 n = MAX (meta->tables [META_TABLE_METHOD].rows,
615 meta->tables [META_TABLE_MEMBERREF].rows);
617 /* 1 bit used to encode tag */
618 field_size = rtsize (n, 16-1);
622 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
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);
630 /* 2 bits used to encode tag (ECMA spec claims 3) */
631 field_size = rtsize (n, 16 - 2);
636 * encode field size as follows (we just need to
643 bitfield |= (field_size-1) << shift;
646 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
649 *result_bitfield = (i << 24) | bitfield;
654 * mono_metadata_compute_table_bases:
655 * @meta: metadata context to compute table values
657 * Computes the table bases for the metadata structure.
658 * This is an internal function used by the image loader code.
661 mono_metadata_compute_table_bases (metadata_t *meta)
664 char *base = meta->tables_base;
666 for (i = 0; i < 64; i++){
667 if (meta->tables [i].rows == 0)
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;
679 * mono_metadata_locate:
680 * @meta: metadata context
681 * @table: table code.
682 * @idx: index of element to retrieve from @table.
684 * Returns a pointer to the @idx element in the metadata table
685 * whose code is @table.
688 mono_metadata_locate (metadata_t *meta, int table, int idx)
690 /* idx == 0 refers always to NULL */
691 g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, "");
693 return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
697 mono_metadata_locate_token (metadata_t *meta, guint32 token)
699 return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
703 * mono_metadata_get_table:
704 * @table: table to retrieve
706 * Returns the MonoMetaTable structure for table @table
709 mono_metadata_get_table (MetaTableEnum table)
713 g_return_val_if_fail ((x > 0) && (x <= META_TABLE_LAST), NULL);
715 return tables [table].table;
719 * mono_metadata_string_heap:
720 * @meta: metadata context
721 * @index: index into the string heap.
723 * Returns: an in-memory pointer to the @index in the string heap.
726 mono_metadata_string_heap (metadata_t *meta, guint32 index)
728 g_return_val_if_fail (index < meta->heap_strings.sh_size, "");
729 return meta->raw_metadata + meta->heap_strings.sh_offset + index;
733 mono_metadata_user_string (metadata_t *meta, guint32 index)
735 g_return_val_if_fail (index < meta->heap_us.sh_size, "");
736 return meta->raw_metadata + meta->heap_us.sh_offset + index;
740 * mono_metadata_blob_heap:
741 * @meta: metadata context
742 * @index: index into the blob.
744 * Returns: an in-memory pointer to the @index in the Blob heap.
747 mono_metadata_blob_heap (metadata_t *meta, guint32 index)
749 g_return_val_if_fail (index < meta->heap_blob.sh_size, "");
750 return meta->raw_metadata + meta->heap_blob.sh_offset + index;
754 dword_align (const char *ptr)
756 return (const char *) (((guint32) (ptr + 3)) & ~3);
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
765 * This decompresses the metadata element @idx in table @t
766 * into the guint32 @res array that has res_size elements
769 mono_metadata_decode_row (metadata_tableinfo_t *t, int idx, guint32 *res, int res_size)
771 guint32 bitfield = t->size_bitfield;
772 int i, count = meta_table_count (bitfield);
773 char *data = t->base + idx * t->row_size;
775 g_assert (res_size == count);
777 for (i = 0; i < count; i++){
778 int n = meta_table_size (bitfield, i);
782 res [i] = *data; break;
784 res [i] = read16 (data); break;
787 res [i] = read32 (data); break;
790 g_assert_not_reached ();
797 * mono_metadata_decode_blob_size:
798 * @ptr: pointer to a blob object
799 * @rptr: the new position of the pointer
801 * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
803 * Returns: the size of the blob object
806 mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
808 const unsigned char *ptr = xptr;
811 if ((*ptr & 0x80) == 0){
812 size = ptr [0] & 0x7f;
814 } else if ((*ptr & 0x40) == 0){
815 size = ((ptr [0] & 0x3f) << 8) + ptr [1];
818 size = ((ptr [0] & 0x1f) << 24) +
831 * mono_metadata_decode_value:
832 * @ptr: pointer to decode from
833 * @rptr: the new position of the pointer
835 * This routine decompresses 32-bit values as specified in the "Blob and
836 * Signature" section (22.2)
838 * Returns: the decoded value
841 mono_metadata_decode_value (const char *_ptr, const char **rptr)
843 const unsigned char *ptr = (unsigned char *) _ptr;
844 unsigned char b = *ptr;
847 if ((b & 0x80) == 0){
850 } else if ((b & 0x40) == 0){
851 len = ((b & 0x3f) << 8 | ptr [1]);
854 len = ((b & 0x1f) << 24) |
867 mono_metadata_parse_typedef_or_ref (metadata_t *m, const char *ptr, const char **rptr)
871 token = mono_metadata_decode_value (ptr, &ptr);
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");
881 return (token >> 2) | table << 24;
885 mono_metadata_parse_custom_mod (metadata_t *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
888 if ((*ptr == ELEMENT_TYPE_CMOD_OPT) ||
889 (*ptr == ELEMENT_TYPE_CMOD_REQD)) {
893 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
900 mono_metadata_parse_array (metadata_t *m, const char *ptr, const char **rptr)
903 MonoArray *array = g_new0 (MonoArray, 1);
905 array->type = mono_metadata_parse_type (m, ptr, &ptr);
906 array->rank = mono_metadata_decode_value (ptr, &ptr);
908 array->numsizes = mono_metadata_decode_value (ptr, &ptr);
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);
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);
926 mono_metadata_free_array (MonoArray *array)
928 mono_metadata_free_type (array->type);
929 g_free (array->sizes);
930 g_free (array->lobounds);
935 mono_metadata_parse_param (metadata_t *m, int rettype, const char *ptr, const char **rptr)
937 const char *tmp_ptr = ptr;
942 /* count the modifiers */
943 while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
945 param = g_malloc0(sizeof(MonoParam)+(count-MONO_ZERO_LEN_ARRAY)*sizeof(MonoCustomMod));
946 param->num_modifiers = count;
947 /* save them this time */
949 while (mono_metadata_parse_custom_mod (m, &(param->modifiers[count]), ptr, &ptr))
952 case ELEMENT_TYPE_TYPEDBYREF:
953 param->typedbyref = 1;
956 case ELEMENT_TYPE_VOID:
958 g_error ("void not allowed in param");
961 case ELEMENT_TYPE_BYREF:
966 param->type = mono_metadata_parse_type (m, ptr, &ptr);
967 param->type->byref = byref;
976 mono_metadata_free_param (MonoParam *param)
979 mono_metadata_free_type (param->type);
983 MonoMethodSignature *
984 mono_metadata_parse_method_signature (metadata_t *m, int def, const char *ptr, const char **rptr)
986 MonoMethodSignature *method = g_new0(MonoMethodSignature, 1);
992 method->explicit_this = 1;
993 method->call_convention = *ptr & 0x0F;
995 method->param_count = mono_metadata_decode_value (ptr, &ptr);
996 method->ret = mono_metadata_parse_param (m, 1, ptr, &ptr);
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;
1007 method->params[i] = mono_metadata_parse_param (m, 0, ptr, &ptr);
1016 mono_metadata_free_method_signature (MonoMethodSignature *method)
1019 mono_metadata_free_param (method->ret);
1020 for (i = 0; i < method->param_count; ++i)
1021 mono_metadata_free_param (method->params[i]);
1023 g_free (method->params);
1028 * do_mono_metadata_parse_type:
1029 * @type: MonoType to be filled in with the return value
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).
1036 * This routine is used by mono_metadata_parse_type and
1037 * mono_metadata_parse_field_type
1039 * This extracts a Type as specified in Partition II (22.2.12)
1042 do_mono_metadata_parse_type (MonoType *type, metadata_t *m, const char *ptr, const char **rptr)
1044 type->type = mono_metadata_decode_value (ptr, &ptr);
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:
1064 case ELEMENT_TYPE_VALUETYPE:
1065 case ELEMENT_TYPE_CLASS:
1066 type->data.token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
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;
1075 type->custom_mod = 1;
1076 /* count the modifiers */
1077 while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
1079 type->data.mtype = mtype = g_malloc0(sizeof(MonoModifiedType)+(count-MONO_ZERO_LEN_ARRAY)*sizeof(MonoCustomMod));
1080 mtype->num_modifiers = count;
1083 /* save them this time */
1084 while (mono_metadata_parse_custom_mod (m, &(mtype->modifiers[count]), ptr, &ptr))
1086 /* FIXME: mono_metadata_decode_value ... */
1087 if (*ptr == ELEMENT_TYPE_VOID) {
1091 mtype->type = mono_metadata_parse_type (m, ptr, &ptr);
1094 /* FIXME: mono_metadata_decode_value ... */
1095 if (*ptr == ELEMENT_TYPE_VOID) {
1096 type->data.type = NULL;
1099 type->data.type = mono_metadata_parse_type (m, ptr, &ptr);
1103 case ELEMENT_TYPE_FNPTR:
1104 type->data.method = mono_metadata_parse_method_signature (m, 0, ptr, &ptr);
1106 case ELEMENT_TYPE_ARRAY:
1107 type->data.array = mono_metadata_parse_array (m, ptr, &ptr);
1110 g_error ("type 0x%02x not handled in mono_metadata_parse_type", type->type);
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
1123 * Returns: A MonoType structure that has the parsed information
1124 * from the type stored at @ptr in the metadata table @m.
1127 mono_metadata_parse_type (metadata_t *m, const char *ptr, const char **rptr)
1129 /* should probably be allocated in a memchunk */
1130 MonoType *type = g_new0(MonoType, 1);
1132 do_mono_metadata_parse_type (type, m, ptr, rptr);
1138 mono_metadata_free_type (MonoType *type)
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);
1151 case ELEMENT_TYPE_FNPTR:
1152 mono_metadata_free_method_signature (type->data.method);
1154 case ELEMENT_TYPE_ARRAY:
1155 mono_metadata_free_array (type->data.array);
1162 hex_dump (const char *buffer, int base, int count)
1164 int show_header = 1;
1172 for (i = 0; i < count; i++){
1175 printf ("\n0x%08x: ", (unsigned char) base + i);
1177 printf ("%02x ", (unsigned char) (buffer [i]));
1183 * @mh: The Method header
1184 * @ptr: Points to the beginning of the Section Data (25.3)
1187 parse_section_data (MonoMetaMethodHeader *mh, const unsigned char *ptr)
1189 unsigned char sect_data_flags;
1190 const unsigned char *sptr;
1192 guint32 sect_data_len;
1195 /* align on 32-bit boundary */
1196 /* FIXME: not 64-bit clean code */
1197 sptr = ptr = dword_align (ptr);
1198 sect_data_flags = *ptr;
1201 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
1203 sect_data_len = (ptr [0] << 16) | (ptr [1] << 8) | ptr [0];
1206 sect_data_len = ptr [0];
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);
1217 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
1218 const unsigned char *p = dword_align (ptr);
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];
1226 /* we could memcpy and byteswap */
1227 ec->flags = read32 (p);
1229 ec->try_offset = read32 (p);
1231 ec->try_len = read32 (p);
1233 ec->handler_offset = read32 (p);
1235 ec->handler_len = read32 (p);
1237 ec->token_or_filter = read32 (p);
1240 ec->flags = read16 (p);
1242 ec->try_offset = read16 (p);
1246 ec->handler_offset = read16 (p);
1248 ec->handler_len = *p;
1250 ec->token_or_filter = read32 (p);
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); */
1256 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
1257 ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
1263 MonoMetaMethodHeader *
1264 mono_metadata_parse_mh (metadata_t *m, const char *ptr)
1266 MonoMetaMethodHeader *mh;
1267 unsigned char flags = *(unsigned char *) ptr;
1268 unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
1272 g_return_val_if_fail (ptr != NULL, NULL);
1274 mh = g_new0 (MonoMetaMethodHeader, 1);
1276 case METHOD_HEADER_TINY_FORMAT:
1279 mh->local_var_sig_tok = 0;
1280 mh->code_size = flags >> 2;
1284 case METHOD_HEADER_TINY_FORMAT1:
1287 mh->local_var_sig_tok = 0;
1290 // The spec claims 3 bits, but the Beta2 is
1293 mh->code_size = flags >> 2;
1297 case METHOD_HEADER_FAT_FORMAT:
1298 fat_flags = read16 (ptr);
1300 hsize = (fat_flags >> 12) & 0xf;
1301 mh->max_stack = *(guint16 *) ptr;
1303 mh->code_size = *(guint32 *) ptr;
1305 mh->local_var_sig_tok = *(guint32 *) ptr;
1308 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
1309 mh->init_locals = 1;
1311 mh->init_locals = 0;
1315 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
1319 * There are more sections
1321 ptr = mh->code + mh->code_size;
1323 parse_section_data (mh, (const unsigned char*)ptr);
1331 if (mh->local_var_sig_tok) {
1332 metadata_tableinfo_t *t = &m->tables [META_TABLE_STANDALONESIG];
1335 int len=0, i, bsize;
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);
1341 g_warning ("wrong signature for locals blob");
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) {
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) {
1353 val = mono_metadata_decode_blob_size (ptr, &ptr);
1355 if (val == ELEMENT_TYPE_BYREF) {
1358 mh->locals [i] = mono_metadata_parse_type (m, p, &ptr);
1365 mono_metadata_free_mh (MonoMetaMethodHeader *mh)
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);
1376 * mono_metadata_parse_field_type:
1377 * @m: metadata context to extract information from
1378 * @ptr: pointer to the field signature
1380 * Parses the field signature, and returns the type information for it.
1382 * Returns: The MonoFieldType that was extracted from @ptr.
1385 mono_metadata_parse_field_type (metadata_t *m, const char *ptr, const char **rptr)
1387 return mono_metadata_parse_param (m, 0, ptr, rptr);
1391 * mono_metadata_token_from_dor:
1392 * @dor_token: A TypeDefOrRef coded index
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.
1398 * Returns: an expanded token
1401 mono_metadata_token_from_dor (guint32 dor_index)
1405 table = dor_index & 0x03;
1406 idx = dor_index >> 2;
1409 case 0: /* TypeDef */
1410 return TOKEN_TYPE_TYPE_DEF | idx;
1412 case 1: /* TypeRef */
1413 return TOKEN_TYPE_TYPE_REF | idx;
1415 case 2: /* TypeSpec */
1416 return TOKEN_TYPE_TYPE_SPEC | idx;
1419 g_assert_not_reached ();
1426 * We use this to pass context information to the typedef locator
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 */
1436 #define CSIZE(x) (sizeof (x) / 4)
1439 typedef_locator (const void *a, const void *b)
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];
1446 mono_metadata_decode_row (loc->t, typedef_index, cols, CSIZE (cols));
1448 if (loc->idx < cols [loc->col_idx])
1452 * Need to check that the next row is valid.
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])
1459 if (cols [loc->col_idx] == cols_next [loc->col_idx])
1463 loc->result = typedef_index;
1468 #define FIELD_INDEX 4
1469 #define METHOD_INDEX 5
1472 mono_metadata_typedef_from_field (metadata_t *meta, guint32 index)
1474 metadata_tableinfo_t *tdef = &meta->tables [META_TABLE_TYPEDEF];
1477 loc.idx = mono_metadata_token_index (index);
1478 loc.col_idx = FIELD_INDEX;
1481 if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1482 g_assert_not_reached ();
1484 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1485 return loc.result + 1;
1489 mono_metadata_typedef_from_method (metadata_t *meta, guint32 index)
1491 metadata_tableinfo_t *tdef = &meta->tables [META_TABLE_TYPEDEF];
1494 loc.idx = mono_metadata_token_index (index);
1495 loc.col_idx = METHOD_INDEX;
1498 if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
1499 g_assert_not_reached ();
1501 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
1502 return loc.result + 1;