2 * metadata.c: Routines for accessing the metadata
5 * Miguel de Icaza (miguel@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2001-2002 Ximian, Inc.
17 #include "tabledefs.h"
18 #include "mono-endian.h"
20 #include "tokentype.h"
21 #include "metadata-internals.h"
22 #include "class-internals.h"
25 static gboolean
do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
26 const char *ptr
, const char **rptr
);
28 static gboolean
do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
);
29 static gboolean
mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
);
30 static gboolean
mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
);
31 static gboolean
_mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
,
32 gboolean signature_only
);
33 static void free_generic_inst (MonoGenericInst
*ginst
);
34 static void free_generic_class (MonoGenericClass
*ginst
);
35 static void free_inflated_method (MonoMethodInflated
*method
);
38 * This enumeration is used to describe the data types in the metadata
49 /* Index into Blob heap */
52 /* Index into String heap */
58 /* Pointer into a table */
61 /* HasConstant:Parent pointer (Param, Field or Property) */
64 /* HasCustomAttribute index. Indexes any table except CustomAttribute */
67 /* CustomAttributeType encoded index */
70 /* HasDeclSecurity index: TypeDef Method or Assembly */
73 /* Implementation coded index: File, Export AssemblyRef */
76 /* HasFieldMarshal coded index: Field or Param table */
79 /* MemberForwardedIndex: Field or Method */
82 /* TypeDefOrRef coded index: typedef, typeref, typespec */
85 /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
88 /* MethodDefOrRef coded index: Method or Member Ref table */
91 /* HasSemantic coded index: Event or Property */
94 /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
98 const static unsigned char TableSchemas
[] = {
99 #define ASSEMBLY_SCHEMA_OFFSET 0
100 MONO_MT_UINT32
, /* "HashId" }, */
101 MONO_MT_UINT16
, /* "Major" }, */
102 MONO_MT_UINT16
, /* "Minor" }, */
103 MONO_MT_UINT16
, /* "BuildNumber" }, */
104 MONO_MT_UINT16
, /* "RevisionNumber" }, */
105 MONO_MT_UINT32
, /* "Flags" }, */
106 MONO_MT_BLOB_IDX
, /* "PublicKey" }, */
107 MONO_MT_STRING_IDX
, /* "Name" }, */
108 MONO_MT_STRING_IDX
, /* "Culture" }, */
111 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
112 MONO_MT_UINT32
, /* "OSPlatformID" }, */
113 MONO_MT_UINT32
, /* "OSMajor" }, */
114 MONO_MT_UINT32
, /* "OSMinor" }, */
117 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
118 MONO_MT_UINT32
, /* "Processor" }, */
121 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
122 MONO_MT_UINT16
, /* "Major" }, */
123 MONO_MT_UINT16
, /* "Minor" }, */
124 MONO_MT_UINT16
, /* "Build" }, */
125 MONO_MT_UINT16
, /* "Revision" }, */
126 MONO_MT_UINT32
, /* "Flags" }, */
127 MONO_MT_BLOB_IDX
, /* "PublicKeyOrToken" }, */
128 MONO_MT_STRING_IDX
, /* "Name" }, */
129 MONO_MT_STRING_IDX
, /* "Culture" }, */
130 MONO_MT_BLOB_IDX
, /* "HashValue" }, */
133 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
134 MONO_MT_UINT32
, /* "OSPlatformID" }, */
135 MONO_MT_UINT32
, /* "OSMajorVersion" }, */
136 MONO_MT_UINT32
, /* "OSMinorVersion" }, */
137 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
140 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
141 MONO_MT_UINT32
, /* "Processor" }, */
142 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
145 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
146 MONO_MT_UINT16
, /* "PackingSize" }, */
147 MONO_MT_UINT32
, /* "ClassSize" }, */
148 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
151 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
152 MONO_MT_UINT8
, /* "Type" }, */
153 MONO_MT_UINT8
, /* "PaddingZero" }, */
154 MONO_MT_CONST_IDX
, /* "Parent" }, */
155 MONO_MT_BLOB_IDX
, /* "Value" }, */
158 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
159 MONO_MT_HASCAT_IDX
, /* "Parent" }, */
160 MONO_MT_CAT_IDX
, /* "Type" }, */
161 MONO_MT_BLOB_IDX
, /* "Value" }, */
164 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
165 MONO_MT_UINT16
, /* "Action" }, */
166 MONO_MT_HASDEC_IDX
, /* "Parent" }, */
167 MONO_MT_BLOB_IDX
, /* "PermissionSet" }, */
170 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
171 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
172 MONO_MT_TABLE_IDX
, /* "EventList:Event" }, */
175 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
176 MONO_MT_UINT16
, /* "EventFlags#EventAttribute" }, */
177 MONO_MT_STRING_IDX
, /* "Name" }, */
178 MONO_MT_TABLE_IDX
, /* "EventType" }, TypeDef or TypeRef */
181 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
182 MONO_MT_TABLE_IDX
, /* "Event" }, */
185 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
186 MONO_MT_UINT32
, /* "Flags" }, */
187 MONO_MT_TABLE_IDX
, /* "TypeDefId" }, */
188 MONO_MT_STRING_IDX
, /* "TypeName" }, */
189 MONO_MT_STRING_IDX
, /* "TypeNameSpace" }, */
190 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
193 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
194 MONO_MT_UINT16
, /* "Flags" }, */
195 MONO_MT_STRING_IDX
, /* "Name" }, */
196 MONO_MT_BLOB_IDX
, /* "Signature" }, */
199 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
200 MONO_MT_UINT32
, /* "Offset" }, */
201 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
204 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
205 MONO_MT_HFM_IDX
, /* "Parent" }, */
206 MONO_MT_BLOB_IDX
, /* "NativeType" }, */
209 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
210 MONO_MT_UINT32
, /* "RVA" }, */
211 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
214 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
215 MONO_MT_TABLE_IDX
, /* "Field" }, */
218 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
219 MONO_MT_UINT32
, /* "Flags" }, */
220 MONO_MT_STRING_IDX
, /* "Name" }, */
221 MONO_MT_BLOB_IDX
, /* "Value" }, */
224 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
225 MONO_MT_UINT16
, /* "MappingFlag" }, */
226 MONO_MT_MF_IDX
, /* "MemberForwarded" }, */
227 MONO_MT_STRING_IDX
, /* "ImportName" }, */
228 MONO_MT_TABLE_IDX
, /* "ImportScope:ModuleRef" }, */
231 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
232 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
233 MONO_MT_TDOR_IDX
, /* "Interface=TypeDefOrRef" }, */
236 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
237 MONO_MT_UINT32
, /* "Offset" }, */
238 MONO_MT_UINT32
, /* "Flags" }, */
239 MONO_MT_STRING_IDX
, /* "Name" }, */
240 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
243 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
244 MONO_MT_MRP_IDX
, /* "Class" }, */
245 MONO_MT_STRING_IDX
, /* "Name" }, */
246 MONO_MT_BLOB_IDX
, /* "Signature" }, */
249 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
250 MONO_MT_UINT32
, /* "RVA" }, */
251 MONO_MT_UINT16
, /* "ImplFlags#MethodImplAttributes" }, */
252 MONO_MT_UINT16
, /* "Flags#MethodAttribute" }, */
253 MONO_MT_STRING_IDX
, /* "Name" }, */
254 MONO_MT_BLOB_IDX
, /* "Signature" }, */
255 MONO_MT_TABLE_IDX
, /* "ParamList:Param" }, */
258 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
259 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
260 MONO_MT_MDOR_IDX
, /* "MethodBody" }, */
261 MONO_MT_MDOR_IDX
, /* "MethodDeclaration" }, */
264 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
265 MONO_MT_UINT16
, /* "MethodSemantic" }, */
266 MONO_MT_TABLE_IDX
, /* "Method:Method" }, */
267 MONO_MT_HS_IDX
, /* "Association" }, */
270 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
271 MONO_MT_TABLE_IDX
, /* "Method" }, */
274 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
275 MONO_MT_UINT16
, /* "Generation" }, */
276 MONO_MT_STRING_IDX
, /* "Name" }, */
277 MONO_MT_GUID_IDX
, /* "MVID" }, */
278 MONO_MT_GUID_IDX
, /* "EncID" }, */
279 MONO_MT_GUID_IDX
, /* "EncBaseID" }, */
282 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
283 MONO_MT_STRING_IDX
, /* "Name" }, */
286 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
287 MONO_MT_TABLE_IDX
, /* "NestedClass:TypeDef" }, */
288 MONO_MT_TABLE_IDX
, /* "EnclosingClass:TypeDef" }, */
291 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
292 MONO_MT_UINT16
, /* "Flags" }, */
293 MONO_MT_UINT16
, /* "Sequence" }, */
294 MONO_MT_STRING_IDX
, /* "Name" }, */
297 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
298 MONO_MT_TABLE_IDX
, /* "Param" }, */
301 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
302 MONO_MT_UINT16
, /* "Flags" }, */
303 MONO_MT_STRING_IDX
, /* "Name" }, */
304 MONO_MT_BLOB_IDX
, /* "Type" }, */
307 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
308 MONO_MT_TABLE_IDX
, /* "Property" }, */
311 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
312 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
313 MONO_MT_TABLE_IDX
, /* "PropertyList:Property" }, */
316 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
317 MONO_MT_BLOB_IDX
, /* "Signature" }, */
320 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
321 MONO_MT_UINT32
, /* "Flags" }, */
322 MONO_MT_STRING_IDX
, /* "Name" }, */
323 MONO_MT_STRING_IDX
, /* "Namespace" }, */
324 MONO_MT_TDOR_IDX
, /* "Extends" }, */
325 MONO_MT_TABLE_IDX
, /* "FieldList:Field" }, */
326 MONO_MT_TABLE_IDX
, /* "MethodList:Method" }, */
329 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
330 MONO_MT_RS_IDX
, /* "ResolutionScope=ResolutionScope" }, */
331 MONO_MT_STRING_IDX
, /* "Name" }, */
332 MONO_MT_STRING_IDX
, /* "Namespace" }, */
335 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
336 MONO_MT_BLOB_IDX
, /* "Signature" }, */
339 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
340 MONO_MT_UINT16
, /* "Number" }, */
341 MONO_MT_UINT16
, /* "Flags" }, */
342 MONO_MT_TABLE_IDX
, /* "Owner" }, TypeDef or MethodDef */
343 MONO_MT_STRING_IDX
, /* "Name" }, */
346 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
347 MONO_MT_MDOR_IDX
, /* "Method" }, */
348 MONO_MT_BLOB_IDX
, /* "Signature" }, */
351 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
352 MONO_MT_TABLE_IDX
, /* "GenericParam" }, */
353 MONO_MT_TDOR_IDX
, /* "Constraint" }, */
356 #define NULL_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
360 /* Must be the same order as MONO_TABLE_* */
361 const static unsigned char
362 table_description
[] = {
363 MODULE_SCHEMA_OFFSET
,
364 TYPEREF_SCHEMA_OFFSET
,
365 TYPEDEF_SCHEMA_OFFSET
,
366 FIELD_POINTER_SCHEMA_OFFSET
,
368 METHOD_POINTER_SCHEMA_OFFSET
,
369 METHOD_SCHEMA_OFFSET
,
370 PARAM_POINTER_SCHEMA_OFFSET
,
372 IFACEMAP_SCHEMA_OFFSET
,
373 MEMBERREF_SCHEMA_OFFSET
, /* 0xa */
374 CONSTANT_SCHEMA_OFFSET
,
375 CUSTOM_ATTR_SCHEMA_OFFSET
,
376 FIELD_MARSHAL_SCHEMA_OFFSET
,
377 DECL_SEC_SCHEMA_OFFSET
,
378 CLASS_LAYOUT_SCHEMA_OFFSET
,
379 FIELD_LAYOUT_SCHEMA_OFFSET
, /* 0x10 */
380 STDALON_SIG_SCHEMA_OFFSET
,
381 EVENTMAP_SCHEMA_OFFSET
,
382 EVENT_POINTER_SCHEMA_OFFSET
,
384 PROPERTY_MAP_SCHEMA_OFFSET
,
385 PROPERTY_POINTER_SCHEMA_OFFSET
,
386 PROPERTY_SCHEMA_OFFSET
,
387 METHOD_SEMA_SCHEMA_OFFSET
,
388 METHOD_IMPL_SCHEMA_OFFSET
,
389 MODULEREF_SCHEMA_OFFSET
, /* 0x1a */
390 TYPESPEC_SCHEMA_OFFSET
,
391 IMPLMAP_SCHEMA_OFFSET
,
392 FIELD_RVA_SCHEMA_OFFSET
,
395 ASSEMBLY_SCHEMA_OFFSET
, /* 0x20 */
396 ASSEMBLYPROC_SCHEMA_OFFSET
,
397 ASSEMBLYOS_SCHEMA_OFFSET
,
398 ASSEMBLYREF_SCHEMA_OFFSET
,
399 ASSEMBLYREFPROC_SCHEMA_OFFSET
,
400 ASSEMBLYREFOS_SCHEMA_OFFSET
,
402 EXPORTED_TYPE_SCHEMA_OFFSET
,
403 MANIFEST_SCHEMA_OFFSET
,
404 NESTED_CLASS_SCHEMA_OFFSET
,
405 GENPARAM_SCHEMA_OFFSET
, /* 0x2a */
406 METHOD_SPEC_SCHEMA_OFFSET
,
407 GEN_CONSTRAINT_SCHEMA_OFFSET
410 #ifdef HAVE_ARRAY_ELEM_INIT
411 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
412 #define MSGSTRFIELD1(line) str##line
413 static const struct msgstr_t
{
414 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
415 #include "mono/cil/tables.def"
418 #define TABLEDEF(a,b) b,
419 #include "mono/cil/tables.def"
422 static const gint16 tableidx
[] = {
423 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
424 #include "mono/cil/tables.def"
429 #define TABLEDEF(a,b) b,
430 static const char* const
431 mono_tables_names
[] = {
432 #include "mono/cil/tables.def"
438 /* Auxiliary structure used for caching inflated signatures */
440 MonoMethodSignature
*sig
;
441 MonoGenericContext context
;
442 } MonoInflatedMethodSignature
;
445 * mono_image_alloc_lock:
447 * Same as mono_image_alloc, but do the locking as well.
448 * LOCKING: Acquires the loader lock.
451 mono_image_alloc_lock (MonoImage
*image
, guint size
)
456 res
= mono_image_alloc (image
, size
);
457 mono_loader_unlock ();
463 * mono_image_alloc0_lock:
465 * Same as mono_image_alloc, but do the locking as well.
466 * LOCKING: Acquires the loader lock.
469 mono_image_alloc0_lock (MonoImage
*image
, guint size
)
474 res
= mono_image_alloc0 (image
, size
);
475 mono_loader_unlock ();
481 * mono_meta_table_name:
482 * @table: table index
484 * Returns the name of the given ECMA metadata logical format table
485 * as described in ECMA 335, Partition II, Section 22.
487 * Returns: the name for the @table index
490 mono_meta_table_name (int table
)
492 if ((table
< 0) || (table
> MONO_TABLE_LAST
))
495 #ifdef HAVE_ARRAY_ELEM_INIT
496 return (const char*)&tablestr
+ tableidx
[table
];
498 return mono_tables_names
[table
];
502 /* The guy who wrote the spec for this should not be allowed near a
505 If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
506 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
507 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
508 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
509 inverse of this mapping.
512 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
513 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
515 /* Reference: Partition II - 23.2.6 */
517 * mono_metadata_compute_size:
518 * @meta: metadata context
519 * @tableindex: metadata table number
520 * @result_bitfield: pointer to guint32 where to store additional info
522 * mono_metadata_compute_size() computes the lenght in bytes of a single
523 * row in a metadata table. The size of each column is encoded in the
524 * @result_bitfield return value along with the number of columns in the table.
525 * the resulting bitfield should be handed to the mono_metadata_table_size()
526 * and mono_metadata_table_count() macros.
527 * This is a Mono runtime internal only function.
530 mono_metadata_compute_size (MonoImage
*meta
, int tableindex
, guint32
*result_bitfield
)
532 guint32 bitfield
= 0;
533 int size
= 0, field_size
= 0;
536 const unsigned char *description
= TableSchemas
+ table_description
[tableindex
];
538 for (i
= 0; (code
= description
[i
]) != MONO_MT_END
; i
++){
541 field_size
= 4; break;
544 field_size
= 2; break;
547 field_size
= 1; break;
549 case MONO_MT_BLOB_IDX
:
550 field_size
= meta
->idx_blob_wide
? 4 : 2; break;
552 case MONO_MT_STRING_IDX
:
553 field_size
= meta
->idx_string_wide
? 4 : 2; break;
555 case MONO_MT_GUID_IDX
:
556 field_size
= meta
->idx_guid_wide
? 4 : 2; break;
558 case MONO_MT_TABLE_IDX
:
559 /* Uhm, a table index can point to other tables besides the current one
560 * so, it's not correct to use the rowcount of the current table to
561 * get the size for this column - lupus
563 switch (tableindex
) {
564 case MONO_TABLE_ASSEMBLYREFOS
:
566 field_size
= idx_size (MONO_TABLE_ASSEMBLYREF
); break;
567 case MONO_TABLE_ASSEMBLYPROCESSOR
:
569 field_size
= idx_size (MONO_TABLE_ASSEMBLYREF
); break;
570 case MONO_TABLE_CLASSLAYOUT
:
572 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
573 case MONO_TABLE_EVENTMAP
:
574 g_assert (i
== 0 || i
== 1);
575 field_size
= i
? idx_size (MONO_TABLE_EVENT
):
576 idx_size(MONO_TABLE_TYPEDEF
);
578 case MONO_TABLE_EVENT
:
580 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
, meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
581 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
582 /*This is a coded token for 3 tables, so takes 2 bits */
583 field_size
= rtsize (n
, 16 - MONO_TYPEDEFORREF_BITS
);
585 case MONO_TABLE_EVENT_POINTER
:
587 field_size
= idx_size (MONO_TABLE_EVENT
); break;
588 case MONO_TABLE_EXPORTEDTYPE
:
590 /* the index is in another metadata file, so it must be 4 */
591 field_size
= 4; break;
592 case MONO_TABLE_FIELDLAYOUT
:
594 field_size
= idx_size (MONO_TABLE_FIELD
); break;
595 case MONO_TABLE_FIELDRVA
:
597 field_size
= idx_size (MONO_TABLE_FIELD
); break;
598 case MONO_TABLE_FIELD_POINTER
:
600 field_size
= idx_size (MONO_TABLE_FIELD
); break;
601 case MONO_TABLE_IMPLMAP
:
603 field_size
= idx_size (MONO_TABLE_MODULEREF
); break;
604 case MONO_TABLE_INTERFACEIMPL
:
606 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
607 case MONO_TABLE_METHOD
:
609 field_size
= idx_size (MONO_TABLE_PARAM
); break;
610 case MONO_TABLE_METHODIMPL
:
612 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
613 case MONO_TABLE_METHODSEMANTICS
:
615 field_size
= idx_size (MONO_TABLE_METHOD
); break;
616 case MONO_TABLE_METHOD_POINTER
:
618 field_size
= idx_size (MONO_TABLE_METHOD
); break;
619 case MONO_TABLE_NESTEDCLASS
:
620 g_assert (i
== 0 || i
== 1);
621 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
622 case MONO_TABLE_PARAM_POINTER
:
624 field_size
= idx_size (MONO_TABLE_PARAM
); break;
625 case MONO_TABLE_PROPERTYMAP
:
626 g_assert (i
== 0 || i
== 1);
627 field_size
= i
? idx_size (MONO_TABLE_PROPERTY
):
628 idx_size(MONO_TABLE_TYPEDEF
);
630 case MONO_TABLE_PROPERTY_POINTER
:
632 field_size
= idx_size (MONO_TABLE_PROPERTY
); break;
633 case MONO_TABLE_TYPEDEF
:
634 g_assert (i
== 4 || i
== 5);
635 field_size
= i
== 4 ? idx_size (MONO_TABLE_FIELD
):
636 idx_size(MONO_TABLE_METHOD
);
638 case MONO_TABLE_GENERICPARAM
:
639 g_assert (i
== 2 || i
== 4 || i
== 5);
641 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
, meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
642 /*This is a coded token for 2 tables, so takes 1 bit */
643 field_size
= rtsize (n
, 16 - MONO_TYPEORMETHOD_BITS
);
645 field_size
= idx_size (MONO_TABLE_TYPEDEF
);
647 field_size
= idx_size (MONO_TABLE_TYPEDEF
);
650 case MONO_TABLE_GENERICPARAMCONSTRAINT
:
652 field_size
= idx_size (MONO_TABLE_GENERICPARAM
);
656 g_assert_not_reached ();
661 * HasConstant: ParamDef, FieldDef, Property
663 case MONO_MT_CONST_IDX
:
664 n
= MAX (meta
->tables
[MONO_TABLE_PARAM
].rows
,
665 meta
->tables
[MONO_TABLE_FIELD
].rows
);
666 n
= MAX (n
, meta
->tables
[MONO_TABLE_PROPERTY
].rows
);
668 /* 2 bits to encode tag */
669 field_size
= rtsize (n
, 16-2);
673 * HasCustomAttribute: points to any table but
676 case MONO_MT_HASCAT_IDX
:
678 * We believe that since the signature and
679 * permission are indexing the Blob heap,
680 * we should consider the blob size first
682 /* I'm not a believer - lupus
683 if (meta->idx_blob_wide){
688 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
,
689 meta
->tables
[MONO_TABLE_FIELD
].rows
);
690 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
691 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
692 n
= MAX (n
, meta
->tables
[MONO_TABLE_PARAM
].rows
);
693 n
= MAX (n
, meta
->tables
[MONO_TABLE_INTERFACEIMPL
].rows
);
694 n
= MAX (n
, meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
695 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULE
].rows
);
696 n
= MAX (n
, meta
->tables
[MONO_TABLE_DECLSECURITY
].rows
);
697 n
= MAX (n
, meta
->tables
[MONO_TABLE_PROPERTY
].rows
);
698 n
= MAX (n
, meta
->tables
[MONO_TABLE_EVENT
].rows
);
699 n
= MAX (n
, meta
->tables
[MONO_TABLE_STANDALONESIG
].rows
);
700 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
701 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
702 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLY
].rows
);
703 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
704 n
= MAX (n
, meta
->tables
[MONO_TABLE_FILE
].rows
);
705 n
= MAX (n
, meta
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
);
706 n
= MAX (n
, meta
->tables
[MONO_TABLE_MANIFESTRESOURCE
].rows
);
708 /* 5 bits to encode */
709 field_size
= rtsize (n
, 16-5);
713 * CustomAttributeType: TypeDef, TypeRef, MethodDef,
714 * MemberRef and String.
716 case MONO_MT_CAT_IDX
:
717 /* String is a heap, if it is wide, we know the size */
719 if (meta->idx_string_wide){
724 n
= MAX (meta
->tables
[MONO_TABLE_TYPEREF
].rows
,
725 meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
726 n
= MAX (n
, meta
->tables
[MONO_TABLE_METHOD
].rows
);
727 n
= MAX (n
, meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
729 /* 3 bits to encode */
730 field_size
= rtsize (n
, 16-3);
734 * HasDeclSecurity: Typedef, MethodDef, Assembly
736 case MONO_MT_HASDEC_IDX
:
737 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
738 meta
->tables
[MONO_TABLE_METHOD
].rows
);
739 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLY
].rows
);
741 /* 2 bits to encode */
742 field_size
= rtsize (n
, 16-2);
746 * Implementation: File, AssemblyRef, ExportedType
748 case MONO_MT_IMPL_IDX
:
749 n
= MAX (meta
->tables
[MONO_TABLE_FILE
].rows
,
750 meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
751 n
= MAX (n
, meta
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
);
753 /* 2 bits to encode tag */
754 field_size
= rtsize (n
, 16-2);
758 * HasFieldMarshall: FieldDef, ParamDef
760 case MONO_MT_HFM_IDX
:
761 n
= MAX (meta
->tables
[MONO_TABLE_FIELD
].rows
,
762 meta
->tables
[MONO_TABLE_PARAM
].rows
);
764 /* 1 bit used to encode tag */
765 field_size
= rtsize (n
, 16-1);
769 * MemberForwarded: FieldDef, MethodDef
772 n
= MAX (meta
->tables
[MONO_TABLE_FIELD
].rows
,
773 meta
->tables
[MONO_TABLE_METHOD
].rows
);
775 /* 1 bit used to encode tag */
776 field_size
= rtsize (n
, 16-1);
780 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
782 * It is TypeDef, _TypeRef_, TypeSpec, instead.
784 case MONO_MT_TDOR_IDX
:
785 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
786 meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
787 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
789 /* 2 bits to encode */
790 field_size
= rtsize (n
, 16-2);
794 * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
796 case MONO_MT_MRP_IDX
:
797 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
798 meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
799 n
= MAX (n
, meta
->tables
[MONO_TABLE_METHOD
].rows
);
800 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
801 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
802 n
= MAX (n
, meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
804 /* 3 bits to encode */
805 field_size
= rtsize (n
, 16 - 3);
809 * MethodDefOrRef: MethodDef, MemberRef
811 case MONO_MT_MDOR_IDX
:
812 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
,
813 meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
815 /* 1 bit used to encode tag */
816 field_size
= rtsize (n
, 16-1);
820 * HasSemantics: Property, Event
823 n
= MAX (meta
->tables
[MONO_TABLE_PROPERTY
].rows
,
824 meta
->tables
[MONO_TABLE_EVENT
].rows
);
826 /* 1 bit used to encode tag */
827 field_size
= rtsize (n
, 16-1);
831 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
834 n
= MAX (meta
->tables
[MONO_TABLE_MODULE
].rows
,
835 meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
836 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
837 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
839 /* 2 bits used to encode tag (ECMA spec claims 3) */
840 field_size
= rtsize (n
, 16 - 2);
845 * encode field size as follows (we just need to
852 bitfield
|= (field_size
-1) << shift
;
855 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
858 *result_bitfield
= (i
<< 24) | bitfield
;
863 * mono_metadata_compute_table_bases:
864 * @meta: metadata context to compute table values
866 * Computes the table bases for the metadata structure.
867 * This is an internal function used by the image loader code.
870 mono_metadata_compute_table_bases (MonoImage
*meta
)
873 const char *base
= meta
->tables_base
;
875 for (i
= 0; i
< MONO_TABLE_NUM
; i
++) {
876 MonoTableInfo
*table
= &meta
->tables
[i
];
877 if (table
->rows
== 0)
880 table
->row_size
= mono_metadata_compute_size (meta
, i
, &table
->size_bitfield
);
882 base
+= table
->rows
* table
->row_size
;
887 * mono_metadata_locate:
888 * @meta: metadata context
889 * @table: table code.
890 * @idx: index of element to retrieve from @table.
892 * Returns: a pointer to the @idx element in the metadata table
893 * whose code is @table.
896 mono_metadata_locate (MonoImage
*meta
, int table
, int idx
)
898 /* idx == 0 refers always to NULL */
899 g_return_val_if_fail (idx
> 0 && idx
<= meta
->tables
[table
].rows
, "");
901 return meta
->tables
[table
].base
+ (meta
->tables
[table
].row_size
* (idx
- 1));
905 * mono_metadata_locate_token:
906 * @meta: metadata context
907 * @token: metadata token
909 * Returns: a pointer to the data in the metadata represented by the
913 mono_metadata_locate_token (MonoImage
*meta
, guint32 token
)
915 return mono_metadata_locate (meta
, token
>> 24, token
& 0xffffff);
919 * mono_metadata_string_heap:
920 * @meta: metadata context
921 * @index: index into the string heap.
923 * Returns: an in-memory pointer to the @index in the string heap.
926 mono_metadata_string_heap (MonoImage
*meta
, guint32 index
)
928 g_return_val_if_fail (index
< meta
->heap_strings
.size
, "");
929 return meta
->heap_strings
.data
+ index
;
933 * mono_metadata_user_string:
934 * @meta: metadata context
935 * @index: index into the user string heap.
937 * Returns: an in-memory pointer to the @index in the user string heap ("#US").
940 mono_metadata_user_string (MonoImage
*meta
, guint32 index
)
942 g_return_val_if_fail (index
< meta
->heap_us
.size
, "");
943 return meta
->heap_us
.data
+ index
;
947 * mono_metadata_blob_heap:
948 * @meta: metadata context
949 * @index: index into the blob.
951 * Returns: an in-memory pointer to the @index in the Blob heap.
954 mono_metadata_blob_heap (MonoImage
*meta
, guint32 index
)
956 g_return_val_if_fail (index
< meta
->heap_blob
.size
, "");
957 return meta
->heap_blob
.data
+ index
;
961 * mono_metadata_guid_heap:
962 * @meta: metadata context
963 * @index: index into the guid heap.
965 * Returns: an in-memory pointer to the @index in the guid heap.
968 mono_metadata_guid_heap (MonoImage
*meta
, guint32 index
)
971 index
*= 16; /* adjust for guid size and 1-based index */
972 g_return_val_if_fail (index
< meta
->heap_guid
.size
, "");
973 return meta
->heap_guid
.data
+ index
;
976 static const unsigned char *
977 dword_align (const unsigned char *ptr
)
979 #if SIZEOF_VOID_P == 8
980 return (const unsigned char *) (((guint64
) (ptr
+ 3)) & ~3);
982 return (const unsigned char *) (((guint32
) (ptr
+ 3)) & ~3);
987 * mono_metadata_decode_row:
988 * @t: table to extract information from.
989 * @idx: index in table.
990 * @res: array of @res_size cols to store the results in
992 * This decompresses the metadata element @idx in table @t
993 * into the guint32 @res array that has res_size elements
996 mono_metadata_decode_row (const MonoTableInfo
*t
, int idx
, guint32
*res
, int res_size
)
998 guint32 bitfield
= t
->size_bitfield
;
999 int i
, count
= mono_metadata_table_count (bitfield
);
1002 g_assert (idx
< t
->rows
);
1003 data
= t
->base
+ idx
* t
->row_size
;
1005 g_assert (res_size
== count
);
1007 for (i
= 0; i
< count
; i
++) {
1008 int n
= mono_metadata_table_size (bitfield
, i
);
1012 res
[i
] = *data
; break;
1014 res
[i
] = read16 (data
); break;
1016 res
[i
] = read32 (data
); break;
1018 g_assert_not_reached ();
1025 * mono_metadata_decode_row_col:
1026 * @t: table to extract information from.
1027 * @idx: index for row in table.
1028 * @col: column in the row.
1030 * This function returns the value of column @col from the @idx
1031 * row in the table @t.
1034 mono_metadata_decode_row_col (const MonoTableInfo
*t
, int idx
, guint col
)
1036 guint32 bitfield
= t
->size_bitfield
;
1038 register const char *data
;
1041 g_assert (idx
< t
->rows
);
1042 g_assert (col
< mono_metadata_table_count (bitfield
));
1043 data
= t
->base
+ idx
* t
->row_size
;
1045 n
= mono_metadata_table_size (bitfield
, 0);
1046 for (i
= 0; i
< col
; ++i
) {
1048 n
= mono_metadata_table_size (bitfield
, i
+ 1);
1054 return read16 (data
);
1056 return read32 (data
);
1058 g_assert_not_reached ();
1064 * mono_metadata_decode_blob_size:
1065 * @ptr: pointer to a blob object
1066 * @rptr: the new position of the pointer
1068 * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
1070 * Returns: the size of the blob object
1073 mono_metadata_decode_blob_size (const char *xptr
, const char **rptr
)
1075 const unsigned char *ptr
= (const unsigned char *)xptr
;
1078 if ((*ptr
& 0x80) == 0){
1079 size
= ptr
[0] & 0x7f;
1081 } else if ((*ptr
& 0x40) == 0){
1082 size
= ((ptr
[0] & 0x3f) << 8) + ptr
[1];
1085 size
= ((ptr
[0] & 0x1f) << 24) +
1097 * mono_metadata_decode_value:
1098 * @ptr: pointer to decode from
1099 * @rptr: the new position of the pointer
1101 * This routine decompresses 32-bit values as specified in the "Blob and
1102 * Signature" section (22.2)
1104 * Returns: the decoded value
1107 mono_metadata_decode_value (const char *_ptr
, const char **rptr
)
1109 const unsigned char *ptr
= (const unsigned char *) _ptr
;
1110 unsigned char b
= *ptr
;
1113 if ((b
& 0x80) == 0){
1116 } else if ((b
& 0x40) == 0){
1117 len
= ((b
& 0x3f) << 8 | ptr
[1]);
1120 len
= ((b
& 0x1f) << 24) |
1133 * mono_metadata_decode_signed_value:
1134 * @ptr: pointer to decode from
1135 * @rptr: the new position of the pointer
1137 * This routine decompresses 32-bit signed values
1138 * (not specified in the spec)
1140 * Returns: the decoded value
1143 mono_metadata_decode_signed_value (const char *ptr
, const char **rptr
)
1145 guint32 uval
= mono_metadata_decode_value (ptr
, rptr
);
1146 gint32 ival
= uval
>> 1;
1149 /* ival is a truncated 2's complement negative number. */
1151 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1154 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1155 return ival
- 0x2000;
1156 if (ival
< 0x10000000)
1157 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1158 return ival
- 0x10000000;
1159 g_assert (ival
< 0x20000000);
1160 g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival
, uval
);
1161 return ival
- 0x20000000;
1165 * Translates the given 1-based index into the Method, Field, Event, or Param tables
1166 * using the *Ptr tables in uncompressed metadata, if they are available.
1168 * FIXME: The caller is not forced to call this function, which is error-prone, since
1169 * forgetting to call it would only show up as a bug on uncompressed metadata.
1172 mono_metadata_translate_token_index (MonoImage
*image
, int table
, guint32 idx
)
1174 if (!image
->uncompressed_metadata
)
1178 case MONO_TABLE_METHOD
:
1179 if (image
->tables
[MONO_TABLE_METHOD_POINTER
].rows
)
1180 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_METHOD_POINTER
], idx
- 1, MONO_METHOD_POINTER_METHOD
);
1183 case MONO_TABLE_FIELD
:
1184 if (image
->tables
[MONO_TABLE_FIELD_POINTER
].rows
)
1185 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_FIELD_POINTER
], idx
- 1, MONO_FIELD_POINTER_FIELD
);
1188 case MONO_TABLE_EVENT
:
1189 if (image
->tables
[MONO_TABLE_EVENT_POINTER
].rows
)
1190 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_EVENT_POINTER
], idx
- 1, MONO_EVENT_POINTER_EVENT
);
1193 case MONO_TABLE_PROPERTY
:
1194 if (image
->tables
[MONO_TABLE_PROPERTY_POINTER
].rows
)
1195 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PROPERTY_POINTER
], idx
- 1, MONO_PROPERTY_POINTER_PROPERTY
);
1198 case MONO_TABLE_PARAM
:
1199 if (image
->tables
[MONO_TABLE_PARAM_POINTER
].rows
)
1200 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PARAM_POINTER
], idx
- 1, MONO_PARAM_POINTER_PARAM
);
1209 * mono_metadata_decode_table_row:
1211 * Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
1212 * uncompressed metadata into account, so it should be used to access the
1213 * Method, Field, Param and Event tables when the access is made from metadata, i.e.
1214 * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
1217 mono_metadata_decode_table_row (MonoImage
*image
, int table
, int idx
, guint32
*res
, int res_size
)
1219 if (image
->uncompressed_metadata
)
1220 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1222 mono_metadata_decode_row (&image
->tables
[table
], idx
, res
, res_size
);
1226 * mono_metadata_decode_table_row_col:
1228 * Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
1229 * uncompressed metadata into account, so it should be used to access the
1230 * Method, Field, Param and Event tables.
1232 guint32
mono_metadata_decode_table_row_col (MonoImage
*image
, int table
, int idx
, guint col
)
1234 if (image
->uncompressed_metadata
)
1235 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1237 return mono_metadata_decode_row_col (&image
->tables
[table
], idx
, col
);
1241 * mono_metadata_parse_typedef_or_ref:
1242 * @m: a metadata context.
1243 * @ptr: a pointer to an encoded TypedefOrRef in @m
1244 * @rptr: pointer updated to match the end of the decoded stream
1246 * Returns: a token valid in the @m metadata decoded from
1247 * the compressed representation.
1250 mono_metadata_parse_typedef_or_ref (MonoImage
*m
, const char *ptr
, const char **rptr
)
1253 token
= mono_metadata_decode_value (ptr
, &ptr
);
1256 return mono_metadata_token_from_dor (token
);
1260 * mono_metadata_parse_custom_mod:
1261 * @m: a metadata context.
1262 * @dest: storage where the info about the custom modifier is stored (may be NULL)
1263 * @ptr: a pointer to (possibly) the start of a custom modifier list
1264 * @rptr: pointer updated to match the end of the decoded stream
1266 * Checks if @ptr points to a type custom modifier compressed representation.
1268 * Returns: #TRUE if a custom modifier was found, #FALSE if not.
1271 mono_metadata_parse_custom_mod (MonoImage
*m
, MonoCustomMod
*dest
, const char *ptr
, const char **rptr
)
1273 MonoCustomMod local
;
1274 if ((*ptr
== MONO_TYPE_CMOD_OPT
) || (*ptr
== MONO_TYPE_CMOD_REQD
)) {
1277 dest
->required
= *ptr
== MONO_TYPE_CMOD_REQD
? 1 : 0;
1278 dest
->token
= mono_metadata_parse_typedef_or_ref (m
, ptr
+ 1, rptr
);
1285 * mono_metadata_parse_array_full:
1286 * @m: a metadata context.
1287 * @ptr: a pointer to an encoded array description.
1288 * @rptr: pointer updated to match the end of the decoded stream
1290 * Decodes the compressed array description found in the metadata @m at @ptr.
1292 * Returns: a #MonoArrayType structure describing the array type
1293 * and dimensions. Memory is allocated from the image mempool.
1295 * LOCKING: Acquires the loader lock
1298 mono_metadata_parse_array_full (MonoImage
*m
, MonoGenericContainer
*container
,
1299 const char *ptr
, const char **rptr
)
1302 MonoArrayType
*array
;
1305 array
= mono_image_alloc0_lock (m
, sizeof (MonoArrayType
));
1306 etype
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
1309 array
->eklass
= mono_class_from_mono_type (etype
);
1310 array
->rank
= mono_metadata_decode_value (ptr
, &ptr
);
1312 array
->numsizes
= mono_metadata_decode_value (ptr
, &ptr
);
1313 if (array
->numsizes
)
1314 array
->sizes
= g_new0 (int, array
->numsizes
);
1315 for (i
= 0; i
< array
->numsizes
; ++i
)
1316 array
->sizes
[i
] = mono_metadata_decode_value (ptr
, &ptr
);
1318 array
->numlobounds
= mono_metadata_decode_value (ptr
, &ptr
);
1319 if (array
->numlobounds
)
1320 array
->lobounds
= g_new0 (int, array
->numlobounds
);
1321 for (i
= 0; i
< array
->numlobounds
; ++i
)
1322 array
->lobounds
[i
] = mono_metadata_decode_signed_value (ptr
, &ptr
);
1330 mono_metadata_parse_array (MonoImage
*m
, const char *ptr
, const char **rptr
)
1332 return mono_metadata_parse_array_full (m
, NULL
, ptr
, rptr
);
1336 * mono_metadata_free_array:
1337 * @array: array description
1339 * Frees the array description returned from mono_metadata_parse_array().
1342 mono_metadata_free_array (MonoArrayType
*array
)
1344 g_free (array
->sizes
);
1345 g_free (array
->lobounds
);
1350 * need to add common field and param attributes combinations:
1353 * public static literal
1356 * private static literal
1358 static const MonoType
1360 /* data, attrs, type, nmods, byref, pinned */
1361 {{NULL
}, 0, MONO_TYPE_VOID
, 0, 0, 0},
1362 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 0, 0},
1363 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 1, 0},
1364 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 0, 0},
1365 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 1, 0},
1366 {{NULL
}, 0, MONO_TYPE_I1
, 0, 0, 0},
1367 {{NULL
}, 0, MONO_TYPE_I1
, 0, 1, 0},
1368 {{NULL
}, 0, MONO_TYPE_U1
, 0, 0, 0},
1369 {{NULL
}, 0, MONO_TYPE_U1
, 0, 1, 0},
1370 {{NULL
}, 0, MONO_TYPE_I2
, 0, 0, 0},
1371 {{NULL
}, 0, MONO_TYPE_I2
, 0, 1, 0},
1372 {{NULL
}, 0, MONO_TYPE_U2
, 0, 0, 0},
1373 {{NULL
}, 0, MONO_TYPE_U2
, 0, 1, 0},
1374 {{NULL
}, 0, MONO_TYPE_I4
, 0, 0, 0},
1375 {{NULL
}, 0, MONO_TYPE_I4
, 0, 1, 0},
1376 {{NULL
}, 0, MONO_TYPE_U4
, 0, 0, 0},
1377 {{NULL
}, 0, MONO_TYPE_U4
, 0, 1, 0},
1378 {{NULL
}, 0, MONO_TYPE_I8
, 0, 0, 0},
1379 {{NULL
}, 0, MONO_TYPE_I8
, 0, 1, 0},
1380 {{NULL
}, 0, MONO_TYPE_U8
, 0, 0, 0},
1381 {{NULL
}, 0, MONO_TYPE_U8
, 0, 1, 0},
1382 {{NULL
}, 0, MONO_TYPE_R4
, 0, 0, 0},
1383 {{NULL
}, 0, MONO_TYPE_R4
, 0, 1, 0},
1384 {{NULL
}, 0, MONO_TYPE_R8
, 0, 0, 0},
1385 {{NULL
}, 0, MONO_TYPE_R8
, 0, 1, 0},
1386 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 0, 0},
1387 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 1, 0},
1388 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 0, 0},
1389 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 1, 0},
1390 {{NULL
}, 0, MONO_TYPE_TYPEDBYREF
, 0, 0, 0},
1391 {{NULL
}, 0, MONO_TYPE_I
, 0, 0, 0},
1392 {{NULL
}, 0, MONO_TYPE_I
, 0, 1, 0},
1393 {{NULL
}, 0, MONO_TYPE_U
, 0, 0, 0},
1394 {{NULL
}, 0, MONO_TYPE_U
, 0, 1, 0},
1397 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1399 static GHashTable
*type_cache
= NULL
;
1400 static GHashTable
*generic_inst_cache
= NULL
;
1401 static GHashTable
*generic_class_cache
= NULL
;
1402 static int next_generic_inst_id
= 0;
1405 * Protected by the loader lock.
1406 * It has a MonoMethodInflated* as key and value.
1407 * The key lookup will just access the declaring and context fields
1409 static GHashTable
*generic_method_cache
= NULL
;
1412 * Protected by the loader lock.
1413 * It has a MonoInflatedMethodSignature* as key and value.
1415 static GHashTable
*generic_signature_cache
= NULL
;
1417 static guint
mono_generic_class_hash (gconstpointer data
);
1420 * MonoTypes with modifies are never cached, so we never check or use that field.
1423 mono_type_hash (gconstpointer data
)
1425 const MonoType
*type
= (const MonoType
*) data
;
1426 if (type
->type
== MONO_TYPE_GENERICINST
)
1427 return mono_generic_class_hash (type
->data
.generic_class
);
1429 return type
->type
| (type
->byref
<< 8) | (type
->attrs
<< 9);
1433 mono_type_equal (gconstpointer ka
, gconstpointer kb
)
1435 const MonoType
*a
= (const MonoType
*) ka
;
1436 const MonoType
*b
= (const MonoType
*) kb
;
1438 if (a
->type
!= b
->type
|| a
->byref
!= b
->byref
|| a
->attrs
!= b
->attrs
|| a
->pinned
!= b
->pinned
)
1440 /* need other checks */
1445 mono_metadata_generic_inst_hash (gconstpointer data
)
1447 const MonoGenericInst
*ginst
= (const MonoGenericInst
*) data
;
1451 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
1453 hash
+= mono_metadata_type_hash (ginst
->type_argv
[i
]);
1456 return hash
^ (ginst
->is_open
<< 8);
1460 mono_generic_inst_equal_full (const MonoGenericInst
*a
, const MonoGenericInst
*b
, gboolean signature_only
)
1464 if (a
->id
&& b
->id
) {
1467 if (!signature_only
)
1471 if (a
->is_open
!= b
->is_open
|| a
->type_argc
!= b
->type_argc
)
1473 for (i
= 0; i
< a
->type_argc
; ++i
) {
1474 if (!do_mono_metadata_type_equal (a
->type_argv
[i
], b
->type_argv
[i
], signature_only
))
1481 mono_metadata_generic_inst_equal (gconstpointer ka
, gconstpointer kb
)
1483 const MonoGenericInst
*a
= (const MonoGenericInst
*) ka
;
1484 const MonoGenericInst
*b
= (const MonoGenericInst
*) kb
;
1486 return mono_generic_inst_equal_full (a
, b
, FALSE
);
1490 mono_generic_class_hash (gconstpointer data
)
1492 const MonoGenericClass
*gclass
= (const MonoGenericClass
*) data
;
1493 guint hash
= mono_metadata_type_hash (&gclass
->container_class
->byval_arg
);
1496 hash
+= gclass
->is_tb_open
;
1497 hash
+= mono_metadata_generic_context_hash (&gclass
->context
);
1503 mono_generic_class_equal (gconstpointer ka
, gconstpointer kb
)
1505 const MonoGenericClass
*a
= (const MonoGenericClass
*) ka
;
1506 const MonoGenericClass
*b
= (const MonoGenericClass
*) kb
;
1508 return _mono_metadata_generic_class_equal (a
, b
, FALSE
);
1512 * mono_metadata_init:
1514 * Initialize the global variables of this module.
1515 * This is a Mono runtime internal function.
1518 mono_metadata_init (void)
1522 type_cache
= g_hash_table_new (mono_type_hash
, mono_type_equal
);
1523 generic_inst_cache
= g_hash_table_new_full (mono_metadata_generic_inst_hash
, mono_metadata_generic_inst_equal
, NULL
, (GDestroyNotify
)free_generic_inst
);
1524 generic_class_cache
= g_hash_table_new_full (mono_generic_class_hash
, mono_generic_class_equal
, NULL
, (GDestroyNotify
)free_generic_class
);
1526 for (i
= 0; i
< NBUILTIN_TYPES (); ++i
)
1527 g_hash_table_insert (type_cache
, (gpointer
) &builtin_types
[i
], (gpointer
) &builtin_types
[i
]);
1531 * mono_metadata_cleanup:
1533 * Free all resources used by this module.
1534 * This is a Mono runtime internal function.
1537 mono_metadata_cleanup (void)
1539 g_hash_table_destroy (type_cache
);
1540 g_hash_table_destroy (generic_inst_cache
);
1541 g_hash_table_destroy (generic_class_cache
);
1542 if (generic_method_cache
)
1543 g_hash_table_destroy (generic_method_cache
);
1544 if (generic_signature_cache
)
1545 g_hash_table_destroy (generic_signature_cache
);
1547 generic_inst_cache
= NULL
;
1548 generic_class_cache
= NULL
;
1549 generic_method_cache
= NULL
;
1550 generic_signature_cache
= NULL
;
1554 * mono_metadata_parse_type:
1555 * @m: metadata context
1556 * @mode: king of type that may be found at @ptr
1557 * @opt_attrs: optional attributes to store in the returned type
1558 * @ptr: pointer to the type representation
1559 * @rptr: pointer updated to match the end of the decoded stream
1561 * Decode a compressed type description found at @ptr in @m.
1562 * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
1563 * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
1564 * This function can be used to decode type descriptions in method signatures,
1565 * field signatures, locals signatures etc.
1567 * To parse a generic type, `generic_container' points to the current class'es
1568 * (the `generic_container' field in the MonoClass) or the current generic method's
1569 * (the `generic_container' field in the MonoMethodNormal) generic container.
1570 * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
1571 * this MonoGenericContainer.
1572 * This is a Mono runtime internal function.
1574 * LOCKING: Acquires the loader lock.
1576 * Returns: a #MonoType structure representing the decoded type.
1579 mono_metadata_parse_type_full (MonoImage
*m
, MonoGenericContainer
*container
, MonoParseTypeMode mode
,
1580 short opt_attrs
, const char *ptr
, const char **rptr
)
1582 MonoType
*type
, *cached
;
1584 gboolean byref
= FALSE
;
1585 gboolean pinned
= FALSE
;
1586 const char *tmp_ptr
;
1591 * According to the spec, custom modifiers should come before the byref
1592 * flag, but the IL produced by ilasm from the following signature:
1593 * object modopt(...) &
1594 * starts with a byref flag, followed by the modifiers. (bug #49802)
1595 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1596 * it would be better to treat byref as real type constructor instead of
1598 * Also, pinned should come before anything else, but some MSV++ produced
1599 * assemblies violate this (#bug 61990).
1602 /* Count the modifiers first */
1607 case MONO_TYPE_PINNED
:
1608 case MONO_TYPE_BYREF
:
1611 case MONO_TYPE_CMOD_REQD
:
1612 case MONO_TYPE_CMOD_OPT
:
1614 mono_metadata_parse_custom_mod (m
, NULL
, tmp_ptr
, &tmp_ptr
);
1622 type
= mono_image_alloc0_lock (m
, sizeof (MonoType
) + ((gint32
)count
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoCustomMod
));
1623 type
->num_mods
= count
;
1625 g_warning ("got more than 64 modifiers in type");
1628 memset (type
, 0, sizeof (MonoType
));
1631 /* Parse pinned, byref and custom modifiers */
1636 case MONO_TYPE_PINNED
:
1640 case MONO_TYPE_BYREF
:
1644 case MONO_TYPE_CMOD_REQD
:
1645 case MONO_TYPE_CMOD_OPT
:
1646 mono_metadata_parse_custom_mod (m
, &(type
->modifiers
[count
]), ptr
, &ptr
);
1654 type
->attrs
= opt_attrs
;
1655 type
->byref
= byref
;
1656 type
->pinned
= pinned
? 1 : 0;
1658 if (!do_mono_metadata_parse_type (type
, m
, container
, ptr
, &ptr
)) {
1665 if (!type
->num_mods
) {
1666 /* no need to free type here, because it is on the stack */
1667 if ((type
->type
== MONO_TYPE_CLASS
|| type
->type
== MONO_TYPE_VALUETYPE
) && !type
->pinned
&& !type
->attrs
) {
1668 MonoType
*ret
= type
->byref
? &type
->data
.klass
->this_arg
: &type
->data
.klass
->byval_arg
;
1670 /* Consider the case:
1672 class Foo<T> { class Bar {} }
1673 class Test : Foo<Test>.Bar {}
1675 When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
1676 a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1678 We ensure that the MonoClass is in a state that we can canonicalize to:
1680 klass->byval_arg.data.klass == klass
1681 klass->this_arg.data.klass == klass
1683 If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1685 LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1686 of a MonoClass which currently holds the loader lock. 'type' is local.
1688 if (ret
->data
.klass
== type
->data
.klass
) {
1692 /* No need to use locking since nobody is modifying the hash table */
1693 if ((cached
= g_hash_table_lookup (type_cache
, type
))) {
1698 /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1700 if (type
== &stype
) {
1701 type
= mono_image_alloc_lock (m
, sizeof (MonoType
));
1702 memcpy (type
, &stype
, sizeof (MonoType
));
1708 * LOCKING: Acquires the loader lock.
1711 mono_metadata_parse_type (MonoImage
*m
, MonoParseTypeMode mode
, short opt_attrs
,
1712 const char *ptr
, const char **rptr
)
1714 return mono_metadata_parse_type_full (m
, NULL
, mode
, opt_attrs
, ptr
, rptr
);
1718 * mono_metadata_get_param_attrs:
1720 * Return the parameter attributes for the method whose MethodDef index is DEF. The
1721 * returned memory needs to be freed by the caller. If all the param attributes are
1722 * 0, then NULL is returned.
1725 mono_metadata_get_param_attrs (MonoImage
*m
, int def
)
1727 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1728 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1729 guint32 cols
[MONO_PARAM_SIZE
];
1730 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (&m
->tables
[MONO_TABLE_METHOD
], def
- 1, MONO_METHOD_PARAMLIST
);
1733 if (def
< methodt
->rows
)
1734 lastp
= mono_metadata_decode_row_col (&m
->tables
[MONO_TABLE_METHOD
], def
, MONO_METHOD_PARAMLIST
);
1736 lastp
= paramt
->rows
+ 1;
1738 for (i
= param_index
; i
< lastp
; ++i
) {
1739 mono_metadata_decode_row (&m
->tables
[MONO_TABLE_PARAM
], i
- 1, cols
, MONO_PARAM_SIZE
);
1740 if (cols
[MONO_PARAM_FLAGS
]) {
1742 pattrs
= g_new0 (int, 1 + (lastp
- param_index
));
1743 pattrs
[cols
[MONO_PARAM_SEQUENCE
]] = cols
[MONO_PARAM_FLAGS
];
1751 * mono_metadata_parse_signature_full:
1752 * @image: metadata context
1753 * @generic_container: generic container
1754 * @toke: metadata token
1756 * Decode a method signature stored in the STANDALONESIG table
1758 * LOCKING: Assumes the loader lock is held.
1760 * Returns: a MonoMethodSignature describing the signature.
1762 MonoMethodSignature
*
1763 mono_metadata_parse_signature_full (MonoImage
*image
, MonoGenericContainer
*generic_container
, guint32 token
)
1765 MonoTableInfo
*tables
= image
->tables
;
1766 guint32 idx
= mono_metadata_token_index (token
);
1771 return mono_lookup_dynamic_token (image
, token
, NULL
);
1773 g_assert (mono_metadata_token_table(token
) == MONO_TABLE_STANDALONESIG
);
1775 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
1777 ptr
= mono_metadata_blob_heap (image
, sig
);
1778 mono_metadata_decode_blob_size (ptr
, &ptr
);
1780 return mono_metadata_parse_method_signature_full (image
, generic_container
, 0, ptr
, NULL
);
1784 * mono_metadata_parse_signature:
1785 * @image: metadata context
1786 * @toke: metadata token
1788 * Decode a method signature stored in the STANDALONESIG table
1790 * Returns: a MonoMethodSignature describing the signature.
1792 MonoMethodSignature
*
1793 mono_metadata_parse_signature (MonoImage
*image
, guint32 token
)
1795 return mono_metadata_parse_signature_full (image
, NULL
, token
);
1799 * mono_metadata_signature_alloc:
1800 * @image: metadata context
1801 * @nparmas: number of parameters in the signature
1803 * Allocate a MonoMethodSignature structure with the specified number of params.
1804 * The return type and the params types need to be filled later.
1805 * This is a Mono runtime internal function.
1807 * LOCKING: Assumes the loader lock is held.
1809 * Returns: the new MonoMethodSignature structure.
1811 MonoMethodSignature
*
1812 mono_metadata_signature_alloc (MonoImage
*m
, guint32 nparams
)
1814 MonoMethodSignature
*sig
;
1816 sig
= mono_image_alloc0_lock (m
, sizeof (MonoMethodSignature
) + ((gint32
)nparams
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoType
*));
1817 sig
->param_count
= nparams
;
1818 sig
->sentinelpos
= -1;
1823 MonoMethodSignature
*
1824 mono_metadata_signature_dup_full (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1828 sigsize
= sizeof (MonoMethodSignature
) + (sig
->param_count
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoType
*);
1831 MonoMethodSignature
*ret
;
1832 mono_loader_lock ();
1833 ret
= mono_mempool_alloc (mp
, sigsize
);
1834 mono_loader_unlock ();
1836 memcpy (ret
, sig
, sigsize
);
1839 return g_memdup (sig
, sigsize
);
1844 * mono_metadata_signature_dup:
1845 * @sig: method signature
1847 * Duplicate an existing MonoMethodSignature so it can be modified.
1848 * This is a Mono runtime internal function.
1850 * Returns: the new MonoMethodSignature structure.
1852 MonoMethodSignature
*
1853 mono_metadata_signature_dup (MonoMethodSignature
*sig
)
1855 return mono_metadata_signature_dup_full (NULL
, sig
);
1859 * mono_metadata_parse_method_signature:
1860 * @m: metadata context
1861 * @generic_container: generics container
1862 * @def: the MethodDef index or 0 for Ref signatures.
1863 * @ptr: pointer to the signature metadata representation
1864 * @rptr: pointer updated to match the end of the decoded stream
1866 * Decode a method signature stored at @ptr.
1867 * This is a Mono runtime internal function.
1869 * LOCKING: Assumes the loader lock is held.
1871 * Returns: a MonoMethodSignature describing the signature.
1873 MonoMethodSignature
*
1874 mono_metadata_parse_method_signature_full (MonoImage
*m
, MonoGenericContainer
*container
,
1875 int def
, const char *ptr
, const char **rptr
)
1877 MonoMethodSignature
*method
;
1878 int i
, *pattrs
= NULL
;
1879 guint32 hasthis
= 0, explicit_this
= 0, call_convention
, param_count
;
1880 guint32 gen_param_count
= 0;
1881 gboolean is_open
= FALSE
;
1884 gen_param_count
= 1;
1889 call_convention
= *ptr
& 0x0F;
1891 if (gen_param_count
)
1892 gen_param_count
= mono_metadata_decode_value (ptr
, &ptr
);
1893 param_count
= mono_metadata_decode_value (ptr
, &ptr
);
1896 pattrs
= mono_metadata_get_param_attrs (m
, def
);
1897 method
= mono_metadata_signature_alloc (m
, param_count
);
1898 method
->hasthis
= hasthis
;
1899 method
->explicit_this
= explicit_this
;
1900 method
->call_convention
= call_convention
;
1901 method
->generic_param_count
= gen_param_count
;
1903 if (call_convention
!= 0xa) {
1904 method
->ret
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_RET
, pattrs
? pattrs
[0] : 0, ptr
, &ptr
);
1906 mono_metadata_free_method_signature (method
);
1910 is_open
= mono_class_is_open_constructed_type (method
->ret
);
1913 for (i
= 0; i
< method
->param_count
; ++i
) {
1914 if (*ptr
== MONO_TYPE_SENTINEL
) {
1915 if (method
->call_convention
!= MONO_CALL_VARARG
|| def
)
1916 g_error ("found sentinel for methoddef or no vararg method");
1917 if (method
->sentinelpos
>= 0)
1918 g_error ("found sentinel twice in the same signature");
1919 method
->sentinelpos
= i
;
1922 method
->params
[i
] = mono_metadata_parse_type_full (m
, container
, MONO_PARSE_PARAM
, pattrs
? pattrs
[i
+1] : 0, ptr
, &ptr
);
1923 if (!method
->params
[i
]) {
1924 mono_metadata_free_method_signature (method
);
1929 is_open
= mono_class_is_open_constructed_type (method
->params
[i
]);
1932 /* The sentinel could be missing if the caller does not pass any additional arguments */
1933 if (!def
&& method
->call_convention
== MONO_CALL_VARARG
&& method
->sentinelpos
< 0)
1934 method
->sentinelpos
= method
->param_count
;
1936 method
->has_type_parameters
= is_open
;
1938 if (def
&& (method
->call_convention
== MONO_CALL_VARARG
))
1939 method
->sentinelpos
= method
->param_count
;
1946 * Add signature to a cache and increase ref count...
1953 * mono_metadata_parse_method_signature:
1954 * @m: metadata context
1955 * @def: the MethodDef index or 0 for Ref signatures.
1956 * @ptr: pointer to the signature metadata representation
1957 * @rptr: pointer updated to match the end of the decoded stream
1959 * Decode a method signature stored at @ptr.
1960 * This is a Mono runtime internal function.
1962 * LOCKING: Assumes the loader lock is held.
1964 * Returns: a MonoMethodSignature describing the signature.
1966 MonoMethodSignature
*
1967 mono_metadata_parse_method_signature (MonoImage
*m
, int def
, const char *ptr
, const char **rptr
)
1969 return mono_metadata_parse_method_signature_full (m
, NULL
, def
, ptr
, rptr
);
1973 * mono_metadata_free_method_signature:
1974 * @sig: signature to destroy
1976 * Free the memory allocated in the signature @sig.
1977 * This method needs to be robust and work also on partially-built
1978 * signatures, so it does extra checks.
1981 mono_metadata_free_method_signature (MonoMethodSignature
*sig
)
1983 /* Everything is allocated from mempools */
1987 mono_metadata_free_type (sig->ret);
1988 for (i = 0; i < sig->param_count; ++i) {
1989 if (sig->params [i])
1990 mono_metadata_free_type (sig->params [i]);
1996 mono_metadata_free_inflated_signature (MonoMethodSignature
*sig
)
2000 /* Allocated in inflate_generic_signature () */
2002 mono_metadata_free_type (sig
->ret
);
2003 for (i
= 0; i
< sig
->param_count
; ++i
) {
2004 if (sig
->params
[i
])
2005 mono_metadata_free_type (sig
->params
[i
]);
2011 inflated_method_equal (gconstpointer a
, gconstpointer b
)
2013 const MonoMethodInflated
*ma
= a
;
2014 const MonoMethodInflated
*mb
= b
;
2015 if (ma
->declaring
!= mb
->declaring
)
2017 if (ma
->is_mb_open
!= mb
->is_mb_open
)
2019 return mono_metadata_generic_context_equal (&ma
->context
, &mb
->context
);
2023 inflated_method_hash (gconstpointer a
)
2025 const MonoMethodInflated
*ma
= a
;
2026 return (mono_metadata_generic_context_hash (&ma
->context
) ^ mono_aligned_addr_hash (ma
->declaring
)) + ma
->is_mb_open
;
2030 inflated_signature_equal (gconstpointer a
, gconstpointer b
)
2032 const MonoInflatedMethodSignature
*sig1
= a
;
2033 const MonoInflatedMethodSignature
*sig2
= b
;
2035 /* sig->sig is assumed to be canonized */
2036 if (sig1
->sig
!= sig2
->sig
)
2038 /* The generic instances are canonized */
2039 return mono_metadata_generic_context_equal (&sig1
->context
, &sig2
->context
);
2043 inflated_signature_hash (gconstpointer a
)
2045 const MonoInflatedMethodSignature
*sig
= a
;
2047 /* sig->sig is assumed to be canonized */
2048 return mono_metadata_generic_context_hash (&sig
->context
) ^ mono_aligned_addr_hash (sig
->sig
);
2052 dump_ginst (MonoGenericInst *ginst)
2057 g_print ("Ginst: <");
2058 for (i = 0; i < ginst->type_argc; ++i) {
2061 name = mono_type_get_name (ginst->type_argv [i]);
2062 g_print ("%s", name);
2068 static gboolean
type_in_image (MonoType
*type
, MonoImage
*image
);
2071 signature_in_image (MonoMethodSignature
*sig
, MonoImage
*image
)
2073 gpointer iter
= NULL
;
2076 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2077 if (type_in_image (p
, image
))
2080 return type_in_image (mono_signature_get_return_type (sig
), image
);
2084 ginst_in_image (MonoGenericInst
*ginst
, MonoImage
*image
)
2088 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2089 if (type_in_image (ginst
->type_argv
[i
], image
))
2097 gclass_in_image (MonoGenericClass
*gclass
, MonoImage
*image
)
2099 return gclass
->container_class
->image
== image
||
2100 ginst_in_image (gclass
->context
.class_inst
, image
);
2104 type_in_image (MonoType
*type
, MonoImage
*image
)
2107 switch (type
->type
) {
2108 case MONO_TYPE_GENERICINST
:
2109 return gclass_in_image (type
->data
.generic_class
, image
);
2111 type
= type
->data
.type
;
2113 case MONO_TYPE_SZARRAY
:
2114 type
= &type
->data
.klass
->byval_arg
;
2116 case MONO_TYPE_ARRAY
:
2117 type
= &type
->data
.array
->eklass
->byval_arg
;
2119 case MONO_TYPE_FNPTR
:
2120 return signature_in_image (type
->data
.method
, image
);
2122 if (type
->data
.generic_param
->owner
) {
2123 g_assert (!type
->data
.generic_param
->owner
->is_method
);
2124 return type
->data
.generic_param
->owner
->owner
.klass
->image
== image
;
2126 return type
->data
.generic_param
->image
== image
;
2128 case MONO_TYPE_MVAR
:
2129 if (type
->data
.generic_param
->owner
) {
2130 g_assert (type
->data
.generic_param
->owner
->is_method
);
2131 if (!type
->data
.generic_param
->owner
->owner
.method
)
2132 /* RefEmit created generic param whose method is not finished */
2134 return type
->data
.generic_param
->owner
->owner
.method
->klass
->image
== image
;
2136 return type
->data
.generic_param
->image
== image
;
2139 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2140 return image
== mono_class_from_mono_type (type
)->image
;
2147 } CleanForImageUserData
;
2150 steal_gclass_in_image (gpointer key
, gpointer value
, gpointer data
)
2152 MonoGenericClass
*gclass
= key
;
2153 CleanForImageUserData
*user_data
= data
;
2155 if (!gclass_in_image (gclass
, user_data
->image
))
2158 user_data
->list
= g_slist_prepend (user_data
->list
, gclass
);
2163 steal_ginst_in_image (gpointer key
, gpointer value
, gpointer data
)
2165 MonoGenericInst
*ginst
= key
;
2166 CleanForImageUserData
*user_data
= data
;
2168 if (!ginst_in_image (ginst
, user_data
->image
))
2171 user_data
->list
= g_slist_prepend (user_data
->list
, ginst
);
2176 inflated_method_in_image (gpointer key
, gpointer value
, gpointer data
)
2178 MonoImage
*image
= data
;
2179 MonoMethodInflated
*method
= key
;
2182 // https://bugzilla.novell.com/show_bug.cgi?id=458168
2183 return method
->declaring
->klass
->image
== image
||
2184 (method
->context
.class_inst
&& ginst_in_image (method
->context
.class_inst
, image
)) ||
2185 (method
->context
.method_inst
&& ginst_in_image (method
->context
.method_inst
, image
)) || signature_in_image (mono_method_signature ((MonoMethod
*)method
), image
);
2189 inflated_signature_in_image (gpointer key
, gpointer value
, gpointer data
)
2191 MonoImage
*image
= data
;
2192 MonoInflatedMethodSignature
*sig
= key
;
2194 return signature_in_image (sig
->sig
, image
) ||
2195 (sig
->context
.class_inst
&& ginst_in_image (sig
->context
.class_inst
, image
)) ||
2196 (sig
->context
.method_inst
&& ginst_in_image (sig
->context
.method_inst
, image
));
2200 mono_metadata_clean_for_image (MonoImage
*image
)
2202 CleanForImageUserData ginst_data
, gclass_data
;
2205 /* The data structures could reference each other so we delete them in two phases */
2206 ginst_data
.image
= gclass_data
.image
= image
;
2207 ginst_data
.list
= gclass_data
.list
= NULL
;
2209 mono_loader_lock ();
2210 /* Collect the items to delete and remove them from the hash table */
2211 g_hash_table_foreach_steal (generic_inst_cache
, steal_ginst_in_image
, &ginst_data
);
2212 g_hash_table_foreach_steal (generic_class_cache
, steal_gclass_in_image
, &gclass_data
);
2213 if (generic_method_cache
)
2214 g_hash_table_foreach_remove (generic_method_cache
, inflated_method_in_image
, image
);
2215 if (generic_signature_cache
)
2216 g_hash_table_foreach_remove (generic_signature_cache
, inflated_signature_in_image
, image
);
2217 /* Delete the removed items */
2218 for (l
= ginst_data
.list
; l
; l
= l
->next
)
2219 free_generic_inst (l
->data
);
2220 for (l
= gclass_data
.list
; l
; l
= l
->next
)
2221 free_generic_class (l
->data
);
2222 g_slist_free (ginst_data
.list
);
2223 g_slist_free (gclass_data
.list
);
2224 mono_class_unregister_image_generic_subclasses (image
);
2225 mono_loader_unlock ();
2229 free_inflated_method (MonoMethodInflated
*imethod
)
2232 MonoMethod
*method
= (MonoMethod
*)imethod
;
2234 if (method
->signature
)
2235 mono_metadata_free_inflated_signature (method
->signature
);
2237 if (!((method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) || (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
) || (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) || (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))) {
2238 MonoMethodNormal
* mn
= (MonoMethodNormal
*) method
;
2239 MonoMethodHeader
*header
= mn
->header
;
2242 /* Allocated in inflate_generic_header () */
2243 for (i
= 0; i
< header
->num_locals
; ++i
)
2244 mono_metadata_free_type (header
->locals
[i
]);
2245 g_free (header
->clauses
);
2254 free_generic_inst (MonoGenericInst
*ginst
)
2258 for (i
= 0; i
< ginst
->type_argc
; ++i
)
2259 mono_metadata_free_type (ginst
->type_argv
[i
]);
2260 g_free (ginst
->type_argv
);
2266 free_generic_class (MonoGenericClass
*gclass
)
2270 /* FIXME: The dynamic case */
2271 if (gclass
->cached_class
&& !gclass
->cached_class
->image
->dynamic
&& !mono_generic_class_is_generic_type_definition (gclass
)) {
2272 MonoClass
*class = gclass
->cached_class
;
2274 /* Allocated in mono_class_init () */
2275 g_free (class->methods
);
2276 g_free (class->properties
);
2277 /* Allocated in mono_generic_class_get_class () */
2278 g_free (class->interfaces
);
2280 } else if (gclass
->is_dynamic
) {
2281 MonoDynamicGenericClass
*dgclass
= (MonoDynamicGenericClass
*)gclass
;
2283 for (i
= 0; i
< dgclass
->count_fields
; ++i
) {
2284 MonoClassField
*field
= dgclass
->fields
+ i
;
2285 mono_metadata_free_type (field
->type
);
2286 g_free ((char*)field
->name
);
2288 for (i
= 0; i
< dgclass
->count_properties
; ++i
) {
2289 MonoProperty
*property
= dgclass
->properties
+ i
;
2290 g_free ((char*)property
->name
);
2292 for (i
= 0; i
< dgclass
->count_events
; ++i
) {
2293 MonoEvent
*event
= dgclass
->events
+ i
;
2294 g_free ((char*)event
->name
);
2297 g_free (dgclass
->methods
);
2298 g_free (dgclass
->ctors
);
2299 g_free (dgclass
->fields
);
2300 g_free (dgclass
->properties
);
2301 g_free (dgclass
->events
);
2302 g_free (dgclass
->field_objects
);
2303 g_free (dgclass
->field_generic_types
);
2304 if (!mono_generic_class_is_generic_type_definition (gclass
))
2305 g_free (gclass
->cached_class
);
2311 free_inflated_signature (MonoInflatedMethodSignature
*sig
)
2313 mono_metadata_free_inflated_signature (sig
->sig
);
2318 * LOCKING: assumes the loader lock is held.
2321 mono_method_inflated_lookup (MonoMethodInflated
* method
, gboolean cache
)
2324 if (!generic_method_cache
)
2325 generic_method_cache
= g_hash_table_new_full (inflated_method_hash
, inflated_method_equal
, NULL
, (GDestroyNotify
)free_inflated_method
);
2326 g_hash_table_insert (generic_method_cache
, method
, method
);
2329 if (generic_method_cache
)
2330 return g_hash_table_lookup (generic_method_cache
, method
);
2336 * mono_metadata_get_inflated_signature:
2338 * Given an inflated signature and a generic context, return a canonical copy of the
2339 * signature. The returned signature might be equal to SIG or it might be a cached copy.
2341 MonoMethodSignature
*
2342 mono_metadata_get_inflated_signature (MonoMethodSignature
*sig
, MonoGenericContext
*context
)
2344 MonoInflatedMethodSignature helper
;
2345 MonoInflatedMethodSignature
*res
;
2347 mono_loader_lock ();
2348 if (!generic_signature_cache
)
2349 generic_signature_cache
= g_hash_table_new_full (inflated_signature_hash
, inflated_signature_equal
, NULL
, (GDestroyNotify
)free_inflated_signature
);
2352 helper
.context
.class_inst
= context
->class_inst
;
2353 helper
.context
.method_inst
= context
->method_inst
;
2354 res
= g_hash_table_lookup (generic_signature_cache
, &helper
);
2356 res
= g_new0 (MonoInflatedMethodSignature
, 1);
2358 res
->context
.class_inst
= context
->class_inst
;
2359 res
->context
.method_inst
= context
->method_inst
;
2360 g_hash_table_insert (generic_signature_cache
, res
, res
);
2363 mono_loader_unlock ();
2368 * mono_metadata_get_generic_inst:
2370 * Given a list of types, return a MonoGenericInst that represents that list.
2371 * The returned MonoGenericInst has its own copy of the list of types. The list
2372 * passed in the argument can be freed, modified or disposed of.
2376 mono_metadata_get_generic_inst (int type_argc
, MonoType
**type_argv
)
2378 MonoGenericInst
*ginst
;
2379 MonoGenericInst helper
;
2382 helper
.type_argc
= type_argc
;
2383 helper
.type_argv
= type_argv
;
2386 for (i
= 0; i
< type_argc
; ++i
)
2387 if (mono_class_is_open_constructed_type (type_argv
[i
]))
2389 helper
.is_open
= (i
< type_argc
);
2391 /*dump_ginst (&helper);*/
2392 mono_loader_lock ();
2393 ginst
= g_hash_table_lookup (generic_inst_cache
, &helper
);
2395 mono_loader_unlock ();
2396 /*g_print (" found cached\n");*/
2400 ginst
= g_new0 (MonoGenericInst
, 1);
2401 ginst
->type_argc
= type_argc
;
2402 ginst
->type_argv
= g_new (MonoType
*, type_argc
);
2403 ginst
->id
= ++next_generic_inst_id
;
2404 ginst
->is_open
= helper
.is_open
;
2406 for (i
= 0; i
< type_argc
; ++i
)
2407 ginst
->type_argv
[i
] = mono_metadata_type_dup (NULL
, type_argv
[i
]);
2409 g_hash_table_insert (generic_inst_cache
, ginst
, ginst
);
2411 mono_loader_unlock ();
2412 /*g_print (" inserted\n");*/
2417 mono_metadata_is_type_builder_generic_type_definition (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
2419 MonoGenericContainer
*container
= container_class
->generic_container
;
2421 if (!is_dynamic
|| container_class
->wastypebuilder
|| container
->type_argc
!= inst
->type_argc
)
2423 return inst
== container
->context
.class_inst
;
2427 * mono_metadata_lookup_generic_class:
2429 * Returns a MonoGenericClass with the given properties.
2433 mono_metadata_lookup_generic_class (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
2435 MonoGenericClass
*gclass
;
2436 MonoGenericClass helper
;
2437 gboolean is_tb_open
= mono_metadata_is_type_builder_generic_type_definition (container_class
, inst
, is_dynamic
);
2439 helper
.container_class
= container_class
;
2440 helper
.context
.class_inst
= inst
;
2441 helper
.context
.method_inst
= NULL
;
2442 helper
.is_dynamic
= is_dynamic
; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
2443 helper
.is_tb_open
= is_tb_open
;
2444 helper
.cached_class
= NULL
;
2446 mono_loader_lock ();
2448 gclass
= g_hash_table_lookup (generic_class_cache
, &helper
);
2450 /* A tripwire just to keep us honest */
2451 g_assert (!helper
.cached_class
);
2454 mono_loader_unlock ();
2459 MonoDynamicGenericClass
*dgclass
= g_new0 (MonoDynamicGenericClass
, 1);
2460 gclass
= &dgclass
->generic_class
;
2461 gclass
->is_dynamic
= 1;
2463 gclass
= g_new0 (MonoGenericClass
, 1);
2466 gclass
->is_tb_open
= is_tb_open
;
2467 gclass
->container_class
= container_class
;
2468 gclass
->context
.class_inst
= inst
;
2469 gclass
->context
.method_inst
= NULL
;
2470 if (inst
== container_class
->generic_container
->context
.class_inst
&& !is_tb_open
)
2471 gclass
->cached_class
= container_class
;
2473 g_hash_table_insert (generic_class_cache
, gclass
, gclass
);
2475 mono_loader_unlock ();
2481 * mono_metadata_inflate_generic_inst:
2483 * Instantiate the generic instance @ginst with the context @context.
2487 mono_metadata_inflate_generic_inst (MonoGenericInst
*ginst
, MonoGenericContext
*context
)
2489 MonoType
**type_argv
;
2490 MonoGenericInst
*nginst
;
2493 if (!ginst
->is_open
)
2496 type_argv
= g_new0 (MonoType
*, ginst
->type_argc
);
2498 for (i
= 0; i
< ginst
->type_argc
; i
++)
2499 type_argv
[i
] = mono_class_inflate_generic_type (ginst
->type_argv
[i
], context
);
2501 nginst
= mono_metadata_get_generic_inst (ginst
->type_argc
, type_argv
);
2503 for (i
= 0; i
< ginst
->type_argc
; i
++)
2504 mono_metadata_free_type (type_argv
[i
]);
2511 mono_metadata_parse_generic_inst (MonoImage
*m
, MonoGenericContainer
*container
,
2512 int count
, const char *ptr
, const char **rptr
)
2514 MonoType
**type_argv
;
2515 MonoGenericInst
*ginst
;
2518 type_argv
= g_new0 (MonoType
*, count
);
2520 for (i
= 0; i
< count
; i
++) {
2521 MonoType
*t
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
2532 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
2540 do_mono_metadata_parse_generic_class (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
2541 const char *ptr
, const char **rptr
)
2543 MonoGenericInst
*inst
;
2548 gtype
= mono_metadata_parse_type (m
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
2552 gklass
= mono_class_from_mono_type (gtype
);
2553 if (!gklass
->generic_container
)
2556 count
= mono_metadata_decode_value (ptr
, &ptr
);
2557 inst
= mono_metadata_parse_generic_inst (m
, container
, count
, ptr
, &ptr
);
2564 type
->data
.generic_class
= mono_metadata_lookup_generic_class (gklass
, inst
, FALSE
);
2570 * @gc: The generic container to normalize
2571 * @type: The kind of generic parameters the resulting generic-container should contain
2574 static MonoGenericContainer
*
2575 select_container (MonoGenericContainer
*gc
, MonoTypeEnum type
)
2577 gboolean is_var
= (type
== MONO_TYPE_VAR
);
2581 g_assert (is_var
|| type
== MONO_TYPE_MVAR
);
2584 if (gc
->is_method
|| gc
->parent
)
2586 * The current MonoGenericContainer is a generic method -> its `parent'
2587 * points to the containing class'es container.
2596 * mono_metadata_parse_generic_param:
2597 * @generic_container: Our MonoClass's or MonoMethodNormal's MonoGenericContainer;
2598 * see mono_metadata_parse_type_full() for details.
2599 * Internal routine to parse a generic type parameter.
2600 * LOCKING: Acquires the loader lock
2602 static MonoGenericParam
*
2603 mono_metadata_parse_generic_param (MonoImage
*m
, MonoGenericContainer
*generic_container
,
2604 MonoTypeEnum type
, const char *ptr
, const char **rptr
)
2606 int index
= mono_metadata_decode_value (ptr
, &ptr
);
2610 generic_container
= select_container (generic_container
, type
);
2611 if (!generic_container
) {
2612 /* Create dummy MonoGenericParam */
2613 MonoGenericParam
*param
;
2615 param
= mono_image_alloc0_lock (m
, sizeof (MonoGenericParam
));
2616 param
->name
= mono_image_alloc0_lock (m
, 8);
2617 sprintf ((char*)param
->name
, "%d", index
);
2624 g_assert (index
< generic_container
->type_argc
);
2625 return &generic_container
->type_params
[index
];
2629 * mono_metadata_get_shared_type:
2631 * Return a shared instance of TYPE, if available, NULL otherwise.
2632 * Shared MonoType instances help save memory. Their contents should not be modified
2633 * by the caller. They do not need to be freed as their lifetime is bound by either
2634 * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
2635 * instance they are embedded in. If they are freed, they should be freed using
2636 * mono_metadata_free_type () instead of g_free ().
2639 mono_metadata_get_shared_type (MonoType
*type
)
2643 /* No need to use locking since nobody is modifying the hash table */
2644 if ((cached
= g_hash_table_lookup (type_cache
, type
)))
2647 switch (type
->type
){
2648 case MONO_TYPE_CLASS
:
2649 case MONO_TYPE_VALUETYPE
:
2650 if (type
== &type
->data
.klass
->byval_arg
)
2652 if (type
== &type
->data
.klass
->this_arg
)
2661 * do_mono_metadata_parse_type:
2662 * @type: MonoType to be filled in with the return value
2664 * @generic_context: generics_context
2665 * @ptr: pointer to the encoded type
2666 * @rptr: pointer where the end of the encoded type is saved
2668 * Internal routine used to "fill" the contents of @type from an
2669 * allocated pointer. This is done this way to avoid doing too
2670 * many mini-allocations (particularly for the MonoFieldType which
2671 * most of the time is just a MonoType, but sometimes might be augmented).
2673 * This routine is used by mono_metadata_parse_type and
2674 * mono_metadata_parse_field_type
2676 * This extracts a Type as specified in Partition II (22.2.12)
2678 * Returns: FALSE if the type could not be loaded
2681 do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
2682 const char *ptr
, const char **rptr
)
2685 type
->type
= mono_metadata_decode_value (ptr
, &ptr
);
2687 switch (type
->type
){
2688 case MONO_TYPE_VOID
:
2689 case MONO_TYPE_BOOLEAN
:
2690 case MONO_TYPE_CHAR
:
2703 case MONO_TYPE_STRING
:
2704 case MONO_TYPE_OBJECT
:
2705 case MONO_TYPE_TYPEDBYREF
:
2707 case MONO_TYPE_VALUETYPE
:
2708 case MONO_TYPE_CLASS
: {
2710 token
= mono_metadata_parse_typedef_or_ref (m
, ptr
, &ptr
);
2711 type
->data
.klass
= mono_class_get (m
, token
);
2712 if (!type
->data
.klass
)
2716 case MONO_TYPE_SZARRAY
: {
2717 MonoType
*etype
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_MOD_TYPE
, 0, ptr
, &ptr
);
2720 type
->data
.klass
= mono_class_from_mono_type (etype
);
2724 type
->data
.type
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_MOD_TYPE
, 0, ptr
, &ptr
);
2725 if (!type
->data
.type
)
2728 case MONO_TYPE_FNPTR
:
2729 type
->data
.method
= mono_metadata_parse_method_signature_full (m
, container
, 0, ptr
, &ptr
);
2731 case MONO_TYPE_ARRAY
:
2732 type
->data
.array
= mono_metadata_parse_array_full (m
, container
, ptr
, &ptr
);
2734 case MONO_TYPE_MVAR
:
2736 type
->data
.generic_param
= mono_metadata_parse_generic_param (m
, container
, type
->type
, ptr
, &ptr
);
2738 case MONO_TYPE_GENERICINST
:
2739 ok
= do_mono_metadata_parse_generic_class (type
, m
, container
, ptr
, &ptr
);
2742 g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type
->type
);
2751 * mono_metadata_free_type:
2752 * @type: type to free
2754 * Free the memory allocated for type @type which is allocated on the heap.
2757 mono_metadata_free_type (MonoType
*type
)
2759 if (type
>= builtin_types
&& type
< builtin_types
+ NBUILTIN_TYPES ())
2762 switch (type
->type
){
2763 case MONO_TYPE_OBJECT
:
2764 case MONO_TYPE_STRING
:
2765 if (!type
->data
.klass
)
2768 case MONO_TYPE_CLASS
:
2769 case MONO_TYPE_VALUETYPE
:
2770 if (type
== &type
->data
.klass
->byval_arg
|| type
== &type
->data
.klass
->this_arg
)
2774 mono_metadata_free_type (type
->data
.type
);
2776 case MONO_TYPE_FNPTR
:
2777 mono_metadata_free_method_signature (type
->data
.method
);
2779 case MONO_TYPE_ARRAY
:
2780 mono_metadata_free_array (type
->data
.array
);
2789 hex_dump (const char *buffer
, int base
, int count
)
2791 int show_header
= 1;
2799 for (i
= 0; i
< count
; i
++){
2802 printf ("\n0x%08x: ", (unsigned char) base
+ i
);
2804 printf ("%02x ", (unsigned char) (buffer
[i
]));
2811 * @mh: The Method header
2812 * @ptr: Points to the beginning of the Section Data (25.3)
2815 parse_section_data (MonoImage
*m
, MonoMethodHeader
*mh
, const unsigned char *ptr
)
2817 unsigned char sect_data_flags
;
2818 const unsigned char *sptr
;
2820 guint32 sect_data_len
;
2823 /* align on 32-bit boundary */
2824 sptr
= ptr
= dword_align (ptr
);
2825 sect_data_flags
= *ptr
;
2828 is_fat
= sect_data_flags
& METHOD_HEADER_SECTION_FAT_FORMAT
;
2830 sect_data_len
= (ptr
[2] << 16) | (ptr
[1] << 8) | ptr
[0];
2833 sect_data_len
= ptr
[0];
2837 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
2838 hex_dump (sptr, 0, sect_data_len+8);
2839 g_print ("\nheader: ");
2840 hex_dump (sptr-4, 0, 4);
2844 if (sect_data_flags
& METHOD_HEADER_SECTION_EHTABLE
) {
2845 const unsigned char *p
= dword_align (ptr
);
2847 mh
->num_clauses
= is_fat
? sect_data_len
/ 24: sect_data_len
/ 12;
2848 /* we could just store a pointer if we don't need to byteswap */
2849 mh
->clauses
= mono_image_alloc0_lock (m
, sizeof (MonoExceptionClause
) * mh
->num_clauses
);
2850 for (i
= 0; i
< mh
->num_clauses
; ++i
) {
2851 MonoExceptionClause
*ec
= &mh
->clauses
[i
];
2854 ec
->flags
= read32 (p
);
2855 ec
->try_offset
= read32 (p
+ 4);
2856 ec
->try_len
= read32 (p
+ 8);
2857 ec
->handler_offset
= read32 (p
+ 12);
2858 ec
->handler_len
= read32 (p
+ 16);
2859 tof_value
= read32 (p
+ 20);
2862 ec
->flags
= read16 (p
);
2863 ec
->try_offset
= read16 (p
+ 2);
2864 ec
->try_len
= *(p
+ 4);
2865 ec
->handler_offset
= read16 (p
+ 5);
2866 ec
->handler_len
= *(p
+ 7);
2867 tof_value
= read32 (p
+ 8);
2870 if (ec
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
) {
2871 ec
->data
.filter_offset
= tof_value
;
2872 } else if (ec
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) {
2873 ec
->data
.catch_class
= tof_value
? mono_class_get (m
, tof_value
): 0;
2875 ec
->data
.catch_class
= NULL
;
2877 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
2881 if (sect_data_flags
& METHOD_HEADER_SECTION_MORE_SECTS
)
2882 ptr
+= sect_data_len
- 4; /* LAMESPEC: it seems the size includes the header */
2889 * mono_metadata_parse_mh_full:
2890 * @m: metadata context
2891 * @generic_context: generics context
2892 * @ptr: pointer to the method header.
2894 * Decode the method header at @ptr, including pointer to the IL code,
2895 * info about local variables and optional exception tables.
2896 * This is a Mono runtime internal function.
2898 * LOCKING: Acquires the loader lock.
2900 * Returns: a MonoMethodHeader allocated from the image mempool.
2903 mono_metadata_parse_mh_full (MonoImage
*m
, MonoGenericContainer
*container
, const char *ptr
)
2905 MonoMethodHeader
*mh
;
2906 unsigned char flags
= *(const unsigned char *) ptr
;
2907 unsigned char format
= flags
& METHOD_HEADER_FORMAT_MASK
;
2909 guint32 local_var_sig_tok
, max_stack
, code_size
, init_locals
;
2910 const unsigned char *code
;
2913 g_return_val_if_fail (ptr
!= NULL
, NULL
);
2916 case METHOD_HEADER_TINY_FORMAT
:
2917 mh
= mono_image_alloc0_lock (m
, sizeof (MonoMethodHeader
));
2920 local_var_sig_tok
= 0;
2921 mh
->code_size
= flags
>> 2;
2922 mh
->code
= (unsigned char*)ptr
;
2924 case METHOD_HEADER_TINY_FORMAT1
:
2925 mh
= mono_image_alloc0_lock (m
, sizeof (MonoMethodHeader
));
2928 local_var_sig_tok
= 0;
2931 * The spec claims 3 bits, but the Beta2 is
2934 mh
->code_size
= flags
>> 2;
2935 mh
->code
= (unsigned char*)ptr
;
2937 case METHOD_HEADER_FAT_FORMAT
:
2938 fat_flags
= read16 (ptr
);
2940 hsize
= (fat_flags
>> 12) & 0xf;
2941 max_stack
= read16 (ptr
);
2943 code_size
= read32 (ptr
);
2945 local_var_sig_tok
= read32 (ptr
);
2948 if (fat_flags
& METHOD_HEADER_INIT_LOCALS
)
2953 code
= (unsigned char*)ptr
;
2955 if (!(fat_flags
& METHOD_HEADER_MORE_SECTS
))
2959 * There are more sections
2961 ptr
= (char*)code
+ code_size
;
2967 if (local_var_sig_tok
) {
2968 MonoTableInfo
*t
= &m
->tables
[MONO_TABLE_STANDALONESIG
];
2969 const char *locals_ptr
;
2970 guint32 cols
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
2971 int len
=0, i
, bsize
;
2973 mono_metadata_decode_row (t
, (local_var_sig_tok
& 0xffffff)-1, cols
, 1);
2974 locals_ptr
= mono_metadata_blob_heap (m
, cols
[MONO_STAND_ALONE_SIGNATURE
]);
2975 bsize
= mono_metadata_decode_blob_size (locals_ptr
, &locals_ptr
);
2976 if (*locals_ptr
!= 0x07)
2977 g_warning ("wrong signature for locals blob");
2979 len
= mono_metadata_decode_value (locals_ptr
, &locals_ptr
);
2980 mh
= mono_image_alloc0_lock (m
, sizeof (MonoMethodHeader
) + (len
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoType
*));
2981 mh
->num_locals
= len
;
2982 for (i
= 0; i
< len
; ++i
) {
2983 mh
->locals
[i
] = mono_metadata_parse_type_full (
2984 m
, container
, MONO_PARSE_LOCAL
, 0, locals_ptr
, &locals_ptr
);
2985 if (!mh
->locals
[i
]) {
2990 mh
= mono_image_alloc0_lock (m
, sizeof (MonoMethodHeader
));
2993 mh
->code_size
= code_size
;
2994 mh
->max_stack
= max_stack
;
2995 mh
->init_locals
= init_locals
;
2996 if (fat_flags
& METHOD_HEADER_MORE_SECTS
)
2997 parse_section_data (m
, mh
, (const unsigned char*)ptr
);
3002 * mono_metadata_parse_mh:
3003 * @generic_context: generics context
3004 * @ptr: pointer to the method header.
3006 * Decode the method header at @ptr, including pointer to the IL code,
3007 * info about local variables and optional exception tables.
3008 * This is a Mono runtime internal function.
3010 * Returns: a MonoMethodHeader.
3013 mono_metadata_parse_mh (MonoImage
*m
, const char *ptr
)
3015 MonoMethodHeader
*res
;
3017 mono_loader_lock ();
3019 res
= mono_metadata_parse_mh_full (m
, NULL
, ptr
);
3021 mono_loader_unlock ();
3027 * mono_metadata_free_mh:
3028 * @mh: a method header
3030 * Free the memory allocated for the method header.
3031 * This is a Mono runtime internal function.
3034 mono_metadata_free_mh (MonoMethodHeader
*mh
)
3036 /* Allocated from the mempool */
3040 * mono_method_header_get_code:
3041 * @header: a MonoMethodHeader pointer
3042 * @code_size: memory location for returning the code size
3043 * @max_stack: memory location for returning the max stack
3045 * Method header accessor to retreive info about the IL code properties:
3046 * a pointer to the IL code itself, the size of the code and the max number
3047 * of stack slots used by the code.
3049 * Returns: pointer to the IL code represented by the method header.
3051 const unsigned char*
3052 mono_method_header_get_code (MonoMethodHeader
*header
, guint32
* code_size
, guint32
* max_stack
)
3055 *code_size
= header
->code_size
;
3057 *max_stack
= header
->max_stack
;
3058 return header
->code
;
3062 * mono_method_header_get_locals:
3063 * @header: a MonoMethodHeader pointer
3064 * @num_locals: memory location for returning the number of local variables
3065 * @init_locals: memory location for returning the init_locals flag
3067 * Method header accessor to retreive info about the local variables:
3068 * an array of local types, the number of locals and whether the locals
3069 * are supposed to be initialized to 0 on method entry
3071 * Returns: pointer to an array of types of the local variables
3074 mono_method_header_get_locals (MonoMethodHeader
*header
, guint32
* num_locals
, gboolean
*init_locals
)
3077 *num_locals
= header
->num_locals
;
3079 *init_locals
= header
->init_locals
;
3080 return header
->locals
;
3084 * mono_method_header_get_num_clauses:
3085 * @header: a MonoMethodHeader pointer
3087 * Method header accessor to retreive the number of exception clauses.
3089 * Returns: the number of exception clauses present
3092 mono_method_header_get_num_clauses (MonoMethodHeader
*header
)
3094 return header
->num_clauses
;
3098 * mono_method_header_get_clauses:
3099 * @header: a MonoMethodHeader pointer
3100 * @method: MonoMethod the header belongs to
3101 * @iter: pointer to a iterator
3102 * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
3104 * Get the info about the exception clauses in the method. Set *iter to NULL to
3105 * initiate the iteration, then call the method repeatedly until it returns FALSE.
3106 * At each iteration, the structure pointed to by clause if filled with the
3107 * exception clause information.
3109 * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
3113 mono_method_header_get_clauses (MonoMethodHeader
*header
, MonoMethod
*method
, gpointer
*iter
, MonoExceptionClause
*clause
)
3115 MonoExceptionClause
*sc
;
3116 /* later we'll be able to use this interface to parse the clause info on demand,
3117 * without allocating anything.
3119 if (!iter
|| !header
->num_clauses
)
3122 *iter
= sc
= header
->clauses
;
3128 if (sc
< header
->clauses
+ header
->num_clauses
) {
3137 * mono_metadata_parse_field_type:
3138 * @m: metadata context to extract information from
3139 * @ptr: pointer to the field signature
3140 * @rptr: pointer updated to match the end of the decoded stream
3142 * Parses the field signature, and returns the type information for it.
3144 * Returns: The MonoType that was extracted from @ptr.
3147 mono_metadata_parse_field_type (MonoImage
*m
, short field_flags
, const char *ptr
, const char **rptr
)
3149 return mono_metadata_parse_type (m
, MONO_PARSE_FIELD
, field_flags
, ptr
, rptr
);
3153 * mono_metadata_parse_param:
3154 * @m: metadata context to extract information from
3155 * @ptr: pointer to the param signature
3156 * @rptr: pointer updated to match the end of the decoded stream
3158 * Parses the param signature, and returns the type information for it.
3160 * Returns: The MonoType that was extracted from @ptr.
3163 mono_metadata_parse_param (MonoImage
*m
, const char *ptr
, const char **rptr
)
3165 return mono_metadata_parse_type (m
, MONO_PARSE_PARAM
, 0, ptr
, rptr
);
3169 * mono_metadata_token_from_dor:
3170 * @dor_token: A TypeDefOrRef coded index
3172 * dor_token is a TypeDefOrRef coded index: it contains either
3173 * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
3174 * bits contain an index into the table.
3176 * Returns: an expanded token
3179 mono_metadata_token_from_dor (guint32 dor_index
)
3183 table
= dor_index
& 0x03;
3184 idx
= dor_index
>> 2;
3187 case 0: /* TypeDef */
3188 return MONO_TOKEN_TYPE_DEF
| idx
;
3189 case 1: /* TypeRef */
3190 return MONO_TOKEN_TYPE_REF
| idx
;
3191 case 2: /* TypeSpec */
3192 return MONO_TOKEN_TYPE_SPEC
| idx
;
3194 g_assert_not_reached ();
3201 * We use this to pass context information to the row locator
3204 int idx
; /* The index that we are trying to locate */
3205 int col_idx
; /* The index in the row where idx may be stored */
3206 MonoTableInfo
*t
; /* pointer to the table */
3211 * How the row locator works.
3216 * ___|___------> _______
3219 * A column in the rows of table A references an index in table B.
3220 * For example A may be the TYPEDEF table and B the METHODDEF table.
3222 * Given an index in table B we want to get the row in table A
3223 * where the column n references our index in B.
3225 * In the locator_t structure:
3227 * col_idx is the column number
3228 * index is the index in table B
3229 * result will be the index in table A
3232 * Table A Table B column (in table A)
3233 * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
3234 * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
3235 * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
3236 * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
3237 * METHODSEM PROPERTY ASSOCIATION (encoded index)
3239 * Note that we still don't support encoded indexes.
3243 typedef_locator (const void *a
, const void *b
)
3245 locator_t
*loc
= (locator_t
*) a
;
3246 const char *bb
= (const char *) b
;
3247 int typedef_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3248 guint32 col
, col_next
;
3250 col
= mono_metadata_decode_row_col (loc
->t
, typedef_index
, loc
->col_idx
);
3256 * Need to check that the next row is valid.
3258 if (typedef_index
+ 1 < loc
->t
->rows
) {
3259 col_next
= mono_metadata_decode_row_col (loc
->t
, typedef_index
+ 1, loc
->col_idx
);
3260 if (loc
->idx
>= col_next
)
3263 if (col
== col_next
)
3267 loc
->result
= typedef_index
;
3273 table_locator (const void *a
, const void *b
)
3275 locator_t
*loc
= (locator_t
*) a
;
3276 const char *bb
= (const char *) b
;
3277 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3280 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
3282 if (loc
->idx
== col
) {
3283 loc
->result
= table_index
;
3293 declsec_locator (const void *a
, const void *b
)
3295 locator_t
*loc
= (locator_t
*) a
;
3296 const char *bb
= (const char *) b
;
3297 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3300 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
3302 if (loc
->idx
== col
) {
3303 loc
->result
= table_index
;
3315 * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
3316 * which contains IDX.
3319 search_ptr_table (MonoImage
*image
, int table
, int idx
)
3321 MonoTableInfo
*ptrdef
= &image
->tables
[table
];
3324 /* Use a linear search to find our index in the table */
3325 for (i
= 0; i
< ptrdef
->rows
; i
++)
3326 /* All the Ptr tables have the same structure */
3327 if (mono_metadata_decode_row_col (ptrdef
, i
, 0) == idx
)
3330 if (i
< ptrdef
->rows
)
3337 * mono_metadata_typedef_from_field:
3338 * @meta: metadata context
3339 * @index: FieldDef token
3341 * Returns: the 1-based index into the TypeDef table of the type that
3342 * declared the field described by @index, or 0 if not found.
3345 mono_metadata_typedef_from_field (MonoImage
*meta
, guint32 index
)
3347 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
3353 loc
.idx
= mono_metadata_token_index (index
);
3354 loc
.col_idx
= MONO_TYPEDEF_FIELD_LIST
;
3357 if (meta
->uncompressed_metadata
)
3358 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
3360 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
3361 g_assert_not_reached ();
3363 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3364 return loc
.result
+ 1;
3368 * mono_metadata_typedef_from_method:
3369 * @meta: metadata context
3370 * @index: MethodDef token
3372 * Returns: the 1-based index into the TypeDef table of the type that
3373 * declared the method described by @index. 0 if not found.
3376 mono_metadata_typedef_from_method (MonoImage
*meta
, guint32 index
)
3378 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
3384 loc
.idx
= mono_metadata_token_index (index
);
3385 loc
.col_idx
= MONO_TYPEDEF_METHOD_LIST
;
3388 if (meta
->uncompressed_metadata
)
3389 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_METHOD_POINTER
, loc
.idx
);
3391 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
3392 g_assert_not_reached ();
3394 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3395 return loc
.result
+ 1;
3399 * mono_metadata_interfaces_from_typedef_full:
3400 * @meta: metadata context
3401 * @index: typedef token
3403 * The array of interfaces that the @index typedef token implements is returned in
3404 * @interfaces. The number of elemnts in the array is returned in @count.
3406 * LOCKING: Assumes the loader lock is held.
3408 * Returns: TRUE on success, FALSE on failure.
3411 mono_metadata_interfaces_from_typedef_full (MonoImage
*meta
, guint32 index
, MonoClass
***interfaces
, guint
*count
, MonoGenericContext
*context
)
3413 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_INTERFACEIMPL
];
3416 guint32 cols
[MONO_INTERFACEIMPL_SIZE
];
3425 loc
.idx
= mono_metadata_token_index (index
);
3426 loc
.col_idx
= MONO_INTERFACEIMPL_CLASS
;
3429 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
3434 * We may end up in the middle of the rows...
3437 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_INTERFACEIMPL_CLASS
))
3443 while (pos
< tdef
->rows
) {
3444 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
3445 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
3450 result
= mono_image_alloc0_lock (meta
, sizeof (MonoClass
*) * (pos
- start
));
3453 while (pos
< tdef
->rows
) {
3456 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
3457 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
3459 iface
= mono_class_get_full (
3460 meta
, mono_metadata_token_from_dor (cols
[MONO_INTERFACEIMPL_INTERFACE
]), context
);
3463 result
[pos
- start
] = iface
;
3466 *count
= pos
- start
;
3467 *interfaces
= result
;
3472 mono_metadata_interfaces_from_typedef (MonoImage
*meta
, guint32 index
, guint
*count
)
3474 MonoClass
**interfaces
;
3477 mono_loader_lock ();
3478 rv
= mono_metadata_interfaces_from_typedef_full (meta
, index
, &interfaces
, count
, NULL
);
3479 mono_loader_unlock ();
3487 * mono_metadata_nested_in_typedef:
3488 * @meta: metadata context
3489 * @index: typedef token
3491 * Returns: the 1-based index into the TypeDef table of the type
3492 * where the type described by @index is nested.
3493 * Retruns 0 if @index describes a non-nested type.
3496 mono_metadata_nested_in_typedef (MonoImage
*meta
, guint32 index
)
3498 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
3504 loc
.idx
= mono_metadata_token_index (index
);
3505 loc
.col_idx
= MONO_NESTED_CLASS_NESTED
;
3508 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
3511 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3512 return mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_NESTED_CLASS_ENCLOSING
) | MONO_TOKEN_TYPE_DEF
;
3516 * mono_metadata_nesting_typedef:
3517 * @meta: metadata context
3518 * @index: typedef token
3520 * Returns: the 1-based index into the TypeDef table of the first type
3521 * that is nested inside the type described by @index. The search starts at
3522 * @start_index. returns 0 if no such type is found.
3525 mono_metadata_nesting_typedef (MonoImage
*meta
, guint32 index
, guint32 start_index
)
3527 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
3529 guint32 class_index
= mono_metadata_token_index (index
);
3534 start
= start_index
;
3536 while (start
<= tdef
->rows
) {
3537 if (class_index
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_NESTED_CLASS_ENCLOSING
))
3543 if (start
> tdef
->rows
)
3550 * mono_metadata_packing_from_typedef:
3551 * @meta: metadata context
3552 * @index: token representing a type
3554 * Returns: the info stored in the ClassLAyout table for the given typedef token
3555 * into the @packing and @size pointers.
3556 * Returns 0 if the info is not found.
3559 mono_metadata_packing_from_typedef (MonoImage
*meta
, guint32 index
, guint32
*packing
, guint32
*size
)
3561 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CLASSLAYOUT
];
3563 guint32 cols
[MONO_CLASS_LAYOUT_SIZE
];
3568 loc
.idx
= mono_metadata_token_index (index
);
3569 loc
.col_idx
= MONO_CLASS_LAYOUT_PARENT
;
3572 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
3575 mono_metadata_decode_row (tdef
, loc
.result
, cols
, MONO_CLASS_LAYOUT_SIZE
);
3577 *packing
= cols
[MONO_CLASS_LAYOUT_PACKING_SIZE
];
3579 *size
= cols
[MONO_CLASS_LAYOUT_CLASS_SIZE
];
3581 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3582 return loc
.result
+ 1;
3586 * mono_metadata_custom_attrs_from_index:
3587 * @meta: metadata context
3588 * @index: token representing the parent
3590 * Returns: the 1-based index into the CustomAttribute table of the first
3591 * attribute which belongs to the metadata object described by @index.
3592 * Returns 0 if no such attribute is found.
3595 mono_metadata_custom_attrs_from_index (MonoImage
*meta
, guint32 index
)
3597 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
3604 loc
.col_idx
= MONO_CUSTOM_ATTR_PARENT
;
3607 /* FIXME: Index translation */
3609 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
3612 /* Find the first entry by searching backwards */
3613 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_CUSTOM_ATTR_PARENT
) == index
))
3616 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3617 return loc
.result
+ 1;
3621 * mono_metadata_declsec_from_index:
3622 * @meta: metadata context
3623 * @index: token representing the parent
3625 * Returns: the 0-based index into the DeclarativeSecurity table of the first
3626 * attribute which belongs to the metadata object described by @index.
3627 * Returns -1 if no such attribute is found.
3630 mono_metadata_declsec_from_index (MonoImage
*meta
, guint32 index
)
3632 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_DECLSECURITY
];
3639 loc
.col_idx
= MONO_DECL_SECURITY_PARENT
;
3642 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, declsec_locator
))
3645 /* Find the first entry by searching backwards */
3646 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_DECL_SECURITY_PARENT
) == index
))
3654 mono_backtrace (int limit
)
3659 backtrace (array
, limit
);
3660 names
= backtrace_symbols (array
, limit
);
3661 for (i
=0; i
< limit
; ++i
) {
3662 g_print ("\t%s\n", names
[i
]);
3669 /*#define __alignof__(a) sizeof(a)*/
3670 #define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
3675 * @t: the type to return the size of
3677 * Returns: the number of bytes required to hold an instance of this
3681 mono_type_size (MonoType
*t
, int *align
)
3688 *align
= __alignof__(gpointer
);
3689 return sizeof (gpointer
);
3693 case MONO_TYPE_VOID
:
3696 case MONO_TYPE_BOOLEAN
:
3697 *align
= __alignof__(gint8
);
3701 *align
= __alignof__(gint8
);
3703 case MONO_TYPE_CHAR
:
3706 *align
= __alignof__(gint16
);
3710 *align
= __alignof__(gint32
);
3713 *align
= __alignof__(float);
3717 *align
= __alignof__(gint64
);
3720 *align
= __alignof__(double);
3724 *align
= __alignof__(gpointer
);
3725 return sizeof (gpointer
);
3726 case MONO_TYPE_STRING
:
3727 *align
= __alignof__(gpointer
);
3728 return sizeof (gpointer
);
3729 case MONO_TYPE_OBJECT
:
3730 *align
= __alignof__(gpointer
);
3731 return sizeof (gpointer
);
3732 case MONO_TYPE_VALUETYPE
: {
3733 if (t
->data
.klass
->enumtype
)
3734 return mono_type_size (t
->data
.klass
->enum_basetype
, align
);
3736 return mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
3738 case MONO_TYPE_CLASS
:
3739 case MONO_TYPE_SZARRAY
:
3741 case MONO_TYPE_FNPTR
:
3742 case MONO_TYPE_ARRAY
:
3743 *align
= __alignof__(gpointer
);
3744 return sizeof (gpointer
);
3745 case MONO_TYPE_TYPEDBYREF
:
3746 return mono_class_value_size (mono_defaults
.typed_reference_class
, (guint32
*)align
);
3747 case MONO_TYPE_GENERICINST
: {
3748 MonoGenericClass
*gclass
= t
->data
.generic_class
;
3749 MonoClass
*container_class
= gclass
->container_class
;
3751 // g_assert (!gclass->inst->is_open);
3753 if (container_class
->valuetype
) {
3754 if (container_class
->enumtype
)
3755 return mono_type_size (container_class
->enum_basetype
, align
);
3757 return mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
3759 *align
= __alignof__(gpointer
);
3760 return sizeof (gpointer
);
3764 case MONO_TYPE_MVAR
:
3765 /* FIXME: Martin, this is wrong. */
3766 *align
= __alignof__(gpointer
);
3767 return sizeof (gpointer
);
3769 g_error ("mono_type_size: type 0x%02x unknown", t
->type
);
3775 * mono_type_stack_size:
3776 * @t: the type to return the size it uses on the stack
3778 * Returns: the number of bytes required to hold an instance of this
3779 * type on the runtime stack
3782 mono_type_stack_size (MonoType
*t
, int *align
)
3784 return mono_type_stack_size_internal (t
, align
, FALSE
);
3788 mono_type_stack_size_internal (MonoType
*t
, int *align
, gboolean allow_open
)
3791 #if SIZEOF_VOID_P == SIZEOF_REGISTER
3792 int stack_slot_size
= sizeof (gpointer
);
3793 int stack_slot_align
= __alignof__ (gpointer
);
3794 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
3795 int stack_slot_size
= SIZEOF_REGISTER
;
3796 int stack_slot_align
= SIZEOF_REGISTER
;
3799 g_assert (t
!= NULL
);
3805 *align
= stack_slot_align
;
3806 return stack_slot_size
;
3810 case MONO_TYPE_BOOLEAN
:
3811 case MONO_TYPE_CHAR
:
3820 case MONO_TYPE_STRING
:
3821 case MONO_TYPE_OBJECT
:
3822 case MONO_TYPE_CLASS
:
3823 case MONO_TYPE_SZARRAY
:
3825 case MONO_TYPE_FNPTR
:
3826 case MONO_TYPE_ARRAY
:
3827 *align
= stack_slot_align
;
3828 return stack_slot_size
;
3830 case MONO_TYPE_MVAR
:
3831 g_assert (allow_open
);
3832 *align
= stack_slot_align
;
3833 return stack_slot_size
;
3834 case MONO_TYPE_TYPEDBYREF
:
3835 *align
= stack_slot_align
;
3836 return stack_slot_size
* 3;
3838 *align
= __alignof__(float);
3839 return sizeof (float);
3842 *align
= __alignof__(gint64
);
3843 return sizeof (gint64
);
3845 *align
= __alignof__(double);
3846 return sizeof (double);
3847 case MONO_TYPE_VALUETYPE
: {
3850 if (t
->data
.klass
->enumtype
)
3851 return mono_type_stack_size_internal (t
->data
.klass
->enum_basetype
, align
, allow_open
);
3853 size
= mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
3855 *align
= *align
+ stack_slot_align
- 1;
3856 *align
&= ~(stack_slot_align
- 1);
3858 size
+= stack_slot_size
- 1;
3859 size
&= ~(stack_slot_size
- 1);
3864 case MONO_TYPE_GENERICINST
: {
3865 MonoGenericClass
*gclass
= t
->data
.generic_class
;
3866 MonoClass
*container_class
= gclass
->container_class
;
3869 g_assert (!gclass
->context
.class_inst
->is_open
);
3871 if (container_class
->valuetype
) {
3872 if (container_class
->enumtype
)
3873 return mono_type_stack_size_internal (container_class
->enum_basetype
, align
, allow_open
);
3875 guint32 size
= mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
3877 *align
= *align
+ stack_slot_align
- 1;
3878 *align
&= ~(stack_slot_align
- 1);
3880 size
+= stack_slot_size
- 1;
3881 size
&= ~(stack_slot_size
- 1);
3886 *align
= stack_slot_align
;
3887 return stack_slot_size
;
3891 g_error ("type 0x%02x unknown", t
->type
);
3897 mono_type_generic_inst_is_valuetype (MonoType
*type
)
3899 g_assert (type
->type
== MONO_TYPE_GENERICINST
);
3900 return type
->data
.generic_class
->container_class
->valuetype
;
3904 mono_metadata_generic_class_is_valuetype (MonoGenericClass
*gclass
)
3906 return gclass
->container_class
->valuetype
;
3910 _mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
, gboolean signature_only
)
3912 MonoGenericInst
*i1
= g1
->context
.class_inst
;
3913 MonoGenericInst
*i2
= g2
->context
.class_inst
;
3915 if (g1
->is_dynamic
!= g2
->is_dynamic
)
3917 if (!mono_metadata_class_equal (g1
->container_class
, g2
->container_class
, signature_only
))
3919 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
3921 return g1
->is_tb_open
== g2
->is_tb_open
;
3925 _mono_metadata_generic_class_container_equal (const MonoGenericClass
*g1
, MonoClass
*c2
, gboolean signature_only
)
3927 MonoGenericInst
*i1
= g1
->context
.class_inst
;
3928 MonoGenericInst
*i2
= c2
->generic_container
->context
.class_inst
;
3930 if (!mono_metadata_class_equal (g1
->container_class
, c2
, signature_only
))
3932 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
3934 return !g1
->is_tb_open
;
3938 mono_metadata_generic_context_hash (const MonoGenericContext
*context
)
3940 /* FIXME: check if this seed is good enough */
3941 guint hash
= 0xc01dfee7;
3942 if (context
->class_inst
)
3943 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->class_inst
);
3944 if (context
->method_inst
)
3945 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->method_inst
);
3950 mono_metadata_generic_context_equal (const MonoGenericContext
*g1
, const MonoGenericContext
*g2
)
3952 return g1
->class_inst
== g2
->class_inst
&& g1
->method_inst
== g2
->method_inst
;
3956 * mono_metadata_type_hash:
3959 * Computes an hash value for @t1 to be used in GHashTable.
3962 mono_metadata_type_hash (MonoType
*t1
)
3964 guint hash
= t1
->type
;
3966 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
3968 case MONO_TYPE_VALUETYPE
:
3969 case MONO_TYPE_CLASS
:
3970 case MONO_TYPE_SZARRAY
:
3971 /* check if the distribution is good enough */
3972 return ((hash
<< 5) - hash
) ^ g_str_hash (t1
->data
.klass
->name
);
3974 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (t1
->data
.type
);
3975 case MONO_TYPE_ARRAY
:
3976 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (&t1
->data
.array
->eklass
->byval_arg
);
3977 case MONO_TYPE_GENERICINST
:
3978 return ((hash
<< 5) - hash
) ^ mono_generic_class_hash (t1
->data
.generic_class
);
3984 mono_metadata_generic_param_equal (MonoGenericParam
*p1
, MonoGenericParam
*p2
, gboolean signature_only
)
3988 if (p1
->num
!= p2
->num
)
3991 if (p1
->owner
== p2
->owner
&& p1
->image
== p2
->image
)
3995 * If `signature_only' is true, we're comparing two (method) signatures.
3996 * In this case, the owner of two type parameters doesn't need to match.
3999 return signature_only
;
4003 mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
)
4007 if (c1
->generic_class
&& c2
->generic_class
)
4008 return _mono_metadata_generic_class_equal (c1
->generic_class
, c2
->generic_class
, signature_only
);
4009 if (c1
->generic_class
&& c2
->generic_container
)
4010 return _mono_metadata_generic_class_container_equal (c1
->generic_class
, c2
, signature_only
);
4011 if (c1
->generic_container
&& c2
->generic_class
)
4012 return _mono_metadata_generic_class_container_equal (c2
->generic_class
, c1
, signature_only
);
4013 if ((c1
->byval_arg
.type
== MONO_TYPE_VAR
) && (c2
->byval_arg
.type
== MONO_TYPE_VAR
))
4014 return mono_metadata_generic_param_equal (
4015 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
4016 if ((c1
->byval_arg
.type
== MONO_TYPE_MVAR
) && (c2
->byval_arg
.type
== MONO_TYPE_MVAR
))
4017 return mono_metadata_generic_param_equal (
4018 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
4019 if (signature_only
&&
4020 (c1
->byval_arg
.type
== MONO_TYPE_SZARRAY
) && (c2
->byval_arg
.type
== MONO_TYPE_SZARRAY
))
4021 return mono_metadata_class_equal (c1
->byval_arg
.data
.klass
, c2
->byval_arg
.data
.klass
, signature_only
);
4026 mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
)
4028 gpointer iter1
= 0, iter2
= 0;
4032 if (s1
->call_convention
!= s2
->call_convention
)
4034 if (s1
->sentinelpos
!= s2
->sentinelpos
)
4036 if (s1
->hasthis
!= s2
->hasthis
)
4038 if (s1
->explicit_this
!= s2
->explicit_this
)
4040 if (! do_mono_metadata_type_equal (s1
->ret
, s2
->ret
, signature_only
))
4042 if (s1
->param_count
!= s2
->param_count
)
4046 MonoType
*t1
= mono_signature_get_params (s1
, &iter1
);
4047 MonoType
*t2
= mono_signature_get_params (s2
, &iter2
);
4049 if (t1
== NULL
|| t2
== NULL
)
4051 if (! do_mono_metadata_type_equal (t1
, t2
, signature_only
))
4057 * mono_metadata_type_equal:
4061 * Determine if @t1 and @t2 represent the same type.
4062 * Returns: #TRUE if @t1 and @t2 are equal.
4065 do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
4067 if (t1
->type
!= t2
->type
|| t1
->byref
!= t2
->byref
)
4071 case MONO_TYPE_VOID
:
4072 case MONO_TYPE_BOOLEAN
:
4073 case MONO_TYPE_CHAR
:
4084 case MONO_TYPE_STRING
:
4087 case MONO_TYPE_OBJECT
:
4088 case MONO_TYPE_TYPEDBYREF
:
4090 case MONO_TYPE_VALUETYPE
:
4091 case MONO_TYPE_CLASS
:
4092 case MONO_TYPE_SZARRAY
:
4093 return mono_metadata_class_equal (t1
->data
.klass
, t2
->data
.klass
, signature_only
);
4095 return do_mono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
, signature_only
);
4096 case MONO_TYPE_ARRAY
:
4097 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
4099 return mono_metadata_class_equal (t1
->data
.array
->eklass
, t2
->data
.array
->eklass
, signature_only
);
4100 case MONO_TYPE_GENERICINST
:
4101 return _mono_metadata_generic_class_equal (
4102 t1
->data
.generic_class
, t2
->data
.generic_class
, signature_only
);
4104 return mono_metadata_generic_param_equal (
4105 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
4106 case MONO_TYPE_MVAR
:
4107 return mono_metadata_generic_param_equal (
4108 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
4109 case MONO_TYPE_FNPTR
:
4110 return mono_metadata_fnptr_equal (t1
->data
.method
, t2
->data
.method
, signature_only
);
4112 g_error ("implement type compare for %0x!", t1
->type
);
4120 mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
4122 return do_mono_metadata_type_equal (t1
, t2
, FALSE
);
4126 * mono_metadata_type_equal_full:
4129 * @signature_only: if signature only comparison should be made
4131 * Determine if @t1 and @t2 are signature compatible if @signature_only is #TRUE, otherwise
4132 * behaves the same way as mono_metadata_type_equal.
4133 * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
4134 * Returns: #TRUE if @t1 and @t2 are equal taking @signature_only into account.
4137 mono_metadata_type_equal_full (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
4139 return do_mono_metadata_type_equal (t1
, t2
, signature_only
);
4143 * mono_metadata_signature_equal:
4144 * @sig1: a signature
4145 * @sig2: another signature
4147 * Determine if @sig1 and @sig2 represent the same signature, with the
4148 * same number of arguments and the same types.
4149 * Returns: #TRUE if @sig1 and @sig2 are equal.
4152 mono_metadata_signature_equal (MonoMethodSignature
*sig1
, MonoMethodSignature
*sig2
)
4156 if (sig1
->hasthis
!= sig2
->hasthis
|| sig1
->param_count
!= sig2
->param_count
)
4159 if (sig1
->generic_param_count
!= sig2
->generic_param_count
)
4163 * We're just comparing the signatures of two methods here:
4165 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
4166 * U and V are equal here.
4168 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
4171 for (i
= 0; i
< sig1
->param_count
; i
++) {
4172 MonoType
*p1
= sig1
->params
[i
];
4173 MonoType
*p2
= sig2
->params
[i
];
4175 /* if (p1->attrs != p2->attrs)
4178 if (!do_mono_metadata_type_equal (p1
, p2
, TRUE
))
4182 if (!do_mono_metadata_type_equal (sig1
->ret
, sig2
->ret
, TRUE
))
4188 * mono_metadata_type_dup:
4189 * @mp: mempool to use
4190 * @original: type to duplicate
4192 * Returns: copy of type allocated from mempool (or from the heap, if @mp is null).
4195 mono_metadata_type_dup (MonoMemPool
*mp
, const MonoType
*o
)
4198 int sizeof_o
= sizeof (MonoType
);
4200 sizeof_o
+= (o
->num_mods
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoCustomMod
);
4202 mono_loader_lock ();
4203 r
= mp
? mono_mempool_alloc0 (mp
, sizeof_o
) : g_malloc (sizeof_o
);
4204 mono_loader_unlock ();
4206 memcpy (r
, o
, sizeof_o
);
4208 if (o
->type
== MONO_TYPE_PTR
) {
4209 r
->data
.type
= mono_metadata_type_dup (mp
, o
->data
.type
);
4210 } else if (o
->type
== MONO_TYPE_ARRAY
) {
4211 r
->data
.array
= mono_dup_array_type (mp
, o
->data
.array
);
4212 } else if (o
->type
== MONO_TYPE_FNPTR
) {
4213 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
4214 r
->data
.method
= mono_metadata_signature_deep_dup (mp
, o
->data
.method
);
4220 mono_signature_hash (MonoMethodSignature
*sig
)
4222 guint i
, res
= sig
->ret
->type
;
4224 for (i
= 0; i
< sig
->param_count
; i
++)
4225 res
= (res
<< 5) - res
+ mono_type_hash (sig
->params
[i
]);
4231 * mono_metadata_encode_value:
4232 * @value: value to encode
4233 * @buf: buffer where to write the compressed representation
4234 * @endbuf: pointer updated to point at the end of the encoded output
4236 * Encodes the value @value in the compressed representation used
4237 * in metadata and stores the result in @buf. @buf needs to be big
4238 * enough to hold the data (4 bytes).
4241 mono_metadata_encode_value (guint32 value
, char *buf
, char **endbuf
)
4247 else if (value
< 0x4000) {
4248 p
[0] = 0x80 | (value
>> 8);
4249 p
[1] = value
& 0xff;
4252 p
[0] = (value
>> 24) | 0xc0;
4253 p
[1] = (value
>> 16) & 0xff;
4254 p
[2] = (value
>> 8) & 0xff;
4255 p
[3] = value
& 0xff;
4263 * mono_metadata_field_info:
4264 * @meta: the Image the field is defined in
4265 * @index: the index in the field table representing the field
4266 * @offset: a pointer to an integer where to store the offset that
4267 * may have been specified for the field in a FieldLayout table
4268 * @rva: a pointer to the RVA of the field data in the image that
4269 * may have been defined in a FieldRVA table
4270 * @marshal_spec: a pointer to the marshal spec that may have been
4271 * defined for the field in a FieldMarshal table.
4273 * Gather info for field @index that may have been defined in the FieldLayout,
4274 * FieldRVA and FieldMarshal tables.
4275 * Either of offset, rva and marshal_spec can be NULL if you're not interested
4279 mono_metadata_field_info (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
4280 MonoMarshalSpec
**marshal_spec
)
4282 return mono_metadata_field_info_with_mempool (NULL
, meta
, index
, offset
, rva
, marshal_spec
);
4286 mono_metadata_field_info_with_mempool (MonoMemPool
*mempool
, MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
4287 MonoMarshalSpec
**marshal_spec
)
4289 MonoTableInfo
*tdef
;
4292 loc
.idx
= index
+ 1;
4293 if (meta
->uncompressed_metadata
)
4294 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
4297 tdef
= &meta
->tables
[MONO_TABLE_FIELDLAYOUT
];
4299 loc
.col_idx
= MONO_FIELD_LAYOUT_FIELD
;
4302 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4303 *offset
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_LAYOUT_OFFSET
);
4305 *offset
= (guint32
)-1;
4309 tdef
= &meta
->tables
[MONO_TABLE_FIELDRVA
];
4311 loc
.col_idx
= MONO_FIELD_RVA_FIELD
;
4314 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4316 * LAMESPEC: There is no signature, no nothing, just the raw data.
4318 *rva
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_RVA_RVA
);
4326 if ((p
= mono_metadata_get_marshal_info (meta
, index
, TRUE
))) {
4327 *marshal_spec
= mono_metadata_parse_marshal_spec_with_mempool (mempool
, p
);
4334 * mono_metadata_get_constant_index:
4335 * @meta: the Image the field is defined in
4336 * @index: the token that may have a row defined in the constants table
4337 * @hint: possible position for the row
4339 * @token must be a FieldDef, ParamDef or PropertyDef token.
4341 * Returns: the index into the Constants table or 0 if not found.
4344 mono_metadata_get_constant_index (MonoImage
*meta
, guint32 token
, guint32 hint
)
4346 MonoTableInfo
*tdef
;
4348 guint32 index
= mono_metadata_token_index (token
);
4350 tdef
= &meta
->tables
[MONO_TABLE_CONSTANT
];
4351 index
<<= MONO_HASCONSTANT_BITS
;
4352 switch (mono_metadata_token_table (token
)) {
4353 case MONO_TABLE_FIELD
:
4354 index
|= MONO_HASCONSTANT_FIEDDEF
;
4356 case MONO_TABLE_PARAM
:
4357 index
|= MONO_HASCONSTANT_PARAM
;
4359 case MONO_TABLE_PROPERTY
:
4360 index
|= MONO_HASCONSTANT_PROPERTY
;
4363 g_warning ("Not a valid token for the constant table: 0x%08x", token
);
4367 loc
.col_idx
= MONO_CONSTANT_PARENT
;
4370 /* FIXME: Index translation */
4372 if ((hint
> 0) && (hint
< tdef
->rows
) && (mono_metadata_decode_row_col (tdef
, hint
- 1, MONO_CONSTANT_PARENT
) == index
))
4375 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4376 return loc
.result
+ 1;
4382 * mono_metadata_events_from_typedef:
4383 * @meta: metadata context
4384 * @index: 0-based index (in the TypeDef table) describing a type
4386 * Returns: the 0-based index in the Event table for the events in the
4387 * type. The last event that belongs to the type (plus 1) is stored
4388 * in the @end_idx pointer.
4391 mono_metadata_events_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
4395 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_EVENTMAP
];
4403 loc
.col_idx
= MONO_EVENT_MAP_PARENT
;
4404 loc
.idx
= index
+ 1;
4406 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4409 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_EVENT_MAP_EVENTLIST
);
4410 if (loc
.result
+ 1 < tdef
->rows
) {
4411 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_EVENT_MAP_EVENTLIST
) - 1;
4413 end
= meta
->tables
[MONO_TABLE_EVENT
].rows
;
4421 * mono_metadata_methods_from_event:
4422 * @meta: metadata context
4423 * @index: 0-based index (in the Event table) describing a event
4425 * Returns: the 0-based index in the MethodDef table for the methods in the
4426 * event. The last method that belongs to the event (plus 1) is stored
4427 * in the @end_idx pointer.
4430 mono_metadata_methods_from_event (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
4434 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
4435 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
4441 if (meta
->uncompressed_metadata
)
4442 index
= search_ptr_table (meta
, MONO_TABLE_EVENT_POINTER
, index
+ 1) - 1;
4445 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
4446 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
; /* Method association coded index */
4448 if (!bsearch (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
4453 * We may end up in the middle of the rows...
4456 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
4462 while (end
< msemt
->rows
) {
4463 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
4464 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
4473 * mono_metadata_properties_from_typedef:
4474 * @meta: metadata context
4475 * @index: 0-based index (in the TypeDef table) describing a type
4477 * Returns: the 0-based index in the Property table for the properties in the
4478 * type. The last property that belongs to the type (plus 1) is stored
4479 * in the @end_idx pointer.
4482 mono_metadata_properties_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
4486 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_PROPERTYMAP
];
4494 loc
.col_idx
= MONO_PROPERTY_MAP_PARENT
;
4495 loc
.idx
= index
+ 1;
4497 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4500 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_PROPERTY_MAP_PROPERTY_LIST
);
4501 if (loc
.result
+ 1 < tdef
->rows
) {
4502 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_PROPERTY_MAP_PROPERTY_LIST
) - 1;
4504 end
= meta
->tables
[MONO_TABLE_PROPERTY
].rows
;
4512 * mono_metadata_methods_from_property:
4513 * @meta: metadata context
4514 * @index: 0-based index (in the PropertyDef table) describing a property
4516 * Returns: the 0-based index in the MethodDef table for the methods in the
4517 * property. The last method that belongs to the property (plus 1) is stored
4518 * in the @end_idx pointer.
4521 mono_metadata_methods_from_property (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
4525 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
4526 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
4532 if (meta
->uncompressed_metadata
)
4533 index
= search_ptr_table (meta
, MONO_TABLE_PROPERTY_POINTER
, index
+ 1) - 1;
4536 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
4537 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
; /* Method association coded index */
4539 if (!bsearch (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
4544 * We may end up in the middle of the rows...
4547 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
4553 while (end
< msemt
->rows
) {
4554 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
4555 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
4564 mono_metadata_implmap_from_method (MonoImage
*meta
, guint32 method_idx
)
4567 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_IMPLMAP
];
4572 /* No index translation seems to be needed */
4575 loc
.col_idx
= MONO_IMPLMAP_MEMBER
;
4576 loc
.idx
= ((method_idx
+ 1) << MONO_MEMBERFORWD_BITS
) | MONO_MEMBERFORWD_METHODDEF
;
4578 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4581 return loc
.result
+ 1;
4585 * @image: context where the image is created
4586 * @type_spec: typespec token
4588 * Creates a MonoType representing the TypeSpec indexed by the @type_spec
4592 mono_type_create_from_typespec (MonoImage
*image
, guint32 type_spec
)
4594 guint32 idx
= mono_metadata_token_index (type_spec
);
4596 guint32 cols
[MONO_TYPESPEC_SIZE
];
4599 MonoType
*type
, *type2
;
4601 mono_loader_lock ();
4603 type
= g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
4605 mono_loader_unlock ();
4609 t
= &image
->tables
[MONO_TABLE_TYPESPEC
];
4611 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPESPEC_SIZE
);
4612 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_TYPESPEC_SIGNATURE
]);
4613 len
= mono_metadata_decode_value (ptr
, &ptr
);
4615 type
= mono_image_alloc0 (image
, sizeof (MonoType
));
4617 if (*ptr
== MONO_TYPE_BYREF
) {
4622 if (!do_mono_metadata_parse_type (type
, image
, NULL
, ptr
, &ptr
)) {
4623 mono_loader_unlock ();
4627 type2
= g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
4630 mono_loader_unlock ();
4634 g_hash_table_insert (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
), type
);
4636 mono_loader_unlock ();
4643 mono_mempool_strndup (MonoMemPool
*mp
, const char *data
, guint len
)
4647 return g_strndup (data
, len
);
4648 res
= mono_mempool_alloc (mp
, len
+ 1);
4649 memcpy (res
, data
, len
);
4655 mono_metadata_parse_marshal_spec (MonoImage
*image
, const char *ptr
)
4657 return mono_metadata_parse_marshal_spec_with_mempool (NULL
, ptr
);
4661 mono_metadata_parse_marshal_spec_with_mempool (MonoMemPool
*mempool
, const char *ptr
)
4663 MonoMarshalSpec
*res
;
4665 const char *start
= ptr
;
4667 /* fixme: this is incomplete, but I cant find more infos in the specs */
4670 res
= mono_mempool_alloc0 (mempool
, sizeof (MonoMarshalSpec
));
4672 res
= g_new0 (MonoMarshalSpec
, 1);
4674 len
= mono_metadata_decode_value (ptr
, &ptr
);
4675 res
->native
= *ptr
++;
4677 if (res
->native
== MONO_NATIVE_LPARRAY
) {
4678 res
->data
.array_data
.param_num
= -1;
4679 res
->data
.array_data
.num_elem
= -1;
4680 res
->data
.array_data
.elem_mult
= -1;
4682 if (ptr
- start
<= len
)
4683 res
->data
.array_data
.elem_type
= *ptr
++;
4684 if (ptr
- start
<= len
)
4685 res
->data
.array_data
.param_num
= mono_metadata_decode_value (ptr
, &ptr
);
4686 if (ptr
- start
<= len
)
4687 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
4688 if (ptr
- start
<= len
) {
4690 * LAMESPEC: Older spec versions say this parameter comes before
4691 * num_elem. Never spec versions don't talk about elem_mult at
4692 * all, but csc still emits it, and it is used to distinguish
4693 * between param_num being 0, and param_num being omitted.
4694 * So if (param_num == 0) && (num_elem > 0), then
4695 * elem_mult == 0 -> the array size is num_elem
4696 * elem_mult == 1 -> the array size is @param_num + num_elem
4698 res
->data
.array_data
.elem_mult
= mono_metadata_decode_value (ptr
, &ptr
);
4702 if (res
->native
== MONO_NATIVE_BYVALTSTR
) {
4703 if (ptr
- start
<= len
)
4704 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
4707 if (res
->native
== MONO_NATIVE_BYVALARRAY
) {
4708 if (ptr
- start
<= len
)
4709 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
4712 if (res
->native
== MONO_NATIVE_CUSTOM
) {
4713 /* skip unused type guid */
4714 len
= mono_metadata_decode_value (ptr
, &ptr
);
4716 /* skip unused native type name */
4717 len
= mono_metadata_decode_value (ptr
, &ptr
);
4719 /* read custom marshaler type name */
4720 len
= mono_metadata_decode_value (ptr
, &ptr
);
4721 res
->data
.custom_data
.custom_name
= mono_mempool_strndup (mempool
, ptr
, len
);
4723 /* read cookie string */
4724 len
= mono_metadata_decode_value (ptr
, &ptr
);
4725 res
->data
.custom_data
.cookie
= mono_mempool_strndup (mempool
, ptr
, len
);
4728 if (res
->native
== MONO_NATIVE_SAFEARRAY
) {
4729 res
->data
.safearray_data
.elem_type
= 0;
4730 res
->data
.safearray_data
.num_elem
= 0;
4731 if (ptr
- start
<= len
)
4732 res
->data
.safearray_data
.elem_type
= *ptr
++;
4733 if (ptr
- start
<= len
)
4734 res
->data
.safearray_data
.num_elem
= *ptr
++;
4740 mono_metadata_free_marshal_spec (MonoMarshalSpec
*spec
)
4742 if (spec
->native
== MONO_NATIVE_CUSTOM
) {
4743 g_free (spec
->data
.custom_data
.custom_name
);
4744 g_free (spec
->data
.custom_data
.cookie
);
4750 * mono_type_to_unmanaged:
4752 * Returns: A MonoMarshalNative enumeration value (MONO_NATIVE_) value
4753 * describing the underlying native reprensetation of the type.
4755 * In addition the value pointed by
4756 * "conv" will contain the kind of marshalling required for this
4757 * particular type one of the MONO_MARSHAL_CONV_ enumeration values.
4760 mono_type_to_unmanaged (MonoType
*type
, MonoMarshalSpec
*mspec
, gboolean as_field
,
4761 gboolean unicode
, MonoMarshalConv
*conv
)
4763 MonoMarshalConv dummy_conv
;
4769 *conv
= MONO_MARSHAL_CONV_NONE
;
4772 return MONO_NATIVE_UINT
;
4776 case MONO_TYPE_BOOLEAN
:
4778 switch (mspec
->native
) {
4779 case MONO_NATIVE_VARIANTBOOL
:
4780 *conv
= MONO_MARSHAL_CONV_BOOL_VARIANTBOOL
;
4781 return MONO_NATIVE_VARIANTBOOL
;
4782 case MONO_NATIVE_BOOLEAN
:
4783 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
4784 return MONO_NATIVE_BOOLEAN
;
4785 case MONO_NATIVE_I1
:
4786 case MONO_NATIVE_U1
:
4787 return mspec
->native
;
4789 g_error ("cant marshal bool to native type %02x", mspec
->native
);
4792 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
4793 return MONO_NATIVE_BOOLEAN
;
4794 case MONO_TYPE_CHAR
: return MONO_NATIVE_U2
;
4795 case MONO_TYPE_I1
: return MONO_NATIVE_I1
;
4796 case MONO_TYPE_U1
: return MONO_NATIVE_U1
;
4797 case MONO_TYPE_I2
: return MONO_NATIVE_I2
;
4798 case MONO_TYPE_U2
: return MONO_NATIVE_U2
;
4799 case MONO_TYPE_I4
: return MONO_NATIVE_I4
;
4800 case MONO_TYPE_U4
: return MONO_NATIVE_U4
;
4801 case MONO_TYPE_I8
: return MONO_NATIVE_I8
;
4802 case MONO_TYPE_U8
: return MONO_NATIVE_U8
;
4803 case MONO_TYPE_R4
: return MONO_NATIVE_R4
;
4804 case MONO_TYPE_R8
: return MONO_NATIVE_R8
;
4805 case MONO_TYPE_STRING
:
4807 switch (mspec
->native
) {
4808 case MONO_NATIVE_BSTR
:
4809 *conv
= MONO_MARSHAL_CONV_STR_BSTR
;
4810 return MONO_NATIVE_BSTR
;
4811 case MONO_NATIVE_LPSTR
:
4812 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
4813 return MONO_NATIVE_LPSTR
;
4814 case MONO_NATIVE_LPWSTR
:
4815 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
4816 return MONO_NATIVE_LPWSTR
;
4817 case MONO_NATIVE_LPTSTR
:
4818 *conv
= MONO_MARSHAL_CONV_STR_LPTSTR
;
4819 return MONO_NATIVE_LPTSTR
;
4820 case MONO_NATIVE_ANSIBSTR
:
4821 *conv
= MONO_MARSHAL_CONV_STR_ANSIBSTR
;
4822 return MONO_NATIVE_ANSIBSTR
;
4823 case MONO_NATIVE_TBSTR
:
4824 *conv
= MONO_MARSHAL_CONV_STR_TBSTR
;
4825 return MONO_NATIVE_TBSTR
;
4826 case MONO_NATIVE_BYVALTSTR
:
4828 *conv
= MONO_MARSHAL_CONV_STR_BYVALWSTR
;
4830 *conv
= MONO_MARSHAL_CONV_STR_BYVALSTR
;
4831 return MONO_NATIVE_BYVALTSTR
;
4833 g_error ("Can not marshal string to native type '%02x': Invalid managed/unmanaged type combination (String fields must be paired with LPStr, LPWStr, BStr or ByValTStr).", mspec
->native
);
4837 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
4838 return MONO_NATIVE_LPWSTR
;
4841 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
4842 return MONO_NATIVE_LPSTR
;
4844 case MONO_TYPE_PTR
: return MONO_NATIVE_UINT
;
4845 case MONO_TYPE_VALUETYPE
: /*FIXME*/
4846 if (type
->data
.klass
->enumtype
) {
4847 t
= type
->data
.klass
->enum_basetype
->type
;
4850 if (type
->data
.klass
== mono_defaults
.handleref_class
){
4851 *conv
= MONO_MARSHAL_CONV_HANDLEREF
;
4852 return MONO_NATIVE_INT
;
4854 return MONO_NATIVE_STRUCT
;
4855 case MONO_TYPE_SZARRAY
:
4856 case MONO_TYPE_ARRAY
:
4858 switch (mspec
->native
) {
4859 case MONO_NATIVE_BYVALARRAY
:
4860 if ((type
->data
.klass
->element_class
== mono_defaults
.char_class
) && !unicode
)
4861 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY
;
4863 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALARRAY
;
4864 return MONO_NATIVE_BYVALARRAY
;
4865 case MONO_NATIVE_SAFEARRAY
:
4866 *conv
= MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
;
4867 return MONO_NATIVE_SAFEARRAY
;
4868 case MONO_NATIVE_LPARRAY
:
4869 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
4870 return MONO_NATIVE_LPARRAY
;
4872 g_error ("cant marshal array as native type %02x", mspec
->native
);
4876 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
4877 return MONO_NATIVE_LPARRAY
;
4878 case MONO_TYPE_I
: return MONO_NATIVE_INT
;
4879 case MONO_TYPE_U
: return MONO_NATIVE_UINT
;
4880 case MONO_TYPE_CLASS
:
4881 case MONO_TYPE_OBJECT
: {
4882 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
4884 switch (mspec
->native
) {
4885 case MONO_NATIVE_STRUCT
:
4886 return MONO_NATIVE_STRUCT
;
4887 case MONO_NATIVE_CUSTOM
:
4888 return MONO_NATIVE_CUSTOM
;
4889 case MONO_NATIVE_INTERFACE
:
4890 *conv
= MONO_MARSHAL_CONV_OBJECT_INTERFACE
;
4891 return MONO_NATIVE_INTERFACE
;
4892 case MONO_NATIVE_IDISPATCH
:
4893 *conv
= MONO_MARSHAL_CONV_OBJECT_IDISPATCH
;
4894 return MONO_NATIVE_IDISPATCH
;
4895 case MONO_NATIVE_IUNKNOWN
:
4896 *conv
= MONO_MARSHAL_CONV_OBJECT_IUNKNOWN
;
4897 return MONO_NATIVE_IUNKNOWN
;
4898 case MONO_NATIVE_FUNC
:
4899 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
4900 type
->data
.klass
== mono_defaults
.delegate_class
||
4901 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
4902 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
4903 return MONO_NATIVE_FUNC
;
4907 g_error ("cant marshal object as native type %02x", mspec
->native
);
4910 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
4911 type
->data
.klass
== mono_defaults
.delegate_class
||
4912 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
4913 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
4914 return MONO_NATIVE_FUNC
;
4916 if (mono_defaults
.safehandle_class
&& type
->data
.klass
== mono_defaults
.safehandle_class
){
4917 *conv
= MONO_MARSHAL_CONV_SAFEHANDLE
;
4918 return MONO_NATIVE_INT
;
4920 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
4921 return MONO_NATIVE_STRUCT
;
4923 case MONO_TYPE_FNPTR
: return MONO_NATIVE_FUNC
;
4924 case MONO_TYPE_GENERICINST
:
4925 type
= &type
->data
.generic_class
->container_class
->byval_arg
;
4928 case MONO_TYPE_TYPEDBYREF
:
4930 g_error ("type 0x%02x not handled in marshal", t
);
4932 return MONO_NATIVE_MAX
;
4936 mono_metadata_get_marshal_info (MonoImage
*meta
, guint32 idx
, gboolean is_field
)
4939 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_FIELDMARSHAL
];
4945 loc
.col_idx
= MONO_FIELD_MARSHAL_PARENT
;
4946 loc
.idx
= ((idx
+ 1) << MONO_HAS_FIELD_MARSHAL_BITS
) | (is_field
? MONO_HAS_FIELD_MARSHAL_FIELDSREF
: MONO_HAS_FIELD_MARSHAL_PARAMDEF
);
4948 /* FIXME: Index translation */
4950 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4953 return mono_metadata_blob_heap (meta
, mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_MARSHAL_NATIVE_TYPE
));
4957 method_from_method_def_or_ref (MonoImage
*m
, guint32 tok
, MonoGenericContext
*context
)
4959 guint32 idx
= tok
>> MONO_METHODDEFORREF_BITS
;
4961 switch (tok
& MONO_METHODDEFORREF_MASK
) {
4962 case MONO_METHODDEFORREF_METHODDEF
:
4963 return mono_get_method_full (m
, MONO_TOKEN_METHOD_DEF
| idx
, NULL
, context
);
4964 case MONO_METHODDEFORREF_METHODREF
:
4965 return mono_get_method_full (m
, MONO_TOKEN_MEMBER_REF
| idx
, NULL
, context
);
4967 g_assert_not_reached ();
4972 * mono_class_get_overrides_full:
4974 * Return the method overrides belonging to class @type_token in @overrides, and
4975 * the number of overrides in @num_overrides.
4977 * Returns: TRUE on success, FALSE on failure.
4980 mono_class_get_overrides_full (MonoImage
*image
, guint32 type_token
, MonoMethod
***overrides
, gint32
*num_overrides
,
4981 MonoGenericContext
*generic_context
)
4984 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_METHODIMPL
];
4987 guint32 cols
[MONO_METHODIMPL_SIZE
];
4988 MonoMethod
**result
;
4999 loc
.col_idx
= MONO_METHODIMPL_CLASS
;
5000 loc
.idx
= mono_metadata_token_index (type_token
);
5002 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5008 * We may end up in the middle of the rows...
5011 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_METHODIMPL_CLASS
))
5016 while (end
< tdef
->rows
) {
5017 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, end
, MONO_METHODIMPL_CLASS
))
5023 result
= g_new (MonoMethod
*, num
* 2);
5024 for (i
= 0; i
< num
; ++i
) {
5027 mono_metadata_decode_row (tdef
, start
+ i
, cols
, MONO_METHODIMPL_SIZE
);
5028 method
= method_from_method_def_or_ref (
5029 image
, cols
[MONO_METHODIMPL_DECLARATION
], generic_context
);
5032 result
[i
* 2] = method
;
5033 method
= method_from_method_def_or_ref (
5034 image
, cols
[MONO_METHODIMPL_BODY
], generic_context
);
5037 result
[i
* 2 + 1] = method
;
5040 *overrides
= result
;
5042 *num_overrides
= num
;
5047 * mono_guid_to_string:
5049 * Converts a 16 byte Microsoft GUID to the standard string representation.
5052 mono_guid_to_string (const guint8
*guid
)
5054 return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
5055 guid
[3], guid
[2], guid
[1], guid
[0],
5059 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
5063 get_constraints (MonoImage
*image
, int owner
, MonoClass
***constraints
, MonoGenericContainer
*container
)
5065 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
5066 guint32 cols
[MONO_GENPARCONSTRAINT_SIZE
];
5067 guint32 i
, token
, found
;
5068 MonoClass
*klass
, **res
;
5069 GList
*cons
= NULL
, *tmp
;
5070 MonoGenericContext
*context
= &container
->context
;
5072 *constraints
= NULL
;
5074 for (i
= 0; i
< tdef
->rows
; ++i
) {
5075 mono_metadata_decode_row (tdef
, i
, cols
, MONO_GENPARCONSTRAINT_SIZE
);
5076 if (cols
[MONO_GENPARCONSTRAINT_GENERICPAR
] == owner
) {
5077 token
= mono_metadata_token_from_dor (cols
[MONO_GENPARCONSTRAINT_CONSTRAINT
]);
5078 klass
= mono_class_get_full (image
, token
, context
);
5079 cons
= g_list_append (cons
, klass
);
5082 /* contiguous list finished */
5089 res
= g_new0 (MonoClass
*, found
+ 1);
5090 for (i
= 0, tmp
= cons
; i
< found
; ++i
, tmp
= tmp
->next
) {
5091 res
[i
] = tmp
->data
;
5099 * mono_metadata_get_generic_param_row:
5102 * @token: TypeOrMethodDef token, owner for GenericParam
5103 * @owner: coded token, set on return
5105 * Returns: 1-based row-id in the GenericParam table whose
5106 * owner is @token. 0 if not found.
5109 mono_metadata_get_generic_param_row (MonoImage
*image
, guint32 token
, guint32
*owner
)
5111 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
5118 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPEDEF
)
5119 *owner
= MONO_TYPEORMETHOD_TYPE
;
5120 else if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
5121 *owner
= MONO_TYPEORMETHOD_METHOD
;
5123 g_error ("wrong token %x to get_generic_param_row", token
);
5126 *owner
|= mono_metadata_token_index (token
) << MONO_TYPEORMETHOD_BITS
;
5129 loc
.col_idx
= MONO_GENERICPARAM_OWNER
;
5132 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5135 /* Find the first entry by searching backwards */
5136 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_GENERICPARAM_OWNER
) == loc
.idx
))
5139 return loc
.result
+ 1;
5143 mono_metadata_has_generic_params (MonoImage
*image
, guint32 token
)
5146 return mono_metadata_get_generic_param_row (image
, token
, &owner
);
5150 * mono_metadata_load_generic_param_constraints:
5152 * Load the generic parameter constraints for the newly created generic type or method
5153 * represented by @token and @container. The @container is the new container which has
5154 * been returned by a call to mono_metadata_load_generic_params() with this @token.
5157 mono_metadata_load_generic_param_constraints (MonoImage
*image
, guint32 token
,
5158 MonoGenericContainer
*container
)
5160 guint32 start_row
, i
, owner
;
5161 if (! (start_row
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
5163 for (i
= 0; i
< container
->type_argc
; i
++)
5164 get_constraints (image
, start_row
+ i
, &container
->type_params
[i
].constraints
, container
);
5168 * mono_metadata_load_generic_params:
5170 * Load the type parameters from the type or method definition @token.
5172 * Use this method after parsing a type or method definition to figure out whether it's a generic
5173 * type / method. When parsing a method definition, @parent_container points to the generic container
5174 * of the current class, if any.
5176 * Note: This method does not load the constraints: for typedefs, this has to be done after fully
5177 * creating the type.
5179 * Returns: NULL if @token is not a generic type or method definition or the new generic container.
5181 * LOCKING: Acquires the loader lock
5184 MonoGenericContainer
*
5185 mono_metadata_load_generic_params (MonoImage
*image
, guint32 token
, MonoGenericContainer
*parent_container
)
5187 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
5188 guint32 cols
[MONO_GENERICPARAM_SIZE
];
5189 guint32 i
, owner
= 0, n
;
5190 MonoGenericContainer
*container
;
5191 MonoGenericParam
*params
;
5192 MonoGenericContext
*context
;
5194 if (!(i
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
5196 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
5199 container
= mono_image_alloc0_lock (image
, sizeof (MonoGenericContainer
));
5202 params
= g_realloc (params
, sizeof (MonoGenericParam
) * n
);
5203 params
[n
- 1].owner
= container
;
5204 params
[n
- 1].pklass
= NULL
;
5205 params
[n
- 1].flags
= cols
[MONO_GENERICPARAM_FLAGS
];
5206 params
[n
- 1].num
= cols
[MONO_GENERICPARAM_NUMBER
];
5207 params
[n
- 1].name
= mono_metadata_string_heap (image
, cols
[MONO_GENERICPARAM_NAME
]);
5208 params
[n
- 1].constraints
= NULL
;
5209 if (++i
> tdef
->rows
)
5211 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
5212 } while (cols
[MONO_GENERICPARAM_OWNER
] == owner
);
5214 container
->type_argc
= n
;
5215 container
->type_params
= mono_image_alloc0_lock (image
, sizeof (MonoGenericParam
) * n
);
5216 memcpy (container
->type_params
, params
, sizeof (MonoGenericParam
) * n
);
5218 container
->parent
= parent_container
;
5220 if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
5221 container
->is_method
= 1;
5223 g_assert (container
->parent
== NULL
|| container
->is_method
);
5225 context
= &container
->context
;
5226 if (container
->is_method
) {
5227 context
->class_inst
= container
->parent
? container
->parent
->context
.class_inst
: NULL
;
5228 context
->method_inst
= mono_get_shared_generic_inst (container
);
5230 context
->class_inst
= mono_get_shared_generic_inst (container
);
5237 mono_get_shared_generic_inst (MonoGenericContainer
*container
)
5239 MonoType
**type_argv
;
5241 MonoGenericInst
*nginst
;
5244 type_argv
= g_new0 (MonoType
*, container
->type_argc
);
5245 helper
= g_new0 (MonoType
, container
->type_argc
);
5247 for (i
= 0; i
< container
->type_argc
; i
++) {
5248 MonoType
*t
= &helper
[i
];
5250 t
->type
= container
->is_method
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
5251 t
->data
.generic_param
= &container
->type_params
[i
];
5256 nginst
= mono_metadata_get_generic_inst (container
->type_argc
, type_argv
);
5265 mono_type_is_byref (MonoType
*type
)
5271 mono_type_get_type (MonoType
*type
)
5276 /* For MONO_TYPE_FNPTR */
5277 MonoMethodSignature
*
5278 mono_type_get_signature (MonoType
*type
)
5280 return type
->data
.method
;
5283 /* For MONO_TYPE_CLASS, VALUETYPE */
5285 mono_type_get_class (MonoType
*type
)
5287 return type
->data
.klass
;
5290 /* For MONO_TYPE_ARRAY */
5292 mono_type_get_array_type (MonoType
*type
)
5294 return type
->data
.array
;
5297 /* For MONO_TYPE_PTR */
5299 mono_type_get_ptr_type (MonoType
*type
)
5301 return type
->data
.type
;
5305 mono_type_get_modifiers (MonoType
*type
, gboolean
*is_required
, gpointer
*iter
)
5307 /* FIXME: implement */
5312 mono_signature_get_return_type (MonoMethodSignature
*sig
)
5318 mono_signature_get_params (MonoMethodSignature
*sig
, gpointer
*iter
)
5324 /* start from the first */
5325 if (sig
->param_count
) {
5326 *iter
= &sig
->params
[0];
5327 return sig
->params
[0];
5335 if (type
< &sig
->params
[sig
->param_count
]) {
5343 mono_signature_get_param_count (MonoMethodSignature
*sig
)
5345 return sig
->param_count
;
5349 mono_signature_get_call_conv (MonoMethodSignature
*sig
)
5351 return sig
->call_convention
;
5355 mono_signature_vararg_start (MonoMethodSignature
*sig
)
5357 return sig
->sentinelpos
;
5361 mono_signature_is_instance (MonoMethodSignature
*sig
)
5363 return sig
->hasthis
;
5367 mono_signature_explicit_this (MonoMethodSignature
*sig
)
5369 return sig
->explicit_this
;
5372 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
5374 mono_aligned_addr_hash (gconstpointer ptr
)
5376 return GPOINTER_TO_UINT (ptr
) >> 3;
5380 * If @field belongs to an inflated generic class, return the corresponding field of the
5381 * generic type definition class.
5384 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField
*field
)
5389 if (!field
->parent
->generic_class
)
5392 gtd
= field
->parent
->generic_class
->container_class
;
5393 offset
= field
- field
->parent
->fields
;
5394 return gtd
->fields
+ offset
;
5398 * If @event belongs to an inflated generic class, return the corresponding event of the
5399 * generic type definition class.
5402 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent
*event
)
5407 if (!event
->parent
->generic_class
)
5410 gtd
= event
->parent
->generic_class
->container_class
;
5411 offset
= event
- event
->parent
->events
;
5412 return gtd
->events
+ offset
;
5416 * If @property belongs to an inflated generic class, return the corresponding property of the
5417 * generic type definition class.
5420 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty
*property
)
5425 if (!property
->parent
->generic_class
)
5428 gtd
= property
->parent
->generic_class
->container_class
;
5429 offset
= property
- property
->parent
->properties
;
5430 return gtd
->properties
+ offset
;