2 * metadata.c: Routines for accessing the metadata
5 * Miguel de Icaza (miguel@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
21 #include "tabledefs.h"
22 #include "mono-endian.h"
24 #include "tokentype.h"
25 #include "metadata-internals.h"
26 #include "class-internals.h"
27 #include "verify-internals.h"
30 #include "gc-internal.h"
31 #include <mono/utils/mono-error-internals.h>
33 /* Auxiliary structure used for caching inflated signatures */
35 MonoMethodSignature
*sig
;
36 MonoGenericContext context
;
37 } MonoInflatedMethodSignature
;
39 static gboolean
do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
40 const char *ptr
, const char **rptr
);
42 static gboolean
do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
);
43 static gboolean
mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
);
44 static gboolean
mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
);
45 static gboolean
_mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
,
46 gboolean signature_only
);
47 static GSList
* free_generic_inst_dependents (MonoGenericInst
*ginst
);
48 static void free_generic_inst (MonoGenericInst
*ginst
);
49 static GSList
* free_generic_class_dependents (MonoGenericClass
*ginst
);
50 static void free_generic_class (MonoGenericClass
*ginst
);
51 static void free_inflated_method (MonoMethodInflated
*method
);
52 static void free_inflated_signature (MonoInflatedMethodSignature
*sig
);
53 static void mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
, MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
);
56 * This enumeration is used to describe the data types in the metadata
67 /* Index into Blob heap */
70 /* Index into String heap */
76 /* Pointer into a table */
79 /* HasConstant:Parent pointer (Param, Field or Property) */
82 /* HasCustomAttribute index. Indexes any table except CustomAttribute */
85 /* CustomAttributeType encoded index */
88 /* HasDeclSecurity index: TypeDef Method or Assembly */
91 /* Implementation coded index: File, Export AssemblyRef */
94 /* HasFieldMarshal coded index: Field or Param table */
97 /* MemberForwardedIndex: Field or Method */
100 /* TypeDefOrRef coded index: typedef, typeref, typespec */
103 /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
106 /* MethodDefOrRef coded index: Method or Member Ref table */
109 /* HasSemantic coded index: Event or Property */
112 /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
116 const static unsigned char TableSchemas
[] = {
117 #define ASSEMBLY_SCHEMA_OFFSET 0
118 MONO_MT_UINT32
, /* "HashId" }, */
119 MONO_MT_UINT16
, /* "Major" }, */
120 MONO_MT_UINT16
, /* "Minor" }, */
121 MONO_MT_UINT16
, /* "BuildNumber" }, */
122 MONO_MT_UINT16
, /* "RevisionNumber" }, */
123 MONO_MT_UINT32
, /* "Flags" }, */
124 MONO_MT_BLOB_IDX
, /* "PublicKey" }, */
125 MONO_MT_STRING_IDX
, /* "Name" }, */
126 MONO_MT_STRING_IDX
, /* "Culture" }, */
129 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
130 MONO_MT_UINT32
, /* "OSPlatformID" }, */
131 MONO_MT_UINT32
, /* "OSMajor" }, */
132 MONO_MT_UINT32
, /* "OSMinor" }, */
135 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
136 MONO_MT_UINT32
, /* "Processor" }, */
139 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
140 MONO_MT_UINT16
, /* "Major" }, */
141 MONO_MT_UINT16
, /* "Minor" }, */
142 MONO_MT_UINT16
, /* "Build" }, */
143 MONO_MT_UINT16
, /* "Revision" }, */
144 MONO_MT_UINT32
, /* "Flags" }, */
145 MONO_MT_BLOB_IDX
, /* "PublicKeyOrToken" }, */
146 MONO_MT_STRING_IDX
, /* "Name" }, */
147 MONO_MT_STRING_IDX
, /* "Culture" }, */
148 MONO_MT_BLOB_IDX
, /* "HashValue" }, */
151 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
152 MONO_MT_UINT32
, /* "OSPlatformID" }, */
153 MONO_MT_UINT32
, /* "OSMajorVersion" }, */
154 MONO_MT_UINT32
, /* "OSMinorVersion" }, */
155 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
158 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
159 MONO_MT_UINT32
, /* "Processor" }, */
160 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
163 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
164 MONO_MT_UINT16
, /* "PackingSize" }, */
165 MONO_MT_UINT32
, /* "ClassSize" }, */
166 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
169 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
170 MONO_MT_UINT8
, /* "Type" }, */
171 MONO_MT_UINT8
, /* "PaddingZero" }, */
172 MONO_MT_CONST_IDX
, /* "Parent" }, */
173 MONO_MT_BLOB_IDX
, /* "Value" }, */
176 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
177 MONO_MT_HASCAT_IDX
, /* "Parent" }, */
178 MONO_MT_CAT_IDX
, /* "Type" }, */
179 MONO_MT_BLOB_IDX
, /* "Value" }, */
182 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
183 MONO_MT_UINT16
, /* "Action" }, */
184 MONO_MT_HASDEC_IDX
, /* "Parent" }, */
185 MONO_MT_BLOB_IDX
, /* "PermissionSet" }, */
188 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
189 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
190 MONO_MT_TABLE_IDX
, /* "EventList:Event" }, */
193 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
194 MONO_MT_UINT16
, /* "EventFlags#EventAttribute" }, */
195 MONO_MT_STRING_IDX
, /* "Name" }, */
196 MONO_MT_TDOR_IDX
, /* "EventType" }, TypeDef or TypeRef or TypeSpec */
199 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
200 MONO_MT_TABLE_IDX
, /* "Event" }, */
203 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
204 MONO_MT_UINT32
, /* "Flags" }, */
205 MONO_MT_TABLE_IDX
, /* "TypeDefId" }, */
206 MONO_MT_STRING_IDX
, /* "TypeName" }, */
207 MONO_MT_STRING_IDX
, /* "TypeNameSpace" }, */
208 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
211 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
212 MONO_MT_UINT16
, /* "Flags" }, */
213 MONO_MT_STRING_IDX
, /* "Name" }, */
214 MONO_MT_BLOB_IDX
, /* "Signature" }, */
217 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
218 MONO_MT_UINT32
, /* "Offset" }, */
219 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
222 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
223 MONO_MT_HFM_IDX
, /* "Parent" }, */
224 MONO_MT_BLOB_IDX
, /* "NativeType" }, */
227 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
228 MONO_MT_UINT32
, /* "RVA" }, */
229 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
232 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
233 MONO_MT_TABLE_IDX
, /* "Field" }, */
236 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
237 MONO_MT_UINT32
, /* "Flags" }, */
238 MONO_MT_STRING_IDX
, /* "Name" }, */
239 MONO_MT_BLOB_IDX
, /* "Value" }, */
242 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
243 MONO_MT_UINT16
, /* "MappingFlag" }, */
244 MONO_MT_MF_IDX
, /* "MemberForwarded" }, */
245 MONO_MT_STRING_IDX
, /* "ImportName" }, */
246 MONO_MT_TABLE_IDX
, /* "ImportScope:ModuleRef" }, */
249 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
250 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
251 MONO_MT_TDOR_IDX
, /* "Interface=TypeDefOrRef" }, */
254 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
255 MONO_MT_UINT32
, /* "Offset" }, */
256 MONO_MT_UINT32
, /* "Flags" }, */
257 MONO_MT_STRING_IDX
, /* "Name" }, */
258 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
261 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
262 MONO_MT_MRP_IDX
, /* "Class" }, */
263 MONO_MT_STRING_IDX
, /* "Name" }, */
264 MONO_MT_BLOB_IDX
, /* "Signature" }, */
267 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
268 MONO_MT_UINT32
, /* "RVA" }, */
269 MONO_MT_UINT16
, /* "ImplFlags#MethodImplAttributes" }, */
270 MONO_MT_UINT16
, /* "Flags#MethodAttribute" }, */
271 MONO_MT_STRING_IDX
, /* "Name" }, */
272 MONO_MT_BLOB_IDX
, /* "Signature" }, */
273 MONO_MT_TABLE_IDX
, /* "ParamList:Param" }, */
276 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
277 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
278 MONO_MT_MDOR_IDX
, /* "MethodBody" }, */
279 MONO_MT_MDOR_IDX
, /* "MethodDeclaration" }, */
282 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
283 MONO_MT_UINT16
, /* "MethodSemantic" }, */
284 MONO_MT_TABLE_IDX
, /* "Method:Method" }, */
285 MONO_MT_HS_IDX
, /* "Association" }, */
288 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
289 MONO_MT_TABLE_IDX
, /* "Method" }, */
292 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
293 MONO_MT_UINT16
, /* "Generation" }, */
294 MONO_MT_STRING_IDX
, /* "Name" }, */
295 MONO_MT_GUID_IDX
, /* "MVID" }, */
296 MONO_MT_GUID_IDX
, /* "EncID" }, */
297 MONO_MT_GUID_IDX
, /* "EncBaseID" }, */
300 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
301 MONO_MT_STRING_IDX
, /* "Name" }, */
304 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
305 MONO_MT_TABLE_IDX
, /* "NestedClass:TypeDef" }, */
306 MONO_MT_TABLE_IDX
, /* "EnclosingClass:TypeDef" }, */
309 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
310 MONO_MT_UINT16
, /* "Flags" }, */
311 MONO_MT_UINT16
, /* "Sequence" }, */
312 MONO_MT_STRING_IDX
, /* "Name" }, */
315 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
316 MONO_MT_TABLE_IDX
, /* "Param" }, */
319 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
320 MONO_MT_UINT16
, /* "Flags" }, */
321 MONO_MT_STRING_IDX
, /* "Name" }, */
322 MONO_MT_BLOB_IDX
, /* "Type" }, */
325 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
326 MONO_MT_TABLE_IDX
, /* "Property" }, */
329 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
330 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
331 MONO_MT_TABLE_IDX
, /* "PropertyList:Property" }, */
334 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
335 MONO_MT_BLOB_IDX
, /* "Signature" }, */
338 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
339 MONO_MT_UINT32
, /* "Flags" }, */
340 MONO_MT_STRING_IDX
, /* "Name" }, */
341 MONO_MT_STRING_IDX
, /* "Namespace" }, */
342 MONO_MT_TDOR_IDX
, /* "Extends" }, */
343 MONO_MT_TABLE_IDX
, /* "FieldList:Field" }, */
344 MONO_MT_TABLE_IDX
, /* "MethodList:Method" }, */
347 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
348 MONO_MT_RS_IDX
, /* "ResolutionScope=ResolutionScope" }, */
349 MONO_MT_STRING_IDX
, /* "Name" }, */
350 MONO_MT_STRING_IDX
, /* "Namespace" }, */
353 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
354 MONO_MT_BLOB_IDX
, /* "Signature" }, */
357 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
358 MONO_MT_UINT16
, /* "Number" }, */
359 MONO_MT_UINT16
, /* "Flags" }, */
360 MONO_MT_TABLE_IDX
, /* "Owner" }, TypeDef or MethodDef */
361 MONO_MT_STRING_IDX
, /* "Name" }, */
364 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
365 MONO_MT_MDOR_IDX
, /* "Method" }, */
366 MONO_MT_BLOB_IDX
, /* "Signature" }, */
369 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
370 MONO_MT_TABLE_IDX
, /* "GenericParam" }, */
371 MONO_MT_TDOR_IDX
, /* "Constraint" }, */
374 #define NULL_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
378 /* Must be the same order as MONO_TABLE_* */
379 const static unsigned char
380 table_description
[] = {
381 MODULE_SCHEMA_OFFSET
,
382 TYPEREF_SCHEMA_OFFSET
,
383 TYPEDEF_SCHEMA_OFFSET
,
384 FIELD_POINTER_SCHEMA_OFFSET
,
386 METHOD_POINTER_SCHEMA_OFFSET
,
387 METHOD_SCHEMA_OFFSET
,
388 PARAM_POINTER_SCHEMA_OFFSET
,
390 IFACEMAP_SCHEMA_OFFSET
,
391 MEMBERREF_SCHEMA_OFFSET
, /* 0xa */
392 CONSTANT_SCHEMA_OFFSET
,
393 CUSTOM_ATTR_SCHEMA_OFFSET
,
394 FIELD_MARSHAL_SCHEMA_OFFSET
,
395 DECL_SEC_SCHEMA_OFFSET
,
396 CLASS_LAYOUT_SCHEMA_OFFSET
,
397 FIELD_LAYOUT_SCHEMA_OFFSET
, /* 0x10 */
398 STDALON_SIG_SCHEMA_OFFSET
,
399 EVENTMAP_SCHEMA_OFFSET
,
400 EVENT_POINTER_SCHEMA_OFFSET
,
402 PROPERTY_MAP_SCHEMA_OFFSET
,
403 PROPERTY_POINTER_SCHEMA_OFFSET
,
404 PROPERTY_SCHEMA_OFFSET
,
405 METHOD_SEMA_SCHEMA_OFFSET
,
406 METHOD_IMPL_SCHEMA_OFFSET
,
407 MODULEREF_SCHEMA_OFFSET
, /* 0x1a */
408 TYPESPEC_SCHEMA_OFFSET
,
409 IMPLMAP_SCHEMA_OFFSET
,
410 FIELD_RVA_SCHEMA_OFFSET
,
413 ASSEMBLY_SCHEMA_OFFSET
, /* 0x20 */
414 ASSEMBLYPROC_SCHEMA_OFFSET
,
415 ASSEMBLYOS_SCHEMA_OFFSET
,
416 ASSEMBLYREF_SCHEMA_OFFSET
,
417 ASSEMBLYREFPROC_SCHEMA_OFFSET
,
418 ASSEMBLYREFOS_SCHEMA_OFFSET
,
420 EXPORTED_TYPE_SCHEMA_OFFSET
,
421 MANIFEST_SCHEMA_OFFSET
,
422 NESTED_CLASS_SCHEMA_OFFSET
,
423 GENPARAM_SCHEMA_OFFSET
, /* 0x2a */
424 METHOD_SPEC_SCHEMA_OFFSET
,
425 GEN_CONSTRAINT_SCHEMA_OFFSET
428 #ifdef HAVE_ARRAY_ELEM_INIT
429 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
430 #define MSGSTRFIELD1(line) str##line
431 static const struct msgstr_t
{
432 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
433 #include "mono/cil/tables.def"
436 #define TABLEDEF(a,b) b,
437 #include "mono/cil/tables.def"
440 static const gint16 tableidx
[] = {
441 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
442 #include "mono/cil/tables.def"
447 #define TABLEDEF(a,b) b,
448 static const char* const
449 mono_tables_names
[] = {
450 #include "mono/cil/tables.def"
457 * mono_meta_table_name:
458 * @table: table index
460 * Returns the name of the given ECMA metadata logical format table
461 * as described in ECMA 335, Partition II, Section 22.
463 * Returns: the name for the @table index
466 mono_meta_table_name (int table
)
468 if ((table
< 0) || (table
> MONO_TABLE_LAST
))
471 #ifdef HAVE_ARRAY_ELEM_INIT
472 return (const char*)&tablestr
+ tableidx
[table
];
474 return mono_tables_names
[table
];
478 /* The guy who wrote the spec for this should not be allowed near a
481 If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
482 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
483 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
484 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
485 inverse of this mapping.
488 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
489 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
491 /* Reference: Partition II - 23.2.6 */
493 * mono_metadata_compute_size:
494 * @meta: metadata context
495 * @tableindex: metadata table number
496 * @result_bitfield: pointer to guint32 where to store additional info
498 * mono_metadata_compute_size() computes the lenght in bytes of a single
499 * row in a metadata table. The size of each column is encoded in the
500 * @result_bitfield return value along with the number of columns in the table.
501 * the resulting bitfield should be handed to the mono_metadata_table_size()
502 * and mono_metadata_table_count() macros.
503 * This is a Mono runtime internal only function.
506 mono_metadata_compute_size (MonoImage
*meta
, int tableindex
, guint32
*result_bitfield
)
508 guint32 bitfield
= 0;
509 int size
= 0, field_size
= 0;
512 const unsigned char *description
= TableSchemas
+ table_description
[tableindex
];
514 for (i
= 0; (code
= description
[i
]) != MONO_MT_END
; i
++){
517 field_size
= 4; break;
520 field_size
= 2; break;
523 field_size
= 1; break;
525 case MONO_MT_BLOB_IDX
:
526 field_size
= meta
->idx_blob_wide
? 4 : 2; break;
528 case MONO_MT_STRING_IDX
:
529 field_size
= meta
->idx_string_wide
? 4 : 2; break;
531 case MONO_MT_GUID_IDX
:
532 field_size
= meta
->idx_guid_wide
? 4 : 2; break;
534 case MONO_MT_TABLE_IDX
:
535 /* Uhm, a table index can point to other tables besides the current one
536 * so, it's not correct to use the rowcount of the current table to
537 * get the size for this column - lupus
539 switch (tableindex
) {
540 case MONO_TABLE_ASSEMBLYREFOS
:
542 field_size
= idx_size (MONO_TABLE_ASSEMBLYREF
); break;
543 case MONO_TABLE_ASSEMBLYREFPROCESSOR
:
545 field_size
= idx_size (MONO_TABLE_ASSEMBLYREF
); break;
546 case MONO_TABLE_CLASSLAYOUT
:
548 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
549 case MONO_TABLE_EVENTMAP
:
550 g_assert (i
== 0 || i
== 1);
551 field_size
= i
? idx_size (MONO_TABLE_EVENT
):
552 idx_size(MONO_TABLE_TYPEDEF
);
554 case MONO_TABLE_EVENT_POINTER
:
556 field_size
= idx_size (MONO_TABLE_EVENT
); break;
557 case MONO_TABLE_EXPORTEDTYPE
:
559 /* the index is in another metadata file, so it must be 4 */
560 field_size
= 4; break;
561 case MONO_TABLE_FIELDLAYOUT
:
563 field_size
= idx_size (MONO_TABLE_FIELD
); break;
564 case MONO_TABLE_FIELDRVA
:
566 field_size
= idx_size (MONO_TABLE_FIELD
); break;
567 case MONO_TABLE_FIELD_POINTER
:
569 field_size
= idx_size (MONO_TABLE_FIELD
); break;
570 case MONO_TABLE_IMPLMAP
:
572 field_size
= idx_size (MONO_TABLE_MODULEREF
); break;
573 case MONO_TABLE_INTERFACEIMPL
:
575 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
576 case MONO_TABLE_METHOD
:
578 field_size
= idx_size (MONO_TABLE_PARAM
); break;
579 case MONO_TABLE_METHODIMPL
:
581 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
582 case MONO_TABLE_METHODSEMANTICS
:
584 field_size
= idx_size (MONO_TABLE_METHOD
); break;
585 case MONO_TABLE_METHOD_POINTER
:
587 field_size
= idx_size (MONO_TABLE_METHOD
); break;
588 case MONO_TABLE_NESTEDCLASS
:
589 g_assert (i
== 0 || i
== 1);
590 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
591 case MONO_TABLE_PARAM_POINTER
:
593 field_size
= idx_size (MONO_TABLE_PARAM
); break;
594 case MONO_TABLE_PROPERTYMAP
:
595 g_assert (i
== 0 || i
== 1);
596 field_size
= i
? idx_size (MONO_TABLE_PROPERTY
):
597 idx_size(MONO_TABLE_TYPEDEF
);
599 case MONO_TABLE_PROPERTY_POINTER
:
601 field_size
= idx_size (MONO_TABLE_PROPERTY
); break;
602 case MONO_TABLE_TYPEDEF
:
603 g_assert (i
== 4 || i
== 5);
604 field_size
= i
== 4 ? idx_size (MONO_TABLE_FIELD
):
605 idx_size(MONO_TABLE_METHOD
);
607 case MONO_TABLE_GENERICPARAM
:
609 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
, meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
610 /*This is a coded token for 2 tables, so takes 1 bit */
611 field_size
= rtsize (n
, 16 - MONO_TYPEORMETHOD_BITS
);
613 case MONO_TABLE_GENERICPARAMCONSTRAINT
:
615 field_size
= idx_size (MONO_TABLE_GENERICPARAM
);
619 g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex
, i
);
624 * HasConstant: ParamDef, FieldDef, Property
626 case MONO_MT_CONST_IDX
:
627 n
= MAX (meta
->tables
[MONO_TABLE_PARAM
].rows
,
628 meta
->tables
[MONO_TABLE_FIELD
].rows
);
629 n
= MAX (n
, meta
->tables
[MONO_TABLE_PROPERTY
].rows
);
631 /* 2 bits to encode tag */
632 field_size
= rtsize (n
, 16-2);
636 * HasCustomAttribute: points to any table but
639 case MONO_MT_HASCAT_IDX
:
641 * We believe that since the signature and
642 * permission are indexing the Blob heap,
643 * we should consider the blob size first
645 /* I'm not a believer - lupus
646 if (meta->idx_blob_wide){
651 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
,
652 meta
->tables
[MONO_TABLE_FIELD
].rows
);
653 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
654 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
655 n
= MAX (n
, meta
->tables
[MONO_TABLE_PARAM
].rows
);
656 n
= MAX (n
, meta
->tables
[MONO_TABLE_INTERFACEIMPL
].rows
);
657 n
= MAX (n
, meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
658 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULE
].rows
);
659 n
= MAX (n
, meta
->tables
[MONO_TABLE_DECLSECURITY
].rows
);
660 n
= MAX (n
, meta
->tables
[MONO_TABLE_PROPERTY
].rows
);
661 n
= MAX (n
, meta
->tables
[MONO_TABLE_EVENT
].rows
);
662 n
= MAX (n
, meta
->tables
[MONO_TABLE_STANDALONESIG
].rows
);
663 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
664 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
665 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLY
].rows
);
666 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
667 n
= MAX (n
, meta
->tables
[MONO_TABLE_FILE
].rows
);
668 n
= MAX (n
, meta
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
);
669 n
= MAX (n
, meta
->tables
[MONO_TABLE_MANIFESTRESOURCE
].rows
);
671 /* 5 bits to encode */
672 field_size
= rtsize (n
, 16-5);
676 * CustomAttributeType: TypeDef, TypeRef, MethodDef,
677 * MemberRef and String.
679 case MONO_MT_CAT_IDX
:
680 /* String is a heap, if it is wide, we know the size */
682 if (meta->idx_string_wide){
687 n
= MAX (meta
->tables
[MONO_TABLE_TYPEREF
].rows
,
688 meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
689 n
= MAX (n
, meta
->tables
[MONO_TABLE_METHOD
].rows
);
690 n
= MAX (n
, meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
692 /* 3 bits to encode */
693 field_size
= rtsize (n
, 16-3);
697 * HasDeclSecurity: Typedef, MethodDef, Assembly
699 case MONO_MT_HASDEC_IDX
:
700 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
701 meta
->tables
[MONO_TABLE_METHOD
].rows
);
702 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLY
].rows
);
704 /* 2 bits to encode */
705 field_size
= rtsize (n
, 16-2);
709 * Implementation: File, AssemblyRef, ExportedType
711 case MONO_MT_IMPL_IDX
:
712 n
= MAX (meta
->tables
[MONO_TABLE_FILE
].rows
,
713 meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
714 n
= MAX (n
, meta
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
);
716 /* 2 bits to encode tag */
717 field_size
= rtsize (n
, 16-2);
721 * HasFieldMarshall: FieldDef, ParamDef
723 case MONO_MT_HFM_IDX
:
724 n
= MAX (meta
->tables
[MONO_TABLE_FIELD
].rows
,
725 meta
->tables
[MONO_TABLE_PARAM
].rows
);
727 /* 1 bit used to encode tag */
728 field_size
= rtsize (n
, 16-1);
732 * MemberForwarded: FieldDef, MethodDef
735 n
= MAX (meta
->tables
[MONO_TABLE_FIELD
].rows
,
736 meta
->tables
[MONO_TABLE_METHOD
].rows
);
738 /* 1 bit used to encode tag */
739 field_size
= rtsize (n
, 16-1);
743 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
745 * It is TypeDef, _TypeRef_, TypeSpec, instead.
747 case MONO_MT_TDOR_IDX
:
748 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
749 meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
750 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
752 /* 2 bits to encode */
753 field_size
= rtsize (n
, 16-2);
757 * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
759 case MONO_MT_MRP_IDX
:
760 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
761 meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
762 n
= MAX (n
, meta
->tables
[MONO_TABLE_METHOD
].rows
);
763 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
764 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
765 n
= MAX (n
, meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
767 /* 3 bits to encode */
768 field_size
= rtsize (n
, 16 - 3);
772 * MethodDefOrRef: MethodDef, MemberRef
774 case MONO_MT_MDOR_IDX
:
775 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
,
776 meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
778 /* 1 bit used to encode tag */
779 field_size
= rtsize (n
, 16-1);
783 * HasSemantics: Property, Event
786 n
= MAX (meta
->tables
[MONO_TABLE_PROPERTY
].rows
,
787 meta
->tables
[MONO_TABLE_EVENT
].rows
);
789 /* 1 bit used to encode tag */
790 field_size
= rtsize (n
, 16-1);
794 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
797 n
= MAX (meta
->tables
[MONO_TABLE_MODULE
].rows
,
798 meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
799 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
800 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
802 /* 2 bits used to encode tag (ECMA spec claims 3) */
803 field_size
= rtsize (n
, 16 - 2);
808 * encode field size as follows (we just need to
815 bitfield
|= (field_size
-1) << shift
;
818 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
821 *result_bitfield
= (i
<< 24) | bitfield
;
826 * mono_metadata_compute_table_bases:
827 * @meta: metadata context to compute table values
829 * Computes the table bases for the metadata structure.
830 * This is an internal function used by the image loader code.
833 mono_metadata_compute_table_bases (MonoImage
*meta
)
836 const char *base
= meta
->tables_base
;
838 for (i
= 0; i
< MONO_TABLE_NUM
; i
++) {
839 MonoTableInfo
*table
= &meta
->tables
[i
];
840 if (table
->rows
== 0)
843 table
->row_size
= mono_metadata_compute_size (meta
, i
, &table
->size_bitfield
);
845 base
+= table
->rows
* table
->row_size
;
850 * mono_metadata_locate:
851 * @meta: metadata context
852 * @table: table code.
853 * @idx: index of element to retrieve from @table.
855 * Returns: a pointer to the @idx element in the metadata table
856 * whose code is @table.
859 mono_metadata_locate (MonoImage
*meta
, int table
, int idx
)
861 /* idx == 0 refers always to NULL */
862 g_return_val_if_fail (idx
> 0 && idx
<= meta
->tables
[table
].rows
, ""); /*FIXME shouldn't we return NULL here?*/
864 return meta
->tables
[table
].base
+ (meta
->tables
[table
].row_size
* (idx
- 1));
868 * mono_metadata_locate_token:
869 * @meta: metadata context
870 * @token: metadata token
872 * Returns: a pointer to the data in the metadata represented by the
876 mono_metadata_locate_token (MonoImage
*meta
, guint32 token
)
878 return mono_metadata_locate (meta
, token
>> 24, token
& 0xffffff);
882 * mono_metadata_string_heap:
883 * @meta: metadata context
884 * @index: index into the string heap.
886 * Returns: an in-memory pointer to the @index in the string heap.
889 mono_metadata_string_heap (MonoImage
*meta
, guint32 index
)
891 g_return_val_if_fail (index
< meta
->heap_strings
.size
, "");
892 return meta
->heap_strings
.data
+ index
;
896 * mono_metadata_user_string:
897 * @meta: metadata context
898 * @index: index into the user string heap.
900 * Returns: an in-memory pointer to the @index in the user string heap ("#US").
903 mono_metadata_user_string (MonoImage
*meta
, guint32 index
)
905 g_return_val_if_fail (index
< meta
->heap_us
.size
, "");
906 return meta
->heap_us
.data
+ index
;
910 * mono_metadata_blob_heap:
911 * @meta: metadata context
912 * @index: index into the blob.
914 * Returns: an in-memory pointer to the @index in the Blob heap.
917 mono_metadata_blob_heap (MonoImage
*meta
, guint32 index
)
919 g_return_val_if_fail (index
< meta
->heap_blob
.size
, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
920 return meta
->heap_blob
.data
+ index
;
924 * mono_metadata_guid_heap:
925 * @meta: metadata context
926 * @index: index into the guid heap.
928 * Returns: an in-memory pointer to the @index in the guid heap.
931 mono_metadata_guid_heap (MonoImage
*meta
, guint32 index
)
934 index
*= 16; /* adjust for guid size and 1-based index */
935 g_return_val_if_fail (index
< meta
->heap_guid
.size
, "");
936 return meta
->heap_guid
.data
+ index
;
939 static const unsigned char *
940 dword_align (const unsigned char *ptr
)
942 #if SIZEOF_VOID_P == 8
943 return (const unsigned char *) (((guint64
) (ptr
+ 3)) & ~3);
945 return (const unsigned char *) (((guint32
) (ptr
+ 3)) & ~3);
950 * mono_metadata_decode_row:
951 * @t: table to extract information from.
952 * @idx: index in table.
953 * @res: array of @res_size cols to store the results in
955 * This decompresses the metadata element @idx in table @t
956 * into the guint32 @res array that has res_size elements
959 mono_metadata_decode_row (const MonoTableInfo
*t
, int idx
, guint32
*res
, int res_size
)
961 guint32 bitfield
= t
->size_bitfield
;
962 int i
, count
= mono_metadata_table_count (bitfield
);
965 g_assert (idx
< t
->rows
);
966 data
= t
->base
+ idx
* t
->row_size
;
968 g_assert (res_size
== count
);
970 for (i
= 0; i
< count
; i
++) {
971 int n
= mono_metadata_table_size (bitfield
, i
);
975 res
[i
] = *data
; break;
977 res
[i
] = read16 (data
); break;
979 res
[i
] = read32 (data
); break;
981 g_assert_not_reached ();
988 * mono_metadata_decode_row_col:
989 * @t: table to extract information from.
990 * @idx: index for row in table.
991 * @col: column in the row.
993 * This function returns the value of column @col from the @idx
994 * row in the table @t.
997 mono_metadata_decode_row_col (const MonoTableInfo
*t
, int idx
, guint col
)
999 guint32 bitfield
= t
->size_bitfield
;
1001 register const char *data
;
1004 g_assert (idx
< t
->rows
);
1005 g_assert (col
< mono_metadata_table_count (bitfield
));
1006 data
= t
->base
+ idx
* t
->row_size
;
1008 n
= mono_metadata_table_size (bitfield
, 0);
1009 for (i
= 0; i
< col
; ++i
) {
1011 n
= mono_metadata_table_size (bitfield
, i
+ 1);
1017 return read16 (data
);
1019 return read32 (data
);
1021 g_assert_not_reached ();
1027 * mono_metadata_decode_blob_size:
1028 * @ptr: pointer to a blob object
1029 * @rptr: the new position of the pointer
1031 * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
1033 * Returns: the size of the blob object
1036 mono_metadata_decode_blob_size (const char *xptr
, const char **rptr
)
1038 const unsigned char *ptr
= (const unsigned char *)xptr
;
1041 if ((*ptr
& 0x80) == 0){
1042 size
= ptr
[0] & 0x7f;
1044 } else if ((*ptr
& 0x40) == 0){
1045 size
= ((ptr
[0] & 0x3f) << 8) + ptr
[1];
1048 size
= ((ptr
[0] & 0x1f) << 24) +
1060 * mono_metadata_decode_value:
1061 * @ptr: pointer to decode from
1062 * @rptr: the new position of the pointer
1064 * This routine decompresses 32-bit values as specified in the "Blob and
1065 * Signature" section (22.2)
1067 * Returns: the decoded value
1070 mono_metadata_decode_value (const char *_ptr
, const char **rptr
)
1072 const unsigned char *ptr
= (const unsigned char *) _ptr
;
1073 unsigned char b
= *ptr
;
1076 if ((b
& 0x80) == 0){
1079 } else if ((b
& 0x40) == 0){
1080 len
= ((b
& 0x3f) << 8 | ptr
[1]);
1083 len
= ((b
& 0x1f) << 24) |
1096 * mono_metadata_decode_signed_value:
1097 * @ptr: pointer to decode from
1098 * @rptr: the new position of the pointer
1100 * This routine decompresses 32-bit signed values
1101 * (not specified in the spec)
1103 * Returns: the decoded value
1106 mono_metadata_decode_signed_value (const char *ptr
, const char **rptr
)
1108 guint32 uval
= mono_metadata_decode_value (ptr
, rptr
);
1109 gint32 ival
= uval
>> 1;
1112 /* ival is a truncated 2's complement negative number. */
1114 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1117 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1118 return ival
- 0x2000;
1119 if (ival
< 0x10000000)
1120 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1121 return ival
- 0x10000000;
1122 g_assert (ival
< 0x20000000);
1123 g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival
, uval
);
1124 return ival
- 0x20000000;
1128 * Translates the given 1-based index into the Method, Field, Event, or Param tables
1129 * using the *Ptr tables in uncompressed metadata, if they are available.
1131 * FIXME: The caller is not forced to call this function, which is error-prone, since
1132 * forgetting to call it would only show up as a bug on uncompressed metadata.
1135 mono_metadata_translate_token_index (MonoImage
*image
, int table
, guint32 idx
)
1137 if (!image
->uncompressed_metadata
)
1141 case MONO_TABLE_METHOD
:
1142 if (image
->tables
[MONO_TABLE_METHOD_POINTER
].rows
)
1143 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_METHOD_POINTER
], idx
- 1, MONO_METHOD_POINTER_METHOD
);
1146 case MONO_TABLE_FIELD
:
1147 if (image
->tables
[MONO_TABLE_FIELD_POINTER
].rows
)
1148 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_FIELD_POINTER
], idx
- 1, MONO_FIELD_POINTER_FIELD
);
1151 case MONO_TABLE_EVENT
:
1152 if (image
->tables
[MONO_TABLE_EVENT_POINTER
].rows
)
1153 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_EVENT_POINTER
], idx
- 1, MONO_EVENT_POINTER_EVENT
);
1156 case MONO_TABLE_PROPERTY
:
1157 if (image
->tables
[MONO_TABLE_PROPERTY_POINTER
].rows
)
1158 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PROPERTY_POINTER
], idx
- 1, MONO_PROPERTY_POINTER_PROPERTY
);
1161 case MONO_TABLE_PARAM
:
1162 if (image
->tables
[MONO_TABLE_PARAM_POINTER
].rows
)
1163 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PARAM_POINTER
], idx
- 1, MONO_PARAM_POINTER_PARAM
);
1172 * mono_metadata_decode_table_row:
1174 * Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
1175 * uncompressed metadata into account, so it should be used to access the
1176 * Method, Field, Param and Event tables when the access is made from metadata, i.e.
1177 * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
1180 mono_metadata_decode_table_row (MonoImage
*image
, int table
, int idx
, guint32
*res
, int res_size
)
1182 if (image
->uncompressed_metadata
)
1183 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1185 mono_metadata_decode_row (&image
->tables
[table
], idx
, res
, res_size
);
1189 * mono_metadata_decode_table_row_col:
1191 * Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
1192 * uncompressed metadata into account, so it should be used to access the
1193 * Method, Field, Param and Event tables.
1195 guint32
mono_metadata_decode_table_row_col (MonoImage
*image
, int table
, int idx
, guint col
)
1197 if (image
->uncompressed_metadata
)
1198 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1200 return mono_metadata_decode_row_col (&image
->tables
[table
], idx
, col
);
1204 * mono_metadata_parse_typedef_or_ref:
1205 * @m: a metadata context.
1206 * @ptr: a pointer to an encoded TypedefOrRef in @m
1207 * @rptr: pointer updated to match the end of the decoded stream
1209 * Returns: a token valid in the @m metadata decoded from
1210 * the compressed representation.
1213 mono_metadata_parse_typedef_or_ref (MonoImage
*m
, const char *ptr
, const char **rptr
)
1216 token
= mono_metadata_decode_value (ptr
, &ptr
);
1219 return mono_metadata_token_from_dor (token
);
1223 * mono_metadata_parse_custom_mod:
1224 * @m: a metadata context.
1225 * @dest: storage where the info about the custom modifier is stored (may be NULL)
1226 * @ptr: a pointer to (possibly) the start of a custom modifier list
1227 * @rptr: pointer updated to match the end of the decoded stream
1229 * Checks if @ptr points to a type custom modifier compressed representation.
1231 * Returns: #TRUE if a custom modifier was found, #FALSE if not.
1234 mono_metadata_parse_custom_mod (MonoImage
*m
, MonoCustomMod
*dest
, const char *ptr
, const char **rptr
)
1236 MonoCustomMod local
;
1237 if ((*ptr
== MONO_TYPE_CMOD_OPT
) || (*ptr
== MONO_TYPE_CMOD_REQD
)) {
1240 dest
->required
= *ptr
== MONO_TYPE_CMOD_REQD
? 1 : 0;
1241 dest
->token
= mono_metadata_parse_typedef_or_ref (m
, ptr
+ 1, rptr
);
1248 * mono_metadata_parse_array_full:
1249 * @m: a metadata context.
1250 * @ptr: a pointer to an encoded array description.
1251 * @rptr: pointer updated to match the end of the decoded stream
1253 * Decodes the compressed array description found in the metadata @m at @ptr.
1255 * Returns: a #MonoArrayType structure describing the array type
1256 * and dimensions. Memory is allocated from the image mempool.
1258 * LOCKING: Acquires the loader lock
1261 mono_metadata_parse_array_full (MonoImage
*m
, MonoGenericContainer
*container
,
1262 const char *ptr
, const char **rptr
)
1265 MonoArrayType
*array
;
1268 array
= mono_image_alloc0 (m
, sizeof (MonoArrayType
));
1269 etype
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
1272 array
->eklass
= mono_class_from_mono_type (etype
);
1273 array
->rank
= mono_metadata_decode_value (ptr
, &ptr
);
1275 array
->numsizes
= mono_metadata_decode_value (ptr
, &ptr
);
1276 if (array
->numsizes
)
1277 array
->sizes
= mono_image_alloc0 (m
, sizeof (int) * array
->numsizes
);
1278 for (i
= 0; i
< array
->numsizes
; ++i
)
1279 array
->sizes
[i
] = mono_metadata_decode_value (ptr
, &ptr
);
1281 array
->numlobounds
= mono_metadata_decode_value (ptr
, &ptr
);
1282 if (array
->numlobounds
)
1283 array
->lobounds
= mono_image_alloc0 (m
, sizeof (int) * array
->numlobounds
);
1284 for (i
= 0; i
< array
->numlobounds
; ++i
)
1285 array
->lobounds
[i
] = mono_metadata_decode_signed_value (ptr
, &ptr
);
1293 mono_metadata_parse_array (MonoImage
*m
, const char *ptr
, const char **rptr
)
1295 return mono_metadata_parse_array_full (m
, NULL
, ptr
, rptr
);
1299 * mono_metadata_free_array:
1300 * @array: array description
1302 * Frees the array description returned from mono_metadata_parse_array().
1305 mono_metadata_free_array (MonoArrayType
*array
)
1307 g_free (array
->sizes
);
1308 g_free (array
->lobounds
);
1313 * need to add common field and param attributes combinations:
1316 * public static literal
1319 * private static literal
1321 static const MonoType
1323 /* data, attrs, type, nmods, byref, pinned */
1324 {{NULL
}, 0, MONO_TYPE_VOID
, 0, 0, 0},
1325 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 0, 0},
1326 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 1, 0},
1327 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 0, 0},
1328 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 1, 0},
1329 {{NULL
}, 0, MONO_TYPE_I1
, 0, 0, 0},
1330 {{NULL
}, 0, MONO_TYPE_I1
, 0, 1, 0},
1331 {{NULL
}, 0, MONO_TYPE_U1
, 0, 0, 0},
1332 {{NULL
}, 0, MONO_TYPE_U1
, 0, 1, 0},
1333 {{NULL
}, 0, MONO_TYPE_I2
, 0, 0, 0},
1334 {{NULL
}, 0, MONO_TYPE_I2
, 0, 1, 0},
1335 {{NULL
}, 0, MONO_TYPE_U2
, 0, 0, 0},
1336 {{NULL
}, 0, MONO_TYPE_U2
, 0, 1, 0},
1337 {{NULL
}, 0, MONO_TYPE_I4
, 0, 0, 0},
1338 {{NULL
}, 0, MONO_TYPE_I4
, 0, 1, 0},
1339 {{NULL
}, 0, MONO_TYPE_U4
, 0, 0, 0},
1340 {{NULL
}, 0, MONO_TYPE_U4
, 0, 1, 0},
1341 {{NULL
}, 0, MONO_TYPE_I8
, 0, 0, 0},
1342 {{NULL
}, 0, MONO_TYPE_I8
, 0, 1, 0},
1343 {{NULL
}, 0, MONO_TYPE_U8
, 0, 0, 0},
1344 {{NULL
}, 0, MONO_TYPE_U8
, 0, 1, 0},
1345 {{NULL
}, 0, MONO_TYPE_R4
, 0, 0, 0},
1346 {{NULL
}, 0, MONO_TYPE_R4
, 0, 1, 0},
1347 {{NULL
}, 0, MONO_TYPE_R8
, 0, 0, 0},
1348 {{NULL
}, 0, MONO_TYPE_R8
, 0, 1, 0},
1349 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 0, 0},
1350 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 1, 0},
1351 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 0, 0},
1352 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 1, 0},
1353 {{NULL
}, 0, MONO_TYPE_TYPEDBYREF
, 0, 0, 0},
1354 {{NULL
}, 0, MONO_TYPE_I
, 0, 0, 0},
1355 {{NULL
}, 0, MONO_TYPE_I
, 0, 1, 0},
1356 {{NULL
}, 0, MONO_TYPE_U
, 0, 0, 0},
1357 {{NULL
}, 0, MONO_TYPE_U
, 0, 1, 0},
1360 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1362 static GHashTable
*type_cache
= NULL
;
1363 static int next_generic_inst_id
= 0;
1365 static guint
mono_generic_class_hash (gconstpointer data
);
1368 * MonoTypes with modifies are never cached, so we never check or use that field.
1371 mono_type_hash (gconstpointer data
)
1373 const MonoType
*type
= (const MonoType
*) data
;
1374 if (type
->type
== MONO_TYPE_GENERICINST
)
1375 return mono_generic_class_hash (type
->data
.generic_class
);
1377 return type
->type
| (type
->byref
<< 8) | (type
->attrs
<< 9);
1381 mono_type_equal (gconstpointer ka
, gconstpointer kb
)
1383 const MonoType
*a
= (const MonoType
*) ka
;
1384 const MonoType
*b
= (const MonoType
*) kb
;
1386 if (a
->type
!= b
->type
|| a
->byref
!= b
->byref
|| a
->attrs
!= b
->attrs
|| a
->pinned
!= b
->pinned
)
1388 /* need other checks */
1393 mono_metadata_generic_inst_hash (gconstpointer data
)
1395 const MonoGenericInst
*ginst
= (const MonoGenericInst
*) data
;
1399 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
1401 hash
+= mono_metadata_type_hash (ginst
->type_argv
[i
]);
1404 return hash
^ (ginst
->is_open
<< 8);
1408 mono_generic_inst_equal_full (const MonoGenericInst
*a
, const MonoGenericInst
*b
, gboolean signature_only
)
1412 #ifndef MONO_SMALL_CONFIG
1413 if (a
->id
&& b
->id
) {
1416 if (!signature_only
)
1421 if (a
->is_open
!= b
->is_open
|| a
->type_argc
!= b
->type_argc
)
1423 for (i
= 0; i
< a
->type_argc
; ++i
) {
1424 if (!do_mono_metadata_type_equal (a
->type_argv
[i
], b
->type_argv
[i
], signature_only
))
1431 mono_metadata_generic_inst_equal (gconstpointer ka
, gconstpointer kb
)
1433 const MonoGenericInst
*a
= (const MonoGenericInst
*) ka
;
1434 const MonoGenericInst
*b
= (const MonoGenericInst
*) kb
;
1436 return mono_generic_inst_equal_full (a
, b
, FALSE
);
1440 mono_generic_class_hash (gconstpointer data
)
1442 const MonoGenericClass
*gclass
= (const MonoGenericClass
*) data
;
1443 guint hash
= mono_metadata_type_hash (&gclass
->container_class
->byval_arg
);
1446 hash
+= gclass
->is_tb_open
;
1447 hash
+= mono_metadata_generic_context_hash (&gclass
->context
);
1453 mono_generic_class_equal (gconstpointer ka
, gconstpointer kb
)
1455 const MonoGenericClass
*a
= (const MonoGenericClass
*) ka
;
1456 const MonoGenericClass
*b
= (const MonoGenericClass
*) kb
;
1458 return _mono_metadata_generic_class_equal (a
, b
, FALSE
);
1462 * mono_metadata_init:
1464 * Initialize the global variables of this module.
1465 * This is a Mono runtime internal function.
1468 mono_metadata_init (void)
1472 type_cache
= g_hash_table_new (mono_type_hash
, mono_type_equal
);
1474 for (i
= 0; i
< NBUILTIN_TYPES (); ++i
)
1475 g_hash_table_insert (type_cache
, (gpointer
) &builtin_types
[i
], (gpointer
) &builtin_types
[i
]);
1479 * mono_metadata_cleanup:
1481 * Free all resources used by this module.
1482 * This is a Mono runtime internal function.
1485 mono_metadata_cleanup (void)
1487 g_hash_table_destroy (type_cache
);
1492 * mono_metadata_parse_type:
1493 * @m: metadata context
1494 * @mode: king of type that may be found at @ptr
1495 * @opt_attrs: optional attributes to store in the returned type
1496 * @ptr: pointer to the type representation
1497 * @rptr: pointer updated to match the end of the decoded stream
1499 * Decode a compressed type description found at @ptr in @m.
1500 * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
1501 * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
1502 * This function can be used to decode type descriptions in method signatures,
1503 * field signatures, locals signatures etc.
1505 * To parse a generic type, `generic_container' points to the current class'es
1506 * (the `generic_container' field in the MonoClass) or the current generic method's
1507 * (stored in image->property_hash) generic container.
1508 * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
1509 * this MonoGenericContainer.
1510 * This is a Mono runtime internal function.
1512 * LOCKING: Acquires the loader lock.
1514 * Returns: a #MonoType structure representing the decoded type.
1517 mono_metadata_parse_type_full (MonoImage
*m
, MonoGenericContainer
*container
, MonoParseTypeMode mode
,
1518 short opt_attrs
, const char *ptr
, const char **rptr
)
1520 MonoType
*type
, *cached
;
1522 gboolean byref
= FALSE
;
1523 gboolean pinned
= FALSE
;
1524 const char *tmp_ptr
;
1529 * According to the spec, custom modifiers should come before the byref
1530 * flag, but the IL produced by ilasm from the following signature:
1531 * object modopt(...) &
1532 * starts with a byref flag, followed by the modifiers. (bug #49802)
1533 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1534 * it would be better to treat byref as real type constructor instead of
1536 * Also, pinned should come before anything else, but some MSV++ produced
1537 * assemblies violate this (#bug 61990).
1540 /* Count the modifiers first */
1545 case MONO_TYPE_PINNED
:
1546 case MONO_TYPE_BYREF
:
1549 case MONO_TYPE_CMOD_REQD
:
1550 case MONO_TYPE_CMOD_OPT
:
1552 mono_metadata_parse_custom_mod (m
, NULL
, tmp_ptr
, &tmp_ptr
);
1560 type
= mono_image_alloc0 (m
, MONO_SIZEOF_TYPE
+ ((gint32
)count
) * sizeof (MonoCustomMod
));
1561 type
->num_mods
= count
;
1563 g_warning ("got more than 64 modifiers in type");
1566 memset (type
, 0, MONO_SIZEOF_TYPE
);
1569 /* Parse pinned, byref and custom modifiers */
1574 case MONO_TYPE_PINNED
:
1578 case MONO_TYPE_BYREF
:
1582 case MONO_TYPE_CMOD_REQD
:
1583 case MONO_TYPE_CMOD_OPT
:
1584 mono_metadata_parse_custom_mod (m
, &(type
->modifiers
[count
]), ptr
, &ptr
);
1592 type
->attrs
= opt_attrs
;
1593 type
->byref
= byref
;
1594 type
->pinned
= pinned
? 1 : 0;
1596 if (!do_mono_metadata_parse_type (type
, m
, container
, ptr
, &ptr
)) {
1603 if (!type
->num_mods
) {
1604 /* no need to free type here, because it is on the stack */
1605 if ((type
->type
== MONO_TYPE_CLASS
|| type
->type
== MONO_TYPE_VALUETYPE
) && !type
->pinned
&& !type
->attrs
) {
1606 MonoType
*ret
= type
->byref
? &type
->data
.klass
->this_arg
: &type
->data
.klass
->byval_arg
;
1608 /* Consider the case:
1610 class Foo<T> { class Bar {} }
1611 class Test : Foo<Test>.Bar {}
1613 When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
1614 a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1616 We ensure that the MonoClass is in a state that we can canonicalize to:
1618 klass->byval_arg.data.klass == klass
1619 klass->this_arg.data.klass == klass
1621 If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1623 LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1624 of a MonoClass which currently holds the loader lock. 'type' is local.
1626 if (ret
->data
.klass
== type
->data
.klass
) {
1630 /* No need to use locking since nobody is modifying the hash table */
1631 if ((cached
= g_hash_table_lookup (type_cache
, type
))) {
1636 /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1638 if (type
== &stype
) {
1639 type
= mono_image_alloc (m
, MONO_SIZEOF_TYPE
);
1640 memcpy (type
, &stype
, MONO_SIZEOF_TYPE
);
1646 * LOCKING: Acquires the loader lock.
1649 mono_metadata_parse_type (MonoImage
*m
, MonoParseTypeMode mode
, short opt_attrs
,
1650 const char *ptr
, const char **rptr
)
1652 return mono_metadata_parse_type_full (m
, NULL
, mode
, opt_attrs
, ptr
, rptr
);
1656 mono_metadata_method_has_param_attrs (MonoImage
*m
, int def
)
1658 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1659 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1660 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1662 if (def
< methodt
->rows
)
1663 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1665 lastp
= m
->tables
[MONO_TABLE_PARAM
].rows
+ 1;
1667 for (i
= param_index
; i
< lastp
; ++i
) {
1668 guint32 flags
= mono_metadata_decode_row_col (paramt
, i
- 1, MONO_PARAM_FLAGS
);
1677 * mono_metadata_get_param_attrs:
1679 * @m The image to loader parameter attributes from
1680 * @def method def token (one based)
1681 * @param_count number of params to decode including the return value
1683 * Return the parameter attributes for the method whose MethodDef index is DEF. The
1684 * returned memory needs to be freed by the caller. If all the param attributes are
1685 * 0, then NULL is returned.
1688 mono_metadata_get_param_attrs (MonoImage
*m
, int def
, int param_count
)
1690 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1691 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1692 guint32 cols
[MONO_PARAM_SIZE
];
1693 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1696 if (def
< methodt
->rows
)
1697 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1699 lastp
= paramt
->rows
+ 1;
1701 for (i
= param_index
; i
< lastp
; ++i
) {
1702 mono_metadata_decode_row (paramt
, i
- 1, cols
, MONO_PARAM_SIZE
);
1703 if (cols
[MONO_PARAM_FLAGS
]) {
1705 pattrs
= g_new0 (int, param_count
);
1706 /* at runtime we just ignore this kind of malformed file:
1707 * the verifier can signal the error to the user
1709 if (cols
[MONO_PARAM_SEQUENCE
] >= param_count
)
1711 pattrs
[cols
[MONO_PARAM_SEQUENCE
]] = cols
[MONO_PARAM_FLAGS
];
1719 * mono_metadata_parse_signature_full:
1720 * @image: metadata context
1721 * @generic_container: generic container
1722 * @toke: metadata token
1724 * Decode a method signature stored in the STANDALONESIG table
1726 * LOCKING: Assumes the loader lock is held.
1728 * Returns: a MonoMethodSignature describing the signature.
1730 MonoMethodSignature
*
1731 mono_metadata_parse_signature_full (MonoImage
*image
, MonoGenericContainer
*generic_container
, guint32 token
)
1733 MonoTableInfo
*tables
= image
->tables
;
1734 guint32 idx
= mono_metadata_token_index (token
);
1739 return mono_lookup_dynamic_token (image
, token
, NULL
);
1741 g_assert (mono_metadata_token_table(token
) == MONO_TABLE_STANDALONESIG
);
1743 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
1745 ptr
= mono_metadata_blob_heap (image
, sig
);
1746 mono_metadata_decode_blob_size (ptr
, &ptr
);
1748 return mono_metadata_parse_method_signature_full (image
, generic_container
, 0, ptr
, NULL
);
1752 * mono_metadata_parse_signature:
1753 * @image: metadata context
1754 * @toke: metadata token
1756 * Decode a method signature stored in the STANDALONESIG table
1758 * Returns: a MonoMethodSignature describing the signature.
1760 MonoMethodSignature
*
1761 mono_metadata_parse_signature (MonoImage
*image
, guint32 token
)
1763 return mono_metadata_parse_signature_full (image
, NULL
, token
);
1767 * mono_metadata_signature_alloc:
1768 * @image: metadata context
1769 * @nparmas: number of parameters in the signature
1771 * Allocate a MonoMethodSignature structure with the specified number of params.
1772 * The return type and the params types need to be filled later.
1773 * This is a Mono runtime internal function.
1775 * LOCKING: Assumes the loader lock is held.
1777 * Returns: the new MonoMethodSignature structure.
1779 MonoMethodSignature
*
1780 mono_metadata_signature_alloc (MonoImage
*m
, guint32 nparams
)
1782 MonoMethodSignature
*sig
;
1784 sig
= mono_image_alloc0 (m
, MONO_SIZEOF_METHOD_SIGNATURE
+ ((gint32
)nparams
) * sizeof (MonoType
*));
1785 sig
->param_count
= nparams
;
1786 sig
->sentinelpos
= -1;
1791 static MonoMethodSignature
*
1792 mono_metadata_signature_dup_internal (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1795 MonoMethodSignature
*ret
;
1796 sigsize
= MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*);
1799 ret
= mono_image_alloc (image
, sigsize
);
1801 ret
= mono_mempool_alloc (mp
, sigsize
);
1803 ret
= g_malloc (sigsize
);
1805 memcpy (ret
, sig
, sigsize
);
1809 MonoMethodSignature
*
1810 mono_metadata_signature_dup_full (MonoImage
*image
, MonoMethodSignature
*sig
)
1812 return mono_metadata_signature_dup_internal (image
, NULL
, sig
);
1815 /*The mempool is accessed without synchronization*/
1816 MonoMethodSignature
*
1817 mono_metadata_signature_dup_mempool (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1819 return mono_metadata_signature_dup_internal (NULL
, mp
, sig
);
1823 * mono_metadata_signature_dup:
1824 * @sig: method signature
1826 * Duplicate an existing MonoMethodSignature so it can be modified.
1827 * This is a Mono runtime internal function.
1829 * Returns: the new MonoMethodSignature structure.
1831 MonoMethodSignature
*
1832 mono_metadata_signature_dup (MonoMethodSignature
*sig
)
1834 return mono_metadata_signature_dup_full (NULL
, sig
);
1838 * mono_metadata_signature_size:
1840 * Return the amount of memory allocated to SIG.
1843 mono_metadata_signature_size (MonoMethodSignature
*sig
)
1845 return MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*);
1849 * mono_metadata_parse_method_signature:
1850 * @m: metadata context
1851 * @generic_container: generics container
1852 * @def: the MethodDef index or 0 for Ref signatures.
1853 * @ptr: pointer to the signature metadata representation
1854 * @rptr: pointer updated to match the end of the decoded stream
1856 * Decode a method signature stored at @ptr.
1857 * This is a Mono runtime internal function.
1859 * LOCKING: Assumes the loader lock is held.
1861 * Returns: a MonoMethodSignature describing the signature.
1863 MonoMethodSignature
*
1864 mono_metadata_parse_method_signature_full (MonoImage
*m
, MonoGenericContainer
*container
,
1865 int def
, const char *ptr
, const char **rptr
)
1867 MonoMethodSignature
*method
;
1868 int i
, *pattrs
= NULL
;
1869 guint32 hasthis
= 0, explicit_this
= 0, call_convention
, param_count
;
1870 guint32 gen_param_count
= 0;
1871 gboolean is_open
= FALSE
;
1874 gen_param_count
= 1;
1879 call_convention
= *ptr
& 0x0F;
1881 if (gen_param_count
)
1882 gen_param_count
= mono_metadata_decode_value (ptr
, &ptr
);
1883 param_count
= mono_metadata_decode_value (ptr
, &ptr
);
1886 pattrs
= mono_metadata_get_param_attrs (m
, def
, param_count
+ 1); /*Must be + 1 since signature's param count doesn't account for the return value */
1888 method
= mono_metadata_signature_alloc (m
, param_count
);
1889 method
->hasthis
= hasthis
;
1890 method
->explicit_this
= explicit_this
;
1891 method
->call_convention
= call_convention
;
1892 method
->generic_param_count
= gen_param_count
;
1894 if (call_convention
!= 0xa) {
1895 method
->ret
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_RET
, pattrs
? pattrs
[0] : 0, ptr
, &ptr
);
1897 mono_metadata_free_method_signature (method
);
1901 is_open
= mono_class_is_open_constructed_type (method
->ret
);
1904 for (i
= 0; i
< method
->param_count
; ++i
) {
1905 if (*ptr
== MONO_TYPE_SENTINEL
) {
1906 if (method
->call_convention
!= MONO_CALL_VARARG
|| def
) {
1907 g_warning ("found sentinel for methoddef or no vararg method 0x%08x on image %s", def
, m
->name
);
1911 if (method
->sentinelpos
>= 0) {
1912 g_warning ("found sentinel twice in the same signature for method 0x%08x on image %s", def
, m
->name
);
1916 method
->sentinelpos
= i
;
1919 method
->params
[i
] = mono_metadata_parse_type_full (m
, container
, MONO_PARSE_PARAM
, pattrs
? pattrs
[i
+1] : 0, ptr
, &ptr
);
1920 if (!method
->params
[i
]) {
1921 mono_metadata_free_method_signature (method
);
1926 is_open
= mono_class_is_open_constructed_type (method
->params
[i
]);
1929 /* The sentinel could be missing if the caller does not pass any additional arguments */
1930 if (!def
&& method
->call_convention
== MONO_CALL_VARARG
&& method
->sentinelpos
< 0)
1931 method
->sentinelpos
= method
->param_count
;
1933 method
->has_type_parameters
= is_open
;
1935 if (def
&& (method
->call_convention
== MONO_CALL_VARARG
))
1936 method
->sentinelpos
= method
->param_count
;
1943 * Add signature to a cache and increase ref count...
1950 * mono_metadata_parse_method_signature:
1951 * @m: metadata context
1952 * @def: the MethodDef index or 0 for Ref signatures.
1953 * @ptr: pointer to the signature metadata representation
1954 * @rptr: pointer updated to match the end of the decoded stream
1956 * Decode a method signature stored at @ptr.
1957 * This is a Mono runtime internal function.
1959 * LOCKING: Assumes the loader lock is held.
1961 * Returns: a MonoMethodSignature describing the signature.
1963 MonoMethodSignature
*
1964 mono_metadata_parse_method_signature (MonoImage
*m
, int def
, const char *ptr
, const char **rptr
)
1966 return mono_metadata_parse_method_signature_full (m
, NULL
, def
, ptr
, rptr
);
1970 * mono_metadata_free_method_signature:
1971 * @sig: signature to destroy
1973 * Free the memory allocated in the signature @sig.
1974 * This method needs to be robust and work also on partially-built
1975 * signatures, so it does extra checks.
1978 mono_metadata_free_method_signature (MonoMethodSignature
*sig
)
1980 /* Everything is allocated from mempools */
1984 mono_metadata_free_type (sig->ret);
1985 for (i = 0; i < sig->param_count; ++i) {
1986 if (sig->params [i])
1987 mono_metadata_free_type (sig->params [i]);
1993 mono_metadata_free_inflated_signature (MonoMethodSignature
*sig
)
1997 /* Allocated in inflate_generic_signature () */
1999 mono_metadata_free_type (sig
->ret
);
2000 for (i
= 0; i
< sig
->param_count
; ++i
) {
2001 if (sig
->params
[i
])
2002 mono_metadata_free_type (sig
->params
[i
]);
2008 inflated_method_equal (gconstpointer a
, gconstpointer b
)
2010 const MonoMethodInflated
*ma
= a
;
2011 const MonoMethodInflated
*mb
= b
;
2012 if (ma
->declaring
!= mb
->declaring
)
2014 if (ma
->method
.method
.is_mb_open
!= mb
->method
.method
.is_mb_open
)
2016 return mono_metadata_generic_context_equal (&ma
->context
, &mb
->context
);
2020 inflated_method_hash (gconstpointer a
)
2022 const MonoMethodInflated
*ma
= a
;
2023 return (mono_metadata_generic_context_hash (&ma
->context
) ^ mono_aligned_addr_hash (ma
->declaring
)) + ma
->method
.method
.is_mb_open
;
2027 inflated_signature_equal (gconstpointer a
, gconstpointer b
)
2029 const MonoInflatedMethodSignature
*sig1
= a
;
2030 const MonoInflatedMethodSignature
*sig2
= b
;
2032 /* sig->sig is assumed to be canonized */
2033 if (sig1
->sig
!= sig2
->sig
)
2035 /* The generic instances are canonized */
2036 return mono_metadata_generic_context_equal (&sig1
->context
, &sig2
->context
);
2040 inflated_signature_hash (gconstpointer a
)
2042 const MonoInflatedMethodSignature
*sig
= a
;
2044 /* sig->sig is assumed to be canonized */
2045 return mono_metadata_generic_context_hash (&sig
->context
) ^ mono_aligned_addr_hash (sig
->sig
);
2049 dump_ginst (MonoGenericInst *ginst)
2054 g_print ("Ginst: <");
2055 for (i = 0; i < ginst->type_argc; ++i) {
2058 name = mono_type_get_name (ginst->type_argv [i]);
2059 g_print ("%s", name);
2065 static gboolean
type_in_image (MonoType
*type
, MonoImage
*image
);
2068 signature_in_image (MonoMethodSignature
*sig
, MonoImage
*image
)
2070 gpointer iter
= NULL
;
2073 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2074 if (type_in_image (p
, image
))
2077 return type_in_image (mono_signature_get_return_type (sig
), image
);
2081 ginst_in_image (MonoGenericInst
*ginst
, MonoImage
*image
)
2085 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2086 if (type_in_image (ginst
->type_argv
[i
], image
))
2094 gclass_in_image (MonoGenericClass
*gclass
, MonoImage
*image
)
2096 return gclass
->container_class
->image
== image
||
2097 ginst_in_image (gclass
->context
.class_inst
, image
);
2101 type_in_image (MonoType
*type
, MonoImage
*image
)
2104 switch (type
->type
) {
2105 case MONO_TYPE_GENERICINST
:
2106 return gclass_in_image (type
->data
.generic_class
, image
);
2108 type
= type
->data
.type
;
2110 case MONO_TYPE_SZARRAY
:
2111 type
= &type
->data
.klass
->byval_arg
;
2113 case MONO_TYPE_ARRAY
:
2114 type
= &type
->data
.array
->eklass
->byval_arg
;
2116 case MONO_TYPE_FNPTR
:
2117 return signature_in_image (type
->data
.method
, image
);
2118 case MONO_TYPE_VAR
: {
2119 MonoGenericContainer
*container
= mono_type_get_generic_param_owner (type
);
2121 g_assert (!container
->is_method
);
2123 * FIXME: The following check is here solely
2124 * for monodis, which uses the internal
2126 * mono_metadata_load_generic_params(). The
2127 * caller of that function needs to fill in
2128 * owner->klass or owner->method of the
2129 * returned struct, but monodis doesn't do
2130 * that. The image unloading depends on that,
2131 * however, so a crash results without this
2134 if (!container
->owner
.klass
)
2135 return container
->image
== image
;
2136 return container
->owner
.klass
->image
== image
;
2138 return type
->data
.generic_param
->image
== image
;
2141 case MONO_TYPE_MVAR
: {
2142 MonoGenericContainer
*container
= mono_type_get_generic_param_owner (type
);
2143 if (type
->data
.generic_param
->image
== image
)
2146 g_assert (container
->is_method
);
2147 if (!container
->owner
.method
)
2148 /* RefEmit created generic param whose method is not finished */
2149 return container
->image
== image
;
2150 return container
->owner
.method
->klass
->image
== image
;
2152 return type
->data
.generic_param
->image
== image
;
2156 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2157 return image
== mono_class_from_mono_type (type
)->image
;
2161 static MonoImageSet
*mscorlib_image_set
;
2162 static GPtrArray
*image_sets
;
2167 * Return a MonoImageSet representing the set of images in IMAGES.
2169 * LOCKING: Assumes the loader lock is held.
2171 static MonoImageSet
*
2172 get_image_set (MonoImage
**images
, int nimages
)
2179 image_sets
= g_ptr_array_new ();
2182 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
&& mscorlib_image_set
)
2183 return mscorlib_image_set
;
2185 /* Happens with empty generic instances */
2187 return mscorlib_image_set
;
2189 if (images
[0] == mono_defaults
.corlib
&& nimages
> 1)
2190 l
= images
[1]->image_sets
;
2192 l
= images
[0]->image_sets
;
2195 for (; l
; l
= l
->next
) {
2198 if (set
->nimages
== nimages
) {
2199 for (j
= 0; j
< nimages
; ++j
) {
2200 for (k
= 0; k
< nimages
; ++k
)
2201 if (set
->images
[k
] == images
[j
])
2215 set
= g_new0 (MonoImageSet
, 1);
2216 set
->nimages
= nimages
;
2217 set
->images
= g_new0 (MonoImage
*, nimages
);
2218 InitializeCriticalSection (&set
->lock
);
2219 for (i
= 0; i
< nimages
; ++i
)
2220 set
->images
[i
] = images
[i
];
2221 set
->gclass_cache
= g_hash_table_new_full (mono_generic_class_hash
, mono_generic_class_equal
, NULL
, (GDestroyNotify
)free_generic_class
);
2222 set
->ginst_cache
= g_hash_table_new_full (mono_metadata_generic_inst_hash
, mono_metadata_generic_inst_equal
, NULL
, (GDestroyNotify
)free_generic_inst
);
2223 set
->gmethod_cache
= g_hash_table_new_full (inflated_method_hash
, inflated_method_equal
, NULL
, (GDestroyNotify
)free_inflated_method
);
2224 set
->gsignature_cache
= g_hash_table_new_full (inflated_signature_hash
, inflated_signature_equal
, NULL
, (GDestroyNotify
)free_inflated_signature
);
2226 for (i
= 0; i
< nimages
; ++i
)
2227 set
->images
[i
]->image_sets
= g_slist_prepend (set
->images
[i
]->image_sets
, set
);
2229 g_ptr_array_add (image_sets
, set
);
2232 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
)
2233 mscorlib_image_set
= set
;
2239 delete_image_set (MonoImageSet
*set
)
2243 g_hash_table_destroy (set
->gclass_cache
);
2244 g_hash_table_destroy (set
->ginst_cache
);
2245 g_hash_table_destroy (set
->gmethod_cache
);
2246 g_hash_table_destroy (set
->gsignature_cache
);
2248 for (i
= 0; i
< set
->nimages
; ++i
)
2249 set
->images
[i
]->image_sets
= g_slist_remove (set
->images
[i
]->image_sets
, set
);
2251 g_ptr_array_remove (image_sets
, set
);
2254 mono_mempool_destroy (set
->mempool
);
2255 g_free (set
->images
);
2256 DeleteCriticalSection (&set
->lock
);
2261 * Structure used by the collect_..._images functions to store the image list.
2264 MonoImage
*image_buf
[64];
2266 int nimages
, images_len
;
2270 collect_data_init (CollectData
*data
)
2272 data
->images
= data
->image_buf
;
2273 data
->images_len
= 64;
2278 collect_data_free (CollectData
*data
)
2280 if (data
->images
!= data
->image_buf
)
2281 g_free (data
->images
);
2285 enlarge_data (CollectData
*data
)
2287 int new_len
= data
->images_len
< 16 ? 16 : data
->images_len
* 2;
2288 MonoImage
**d
= g_new (MonoImage
*, new_len
);
2291 g_assert_not_reached ();
2292 memcpy (d
, data
->images
, data
->images_len
);
2293 if (data
->images
!= data
->image_buf
)
2294 g_free (data
->images
);
2296 data
->images_len
= new_len
;
2300 add_image (MonoImage
*image
, CollectData
*data
)
2304 /* The arrays are small, so use a linear search instead of a hash table */
2305 for (i
= 0; i
< data
->nimages
; ++i
)
2306 if (data
->images
[i
] == image
)
2309 if (data
->nimages
== data
->images_len
)
2310 enlarge_data (data
);
2312 data
->images
[data
->nimages
++] = image
;
2316 collect_type_images (MonoType
*type
, CollectData
*data
);
2319 collect_ginst_images (MonoGenericInst
*ginst
, CollectData
*data
)
2323 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2324 collect_type_images (ginst
->type_argv
[i
], data
);
2329 collect_gclass_images (MonoGenericClass
*gclass
, CollectData
*data
)
2331 add_image (gclass
->container_class
->image
, data
);
2332 if (gclass
->context
.class_inst
)
2333 collect_ginst_images (gclass
->context
.class_inst
, data
);
2337 collect_signature_images (MonoMethodSignature
*sig
, CollectData
*data
)
2339 gpointer iter
= NULL
;
2342 collect_type_images (mono_signature_get_return_type (sig
), data
);
2343 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2344 collect_type_images (p
, data
);
2348 collect_inflated_signature_images (MonoInflatedMethodSignature
*sig
, CollectData
*data
)
2350 collect_signature_images (sig
->sig
, data
);
2351 if (sig
->context
.class_inst
)
2352 collect_ginst_images (sig
->context
.class_inst
, data
);
2353 if (sig
->context
.method_inst
)
2354 collect_ginst_images (sig
->context
.method_inst
, data
);
2358 collect_method_images (MonoMethodInflated
*method
, CollectData
*data
)
2360 add_image (method
->declaring
->klass
->image
, data
);
2361 if (method
->context
.class_inst
)
2362 collect_ginst_images (method
->context
.class_inst
, data
);
2363 if (method
->context
.method_inst
)
2364 collect_ginst_images (method
->context
.method_inst
, data
);
2366 if (((MonoMethod*)method)->signature)
2367 collect_signature_images (mono_method_signature ((MonoMethod*)method), data);
2372 collect_type_images (MonoType
*type
, CollectData
*data
)
2375 switch (type
->type
) {
2376 case MONO_TYPE_GENERICINST
:
2377 collect_gclass_images (type
->data
.generic_class
, data
);
2380 type
= type
->data
.type
;
2382 case MONO_TYPE_SZARRAY
:
2383 type
= &type
->data
.klass
->byval_arg
;
2385 case MONO_TYPE_ARRAY
:
2386 type
= &type
->data
.array
->eklass
->byval_arg
;
2388 case MONO_TYPE_FNPTR
:
2389 //return signature_in_image (type->data.method, image);
2390 g_assert_not_reached ();
2391 case MONO_TYPE_VAR
: {
2392 MonoGenericContainer
*container
= mono_type_get_generic_param_owner (type
);
2394 g_assert (!container
->is_method
);
2396 * FIXME: The following check is here solely
2397 * for monodis, which uses the internal
2399 * mono_metadata_load_generic_params(). The
2400 * caller of that function needs to fill in
2401 * owner->klass or owner->method of the
2402 * returned struct, but monodis doesn't do
2403 * that. The image unloading depends on that,
2404 * however, so a crash results without this
2407 if (!container
->owner
.klass
)
2408 add_image (container
->image
, data
);
2410 add_image (container
->owner
.klass
->image
, data
);
2412 add_image (type
->data
.generic_param
->image
, data
);
2416 case MONO_TYPE_MVAR
: {
2417 MonoGenericContainer
*container
= mono_type_get_generic_param_owner (type
);
2418 if (type
->data
.generic_param
->image
)
2419 add_image (type
->data
.generic_param
->image
, data
);
2421 if (!container
->owner
.method
) {
2422 /* RefEmit created generic param whose method is not finished */
2423 add_image (container
->image
, data
);
2425 g_assert (container
->is_method
);
2426 add_image (container
->owner
.method
->klass
->image
, data
);
2429 add_image (type
->data
.generic_param
->image
, data
);
2433 case MONO_TYPE_CLASS
:
2434 case MONO_TYPE_VALUETYPE
:
2435 add_image (mono_class_from_mono_type (type
)->image
, data
);
2438 add_image (mono_defaults
.corlib
, data
);
2445 } CleanForImageUserData
;
2448 steal_gclass_in_image (gpointer key
, gpointer value
, gpointer data
)
2450 MonoGenericClass
*gclass
= key
;
2451 CleanForImageUserData
*user_data
= data
;
2453 g_assert (gclass_in_image (gclass
, user_data
->image
));
2455 user_data
->list
= g_slist_prepend (user_data
->list
, gclass
);
2460 steal_ginst_in_image (gpointer key
, gpointer value
, gpointer data
)
2462 MonoGenericInst
*ginst
= key
;
2463 CleanForImageUserData
*user_data
= data
;
2465 // This doesn't work during corlib compilation
2466 //g_assert (ginst_in_image (ginst, user_data->image));
2468 user_data
->list
= g_slist_prepend (user_data
->list
, ginst
);
2473 inflated_method_in_image (gpointer key
, gpointer value
, gpointer data
)
2475 MonoImage
*image
= data
;
2476 MonoMethodInflated
*method
= key
;
2479 // https://bugzilla.novell.com/show_bug.cgi?id=458168
2480 g_assert (method
->declaring
->klass
->image
== image
||
2481 (method
->context
.class_inst
&& ginst_in_image (method
->context
.class_inst
, image
)) ||
2482 (method
->context
.method_inst
&& ginst_in_image (method
->context
.method_inst
, image
)) || (((MonoMethod
*)method
)->signature
&& signature_in_image (mono_method_signature ((MonoMethod
*)method
), image
)));
2488 inflated_signature_in_image (gpointer key
, gpointer value
, gpointer data
)
2490 MonoImage
*image
= data
;
2491 MonoInflatedMethodSignature
*sig
= key
;
2493 return signature_in_image (sig
->sig
, image
) ||
2494 (sig
->context
.class_inst
&& ginst_in_image (sig
->context
.class_inst
, image
)) ||
2495 (sig
->context
.method_inst
&& ginst_in_image (sig
->context
.method_inst
, image
));
2499 check_gmethod (gpointer key
, gpointer value
, gpointer data
)
2501 MonoMethodInflated
*method
= key
;
2502 MonoImage
*image
= data
;
2504 if (method
->context
.class_inst
)
2505 g_assert (!ginst_in_image (method
->context
.class_inst
, image
));
2506 if (method
->context
.method_inst
)
2507 g_assert (!ginst_in_image (method
->context
.method_inst
, image
));
2508 if (((MonoMethod
*)method
)->signature
)
2509 g_assert (!signature_in_image (mono_method_signature ((MonoMethod
*)method
), image
));
2515 * Run a consistency check on the image set data structures.
2517 static G_GNUC_UNUSED
void
2518 check_image_sets (MonoImage
*image
)
2521 GSList
*l
= image
->image_sets
;
2526 for (i
= 0; i
< image_sets
->len
; ++i
) {
2527 MonoImageSet
*set
= g_ptr_array_index (image_sets
, i
);
2529 if (!g_slist_find (l
, set
)) {
2530 g_hash_table_foreach (set
->gmethod_cache
, check_gmethod
, image
);
2536 mono_metadata_clean_for_image (MonoImage
*image
)
2538 CleanForImageUserData ginst_data
, gclass_data
;
2539 GSList
*l
, *set_list
, *free_list
= NULL
;
2541 //check_image_sets (image);
2543 /* The data structures could reference each other so we delete them in two phases */
2544 ginst_data
.image
= gclass_data
.image
= image
;
2545 ginst_data
.list
= gclass_data
.list
= NULL
;
2546 mono_loader_lock ();
2548 /* Collect the items to delete */
2549 /* delete_image_set () modifies the lists so make a copy */
2550 for (l
= image
->image_sets
; l
; l
= l
->next
) {
2551 MonoImageSet
*set
= l
->data
;
2553 g_hash_table_foreach_steal (set
->gclass_cache
, steal_gclass_in_image
, &gclass_data
);
2554 g_hash_table_foreach_steal (set
->ginst_cache
, steal_ginst_in_image
, &ginst_data
);
2555 g_hash_table_foreach_remove (set
->gmethod_cache
, inflated_method_in_image
, image
);
2556 g_hash_table_foreach_remove (set
->gsignature_cache
, inflated_signature_in_image
, image
);
2559 /* Delete the removed items */
2560 for (l
= ginst_data
.list
; l
; l
= l
->next
)
2561 free_list
= g_slist_concat (free_generic_inst_dependents (l
->data
), free_list
);
2562 for (l
= gclass_data
.list
; l
; l
= l
->next
)
2563 free_list
= g_slist_concat (free_generic_class_dependents (l
->data
), free_list
);
2564 g_slist_free (ginst_data
.list
);
2565 g_slist_free (gclass_data
.list
);
2566 /* delete_image_set () modifies the lists so make a copy */
2567 set_list
= g_slist_copy (image
->image_sets
);
2568 for (l
= set_list
; l
; l
= l
->next
) {
2569 MonoImageSet
*set
= l
->data
;
2571 delete_image_set (set
);
2573 g_slist_free (set_list
);
2575 mono_loader_unlock ();
2581 free_inflated_method (MonoMethodInflated
*imethod
)
2584 MonoMethod
*method
= (MonoMethod
*)imethod
;
2586 mono_marshal_free_inflated_wrappers (method
);
2588 if (method
->signature
)
2589 mono_metadata_free_inflated_signature (method
->signature
);
2591 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
))) {
2592 MonoMethodHeader
*header
= imethod
->header
;
2595 /* Allocated in inflate_generic_header () */
2596 for (i
= 0; i
< header
->num_locals
; ++i
)
2597 mono_metadata_free_type (header
->locals
[i
]);
2598 g_free (header
->clauses
);
2607 free_list_with_data (GSList
*l
)
2611 l
= g_slist_delete_link (l
, l
);
2616 free_generic_inst_dependents (MonoGenericInst
*ginst
)
2620 for (i
= 0; i
< ginst
->type_argc
; ++i
)
2621 mono_metadata_free_type (ginst
->type_argv
[i
]);
2622 return g_slist_prepend (NULL
, ginst
);
2626 free_generic_inst (MonoGenericInst
*ginst
)
2628 free_list_with_data (free_generic_inst_dependents (ginst
));
2632 free_generic_class_dependents (MonoGenericClass
*gclass
)
2637 /* FIXME: The dynamic case */
2638 if (gclass
->cached_class
&& !gclass
->cached_class
->image
->dynamic
&& !mono_generic_class_is_generic_type_definition (gclass
)) {
2639 MonoClass
*class = gclass
->cached_class
;
2641 /* Allocated in mono_class_init () */
2642 g_free (class->methods
);
2644 g_free (class->ext
->properties
);
2645 /* Allocated in mono_generic_class_get_class () */
2646 g_free (class->interfaces
);
2647 l
= g_slist_prepend (l
, class);
2648 } else if (gclass
->is_dynamic
) {
2649 MonoDynamicGenericClass
*dgclass
= (MonoDynamicGenericClass
*)gclass
;
2651 for (i
= 0; i
< dgclass
->count_fields
; ++i
) {
2652 MonoClassField
*field
= dgclass
->fields
+ i
;
2653 mono_metadata_free_type (field
->type
);
2654 g_free ((char*)field
->name
);
2656 MONO_GC_UNREGISTER_ROOT (dgclass
->field_objects
[i
]);
2660 g_free (dgclass
->methods
);
2661 g_free (dgclass
->ctors
);
2662 g_free (dgclass
->fields
);
2663 g_free (dgclass
->field_objects
);
2664 g_free (dgclass
->field_generic_types
);
2665 if (!mono_generic_class_is_generic_type_definition (gclass
))
2666 l
= g_slist_prepend (l
, gclass
->cached_class
);
2668 return g_slist_prepend (l
, gclass
);
2672 free_generic_class (MonoGenericClass
*gclass
)
2674 free_list_with_data (free_generic_class_dependents (gclass
));
2678 free_inflated_signature (MonoInflatedMethodSignature
*sig
)
2680 mono_metadata_free_inflated_signature (sig
->sig
);
2685 * LOCKING: assumes the loader lock is held.
2688 mono_method_inflated_lookup (MonoMethodInflated
* method
, gboolean cache
)
2693 collect_data_init (&data
);
2695 collect_method_images (method
, &data
);
2697 set
= get_image_set (data
.images
, data
.nimages
);
2699 collect_data_free (&data
);
2702 g_hash_table_insert (set
->gmethod_cache
, method
, method
);
2706 return g_hash_table_lookup (set
->gmethod_cache
, method
);
2711 * mono_metadata_get_inflated_signature:
2713 * Given an inflated signature and a generic context, return a canonical copy of the
2714 * signature. The returned signature might be equal to SIG or it might be a cached copy.
2716 MonoMethodSignature
*
2717 mono_metadata_get_inflated_signature (MonoMethodSignature
*sig
, MonoGenericContext
*context
)
2719 MonoInflatedMethodSignature helper
;
2720 MonoInflatedMethodSignature
*res
;
2724 mono_loader_lock ();
2727 helper
.context
.class_inst
= context
->class_inst
;
2728 helper
.context
.method_inst
= context
->method_inst
;
2730 collect_data_init (&data
);
2732 collect_inflated_signature_images (&helper
, &data
);
2734 set
= get_image_set (data
.images
, data
.nimages
);
2736 collect_data_free (&data
);
2738 res
= g_hash_table_lookup (set
->gsignature_cache
, &helper
);
2740 res
= g_new0 (MonoInflatedMethodSignature
, 1);
2742 res
->context
.class_inst
= context
->class_inst
;
2743 res
->context
.method_inst
= context
->method_inst
;
2744 g_hash_table_insert (set
->gsignature_cache
, res
, res
);
2747 mono_loader_unlock ();
2752 * mono_metadata_get_generic_inst:
2754 * Given a list of types, return a MonoGenericInst that represents that list.
2755 * The returned MonoGenericInst has its own copy of the list of types. The list
2756 * passed in the argument can be freed, modified or disposed of.
2760 mono_metadata_get_generic_inst (int type_argc
, MonoType
**type_argv
)
2762 MonoGenericInst
*ginst
;
2765 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
2769 for (i
= 0; i
< type_argc
; ++i
)
2770 if (mono_class_is_open_constructed_type (type_argv
[i
]))
2772 is_open
= (i
< type_argc
);
2774 ginst
= alloca (size
);
2775 #ifndef MONO_SMALL_CONFIG
2778 ginst
->is_open
= is_open
;
2779 ginst
->type_argc
= type_argc
;
2780 memcpy (ginst
->type_argv
, type_argv
, type_argc
* sizeof (MonoType
*));
2782 mono_loader_lock ();
2784 collect_data_init (&data
);
2786 collect_ginst_images (ginst
, &data
);
2788 set
= get_image_set (data
.images
, data
.nimages
);
2790 collect_data_free (&data
);
2792 ginst
= g_hash_table_lookup (set
->ginst_cache
, ginst
);
2794 ginst
= g_malloc (size
);
2795 #ifndef MONO_SMALL_CONFIG
2796 ginst
->id
= ++next_generic_inst_id
;
2798 ginst
->is_open
= is_open
;
2799 ginst
->type_argc
= type_argc
;
2801 for (i
= 0; i
< type_argc
; ++i
)
2802 ginst
->type_argv
[i
] = mono_metadata_type_dup (NULL
, type_argv
[i
]);
2804 g_hash_table_insert (set
->ginst_cache
, ginst
, ginst
);
2807 mono_loader_unlock ();
2812 mono_metadata_is_type_builder_generic_type_definition (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
2814 MonoGenericContainer
*container
= container_class
->generic_container
;
2816 if (!is_dynamic
|| container_class
->wastypebuilder
|| container
->type_argc
!= inst
->type_argc
)
2818 return inst
== container
->context
.class_inst
;
2822 * mono_metadata_lookup_generic_class:
2824 * Returns a MonoGenericClass with the given properties.
2828 mono_metadata_lookup_generic_class (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
2830 MonoGenericClass
*gclass
;
2831 MonoGenericClass helper
;
2832 gboolean is_tb_open
= mono_metadata_is_type_builder_generic_type_definition (container_class
, inst
, is_dynamic
);
2836 helper
.container_class
= container_class
;
2837 helper
.context
.class_inst
= inst
;
2838 helper
.context
.method_inst
= NULL
;
2839 helper
.is_dynamic
= is_dynamic
; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
2840 helper
.is_tb_open
= is_tb_open
;
2841 helper
.cached_class
= NULL
;
2843 mono_loader_lock ();
2845 collect_data_init (&data
);
2847 collect_gclass_images (&helper
, &data
);
2849 set
= get_image_set (data
.images
, data
.nimages
);
2851 collect_data_free (&data
);
2853 gclass
= g_hash_table_lookup (set
->gclass_cache
, &helper
);
2855 /* A tripwire just to keep us honest */
2856 g_assert (!helper
.cached_class
);
2859 mono_loader_unlock ();
2864 MonoDynamicGenericClass
*dgclass
= g_new0 (MonoDynamicGenericClass
, 1);
2865 gclass
= &dgclass
->generic_class
;
2866 gclass
->is_dynamic
= 1;
2868 gclass
= g_new0 (MonoGenericClass
, 1);
2871 gclass
->is_tb_open
= is_tb_open
;
2872 gclass
->container_class
= container_class
;
2873 gclass
->context
.class_inst
= inst
;
2874 gclass
->context
.method_inst
= NULL
;
2875 if (inst
== container_class
->generic_container
->context
.class_inst
&& !is_tb_open
)
2876 gclass
->cached_class
= container_class
;
2878 g_hash_table_insert (set
->gclass_cache
, gclass
, gclass
);
2880 mono_loader_unlock ();
2886 * mono_metadata_inflate_generic_inst:
2888 * Instantiate the generic instance @ginst with the context @context.
2889 * Check @error for success.
2893 mono_metadata_inflate_generic_inst (MonoGenericInst
*ginst
, MonoGenericContext
*context
, MonoError
*error
)
2895 MonoType
**type_argv
;
2896 MonoGenericInst
*nginst
= NULL
;
2899 mono_error_init (error
);
2901 if (!ginst
->is_open
)
2904 type_argv
= g_new0 (MonoType
*, ginst
->type_argc
);
2906 for (i
= 0; i
< ginst
->type_argc
; i
++) {
2907 type_argv
[i
] = mono_class_inflate_generic_type_checked (ginst
->type_argv
[i
], context
, error
);
2908 if (!mono_error_ok (error
))
2913 nginst
= mono_metadata_get_generic_inst (ginst
->type_argc
, type_argv
);
2916 for (i
= 0; i
< count
; i
++)
2917 mono_metadata_free_type (type_argv
[i
]);
2924 mono_metadata_parse_generic_inst (MonoImage
*m
, MonoGenericContainer
*container
,
2925 int count
, const char *ptr
, const char **rptr
)
2927 MonoType
**type_argv
;
2928 MonoGenericInst
*ginst
;
2931 type_argv
= g_new0 (MonoType
*, count
);
2933 for (i
= 0; i
< count
; i
++) {
2934 MonoType
*t
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
2945 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
2953 do_mono_metadata_parse_generic_class (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
2954 const char *ptr
, const char **rptr
)
2956 MonoGenericInst
*inst
;
2961 gtype
= mono_metadata_parse_type (m
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
2965 gklass
= mono_class_from_mono_type (gtype
);
2966 if (!gklass
->generic_container
)
2969 count
= mono_metadata_decode_value (ptr
, &ptr
);
2970 inst
= mono_metadata_parse_generic_inst (m
, container
, count
, ptr
, &ptr
);
2977 type
->data
.generic_class
= mono_metadata_lookup_generic_class (gklass
, inst
, FALSE
);
2983 * @gc: The generic container to normalize
2984 * @type: The kind of generic parameters the resulting generic-container should contain
2987 static MonoGenericContainer
*
2988 select_container (MonoGenericContainer
*gc
, MonoTypeEnum type
)
2990 gboolean is_var
= (type
== MONO_TYPE_VAR
);
2994 g_assert (is_var
|| type
== MONO_TYPE_MVAR
);
2997 if (gc
->is_method
|| gc
->parent
)
2999 * The current MonoGenericContainer is a generic method -> its `parent'
3000 * points to the containing class'es container.
3009 * mono_metadata_parse_generic_param:
3010 * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3011 * see mono_metadata_parse_type_full() for details.
3012 * Internal routine to parse a generic type parameter.
3013 * LOCKING: Acquires the loader lock
3015 static MonoGenericParam
*
3016 mono_metadata_parse_generic_param (MonoImage
*m
, MonoGenericContainer
*generic_container
,
3017 MonoTypeEnum type
, const char *ptr
, const char **rptr
)
3019 int index
= mono_metadata_decode_value (ptr
, &ptr
);
3023 generic_container
= select_container (generic_container
, type
);
3024 if (!generic_container
) {
3025 /* Create dummy MonoGenericParam */
3026 MonoGenericParam
*param
;
3028 param
= mono_image_alloc0 (m
, sizeof (MonoGenericParam
));
3035 if (index
>= generic_container
->type_argc
)
3038 return mono_generic_container_get_param (generic_container
, index
);
3042 * mono_metadata_get_shared_type:
3044 * Return a shared instance of TYPE, if available, NULL otherwise.
3045 * Shared MonoType instances help save memory. Their contents should not be modified
3046 * by the caller. They do not need to be freed as their lifetime is bound by either
3047 * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3048 * instance they are embedded in. If they are freed, they should be freed using
3049 * mono_metadata_free_type () instead of g_free ().
3052 mono_metadata_get_shared_type (MonoType
*type
)
3056 /* No need to use locking since nobody is modifying the hash table */
3057 if ((cached
= g_hash_table_lookup (type_cache
, type
)))
3060 switch (type
->type
){
3061 case MONO_TYPE_CLASS
:
3062 case MONO_TYPE_VALUETYPE
:
3063 if (type
== &type
->data
.klass
->byval_arg
)
3065 if (type
== &type
->data
.klass
->this_arg
)
3074 * do_mono_metadata_parse_type:
3075 * @type: MonoType to be filled in with the return value
3077 * @generic_context: generics_context
3078 * @ptr: pointer to the encoded type
3079 * @rptr: pointer where the end of the encoded type is saved
3081 * Internal routine used to "fill" the contents of @type from an
3082 * allocated pointer. This is done this way to avoid doing too
3083 * many mini-allocations (particularly for the MonoFieldType which
3084 * most of the time is just a MonoType, but sometimes might be augmented).
3086 * This routine is used by mono_metadata_parse_type and
3087 * mono_metadata_parse_field_type
3089 * This extracts a Type as specified in Partition II (22.2.12)
3091 * Returns: FALSE if the type could not be loaded
3094 do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
3095 const char *ptr
, const char **rptr
)
3098 type
->type
= mono_metadata_decode_value (ptr
, &ptr
);
3100 switch (type
->type
){
3101 case MONO_TYPE_VOID
:
3102 case MONO_TYPE_BOOLEAN
:
3103 case MONO_TYPE_CHAR
:
3116 case MONO_TYPE_STRING
:
3117 case MONO_TYPE_OBJECT
:
3118 case MONO_TYPE_TYPEDBYREF
:
3120 case MONO_TYPE_VALUETYPE
:
3121 case MONO_TYPE_CLASS
: {
3123 token
= mono_metadata_parse_typedef_or_ref (m
, ptr
, &ptr
);
3124 type
->data
.klass
= mono_class_get (m
, token
);
3125 if (!type
->data
.klass
)
3129 case MONO_TYPE_SZARRAY
: {
3130 MonoType
*etype
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_MOD_TYPE
, 0, ptr
, &ptr
);
3133 type
->data
.klass
= mono_class_from_mono_type (etype
);
3134 if (!type
->data
.klass
)
3139 type
->data
.type
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_MOD_TYPE
, 0, ptr
, &ptr
);
3140 if (!type
->data
.type
)
3143 case MONO_TYPE_FNPTR
:
3144 type
->data
.method
= mono_metadata_parse_method_signature_full (m
, container
, 0, ptr
, &ptr
);
3145 if (!type
->data
.method
)
3148 case MONO_TYPE_ARRAY
:
3149 type
->data
.array
= mono_metadata_parse_array_full (m
, container
, ptr
, &ptr
);
3150 if (!type
->data
.array
)
3153 case MONO_TYPE_MVAR
:
3154 if (container
&& !container
->is_method
)
3157 type
->data
.generic_param
= mono_metadata_parse_generic_param (m
, container
, type
->type
, ptr
, &ptr
);
3158 if (!type
->data
.generic_param
)
3161 case MONO_TYPE_GENERICINST
:
3162 ok
= do_mono_metadata_parse_generic_class (type
, m
, container
, ptr
, &ptr
);
3165 g_warning ("type 0x%02x not handled in do_mono_metadata_parse_type on image %s", type
->type
, m
->name
);
3175 * mono_metadata_free_type:
3176 * @type: type to free
3178 * Free the memory allocated for type @type which is allocated on the heap.
3181 mono_metadata_free_type (MonoType
*type
)
3183 if (type
>= builtin_types
&& type
< builtin_types
+ NBUILTIN_TYPES ())
3186 switch (type
->type
){
3187 case MONO_TYPE_OBJECT
:
3188 case MONO_TYPE_STRING
:
3189 if (!type
->data
.klass
)
3192 case MONO_TYPE_CLASS
:
3193 case MONO_TYPE_VALUETYPE
:
3194 if (type
== &type
->data
.klass
->byval_arg
|| type
== &type
->data
.klass
->this_arg
)
3198 mono_metadata_free_type (type
->data
.type
);
3200 case MONO_TYPE_FNPTR
:
3201 mono_metadata_free_method_signature (type
->data
.method
);
3203 case MONO_TYPE_ARRAY
:
3204 mono_metadata_free_array (type
->data
.array
);
3213 hex_dump (const char *buffer
, int base
, int count
)
3215 int show_header
= 1;
3223 for (i
= 0; i
< count
; i
++){
3226 printf ("\n0x%08x: ", (unsigned char) base
+ i
);
3228 printf ("%02x ", (unsigned char) (buffer
[i
]));
3235 * @ptr: Points to the beginning of the Section Data (25.3)
3237 static MonoExceptionClause
*
3238 parse_section_data (MonoImage
*m
, int *num_clauses
, const unsigned char *ptr
)
3240 unsigned char sect_data_flags
;
3241 const unsigned char *sptr
;
3243 guint32 sect_data_len
;
3244 MonoExceptionClause
* clauses
= NULL
;
3247 /* align on 32-bit boundary */
3248 sptr
= ptr
= dword_align (ptr
);
3249 sect_data_flags
= *ptr
;
3252 is_fat
= sect_data_flags
& METHOD_HEADER_SECTION_FAT_FORMAT
;
3254 sect_data_len
= (ptr
[2] << 16) | (ptr
[1] << 8) | ptr
[0];
3257 sect_data_len
= ptr
[0];
3261 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
3262 hex_dump (sptr, 0, sect_data_len+8);
3263 g_print ("\nheader: ");
3264 hex_dump (sptr-4, 0, 4);
3268 if (sect_data_flags
& METHOD_HEADER_SECTION_EHTABLE
) {
3269 const unsigned char *p
= dword_align (ptr
);
3271 *num_clauses
= is_fat
? sect_data_len
/ 24: sect_data_len
/ 12;
3272 /* we could just store a pointer if we don't need to byteswap */
3273 clauses
= g_malloc0 (sizeof (MonoExceptionClause
) * (*num_clauses
));
3274 for (i
= 0; i
< *num_clauses
; ++i
) {
3275 MonoExceptionClause
*ec
= &clauses
[i
];
3278 ec
->flags
= read32 (p
);
3279 ec
->try_offset
= read32 (p
+ 4);
3280 ec
->try_len
= read32 (p
+ 8);
3281 ec
->handler_offset
= read32 (p
+ 12);
3282 ec
->handler_len
= read32 (p
+ 16);
3283 tof_value
= read32 (p
+ 20);
3286 ec
->flags
= read16 (p
);
3287 ec
->try_offset
= read16 (p
+ 2);
3288 ec
->try_len
= *(p
+ 4);
3289 ec
->handler_offset
= read16 (p
+ 5);
3290 ec
->handler_len
= *(p
+ 7);
3291 tof_value
= read32 (p
+ 8);
3294 if (ec
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
) {
3295 ec
->data
.filter_offset
= tof_value
;
3296 } else if (ec
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) {
3297 ec
->data
.catch_class
= tof_value
? mono_class_get (m
, tof_value
): 0;
3299 ec
->data
.catch_class
= NULL
;
3301 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
3305 if (sect_data_flags
& METHOD_HEADER_SECTION_MORE_SECTS
)
3306 ptr
+= sect_data_len
- 4; /* LAMESPEC: it seems the size includes the header */
3313 * mono_method_get_header_summary:
3314 * @method: The method to get the header.
3315 * @summary: Where to store the header
3318 * Returns: true if the header was properly decoded.
3321 mono_method_get_header_summary (MonoMethod
*method
, MonoMethodHeaderSummary
*summary
)
3327 unsigned char flags
, format
;
3330 /*Only the GMD has a pointer to the metadata.*/
3331 while (method
->is_inflated
)
3332 method
= ((MonoMethodInflated
*)method
)->declaring
;
3334 summary
->code_size
= 0;
3335 summary
->has_clauses
= FALSE
;
3337 /*FIXME extract this into a MACRO and share it with mono_method_get_header*/
3338 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
))
3341 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| method
->sre_method
) {
3342 MonoMethodHeader
*header
= ((MonoMethodWrapper
*)method
)->header
;
3345 summary
->code_size
= header
->code_size
;
3346 summary
->has_clauses
= header
->num_clauses
> 0;
3351 idx
= mono_metadata_token_index (method
->token
);
3352 img
= method
->klass
->image
;
3353 rva
= mono_metadata_decode_row_col (&img
->tables
[MONO_TABLE_METHOD
], idx
- 1, MONO_METHOD_RVA
);
3355 /*We must run the verifier since we'll be decoding it.*/
3356 if (!mono_verifier_verify_method_header (img
, rva
, NULL
))
3359 ptr
= mono_image_rva_map (img
, rva
);
3362 flags
= *(const unsigned char *)ptr
;
3363 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
3366 case METHOD_HEADER_TINY_FORMAT
:
3368 summary
->code_size
= flags
>> 2;
3370 case METHOD_HEADER_FAT_FORMAT
:
3371 fat_flags
= read16 (ptr
);
3373 summary
->code_size
= read32 (ptr
);
3374 if (fat_flags
& METHOD_HEADER_MORE_SECTS
)
3375 summary
->has_clauses
= TRUE
;
3384 * mono_metadata_parse_mh_full:
3385 * @m: metadata context
3386 * @generic_context: generics context
3387 * @ptr: pointer to the method header.
3389 * Decode the method header at @ptr, including pointer to the IL code,
3390 * info about local variables and optional exception tables.
3391 * This is a Mono runtime internal function.
3393 * LOCKING: Acquires the loader lock.
3395 * Returns: a MonoMethodHeader allocated from the image mempool.
3398 mono_metadata_parse_mh_full (MonoImage
*m
, MonoGenericContainer
*container
, const char *ptr
)
3400 MonoMethodHeader
*mh
;
3401 unsigned char flags
= *(const unsigned char *) ptr
;
3402 unsigned char format
= flags
& METHOD_HEADER_FORMAT_MASK
;
3404 guint32 local_var_sig_tok
, max_stack
, code_size
, init_locals
;
3405 const unsigned char *code
;
3406 MonoExceptionClause
* clauses
= NULL
;
3407 int hsize
, num_clauses
= 0;
3408 MonoTableInfo
*t
= &m
->tables
[MONO_TABLE_STANDALONESIG
];
3409 guint32 cols
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
3411 g_return_val_if_fail (ptr
!= NULL
, NULL
);
3414 case METHOD_HEADER_TINY_FORMAT
:
3415 mh
= g_malloc0 (MONO_SIZEOF_METHOD_HEADER
);
3418 mh
->is_transient
= TRUE
;
3419 local_var_sig_tok
= 0;
3420 mh
->code_size
= flags
>> 2;
3421 mh
->code
= (unsigned char*)ptr
;
3423 case METHOD_HEADER_FAT_FORMAT
:
3424 fat_flags
= read16 (ptr
);
3426 hsize
= (fat_flags
>> 12) & 0xf;
3427 max_stack
= read16 (ptr
);
3429 code_size
= read32 (ptr
);
3431 local_var_sig_tok
= read32 (ptr
);
3434 if (fat_flags
& METHOD_HEADER_INIT_LOCALS
)
3439 code
= (unsigned char*)ptr
;
3441 if (!(fat_flags
& METHOD_HEADER_MORE_SECTS
))
3445 * There are more sections
3447 ptr
= (char*)code
+ code_size
;
3453 if (local_var_sig_tok
) {
3454 int idx
= (local_var_sig_tok
& 0xffffff)-1;
3457 mono_metadata_decode_row (t
, idx
, cols
, 1);
3459 if (!mono_verifier_verify_standalone_signature (m
, cols
[MONO_STAND_ALONE_SIGNATURE
], NULL
))
3462 if (fat_flags
& METHOD_HEADER_MORE_SECTS
)
3463 clauses
= parse_section_data (m
, &num_clauses
, (const unsigned char*)ptr
);
3464 if (local_var_sig_tok
) {
3465 const char *locals_ptr
;
3466 int len
=0, i
, bsize
;
3468 locals_ptr
= mono_metadata_blob_heap (m
, cols
[MONO_STAND_ALONE_SIGNATURE
]);
3469 bsize
= mono_metadata_decode_blob_size (locals_ptr
, &locals_ptr
);
3470 if (*locals_ptr
!= 0x07)
3471 g_warning ("wrong signature for locals blob");
3473 len
= mono_metadata_decode_value (locals_ptr
, &locals_ptr
);
3474 mh
= g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ len
* sizeof (MonoType
*) + num_clauses
* sizeof (MonoExceptionClause
));
3475 mh
->num_locals
= len
;
3476 for (i
= 0; i
< len
; ++i
) {
3477 mh
->locals
[i
] = mono_metadata_parse_type_full (
3478 m
, container
, MONO_PARSE_LOCAL
, 0, locals_ptr
, &locals_ptr
);
3479 if (!mh
->locals
[i
]) {
3485 mh
= g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ num_clauses
* sizeof (MonoExceptionClause
));
3488 mh
->code_size
= code_size
;
3489 mh
->max_stack
= max_stack
;
3490 mh
->is_transient
= TRUE
;
3491 mh
->init_locals
= init_locals
;
3493 MonoExceptionClause
* clausesp
= (MonoExceptionClause
*)&mh
->locals
[mh
->num_locals
];
3494 memcpy (clausesp
, clauses
, num_clauses
* sizeof (MonoExceptionClause
));
3496 mh
->clauses
= clausesp
;
3497 mh
->num_clauses
= num_clauses
;
3503 * mono_metadata_parse_mh:
3504 * @generic_context: generics context
3505 * @ptr: pointer to the method header.
3507 * Decode the method header at @ptr, including pointer to the IL code,
3508 * info about local variables and optional exception tables.
3509 * This is a Mono runtime internal function.
3511 * Returns: a MonoMethodHeader.
3514 mono_metadata_parse_mh (MonoImage
*m
, const char *ptr
)
3516 MonoMethodHeader
*res
;
3518 mono_loader_lock ();
3520 res
= mono_metadata_parse_mh_full (m
, NULL
, ptr
);
3522 mono_loader_unlock ();
3528 * mono_metadata_free_mh:
3529 * @mh: a method header
3531 * Free the memory allocated for the method header.
3534 mono_metadata_free_mh (MonoMethodHeader
*mh
)
3536 /* If it is not transient it means it's part of a wrapper method,
3537 * or a SRE-generated method, so the lifetime in that case is
3538 * dictated by the method's own lifetime
3540 if (mh
->is_transient
)
3545 * mono_method_header_get_code:
3546 * @header: a MonoMethodHeader pointer
3547 * @code_size: memory location for returning the code size
3548 * @max_stack: memory location for returning the max stack
3550 * Method header accessor to retreive info about the IL code properties:
3551 * a pointer to the IL code itself, the size of the code and the max number
3552 * of stack slots used by the code.
3554 * Returns: pointer to the IL code represented by the method header.
3556 const unsigned char*
3557 mono_method_header_get_code (MonoMethodHeader
*header
, guint32
* code_size
, guint32
* max_stack
)
3560 *code_size
= header
->code_size
;
3562 *max_stack
= header
->max_stack
;
3563 return header
->code
;
3567 * mono_method_header_get_locals:
3568 * @header: a MonoMethodHeader pointer
3569 * @num_locals: memory location for returning the number of local variables
3570 * @init_locals: memory location for returning the init_locals flag
3572 * Method header accessor to retreive info about the local variables:
3573 * an array of local types, the number of locals and whether the locals
3574 * are supposed to be initialized to 0 on method entry
3576 * Returns: pointer to an array of types of the local variables
3579 mono_method_header_get_locals (MonoMethodHeader
*header
, guint32
* num_locals
, gboolean
*init_locals
)
3582 *num_locals
= header
->num_locals
;
3584 *init_locals
= header
->init_locals
;
3585 return header
->locals
;
3589 * mono_method_header_get_num_clauses:
3590 * @header: a MonoMethodHeader pointer
3592 * Method header accessor to retreive the number of exception clauses.
3594 * Returns: the number of exception clauses present
3597 mono_method_header_get_num_clauses (MonoMethodHeader
*header
)
3599 return header
->num_clauses
;
3603 * mono_method_header_get_clauses:
3604 * @header: a MonoMethodHeader pointer
3605 * @method: MonoMethod the header belongs to
3606 * @iter: pointer to a iterator
3607 * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
3609 * Get the info about the exception clauses in the method. Set *iter to NULL to
3610 * initiate the iteration, then call the method repeatedly until it returns FALSE.
3611 * At each iteration, the structure pointed to by clause if filled with the
3612 * exception clause information.
3614 * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
3618 mono_method_header_get_clauses (MonoMethodHeader
*header
, MonoMethod
*method
, gpointer
*iter
, MonoExceptionClause
*clause
)
3620 MonoExceptionClause
*sc
;
3621 /* later we'll be able to use this interface to parse the clause info on demand,
3622 * without allocating anything.
3624 if (!iter
|| !header
->num_clauses
)
3627 *iter
= sc
= header
->clauses
;
3633 if (sc
< header
->clauses
+ header
->num_clauses
) {
3642 * mono_metadata_parse_field_type:
3643 * @m: metadata context to extract information from
3644 * @ptr: pointer to the field signature
3645 * @rptr: pointer updated to match the end of the decoded stream
3647 * Parses the field signature, and returns the type information for it.
3649 * Returns: The MonoType that was extracted from @ptr.
3652 mono_metadata_parse_field_type (MonoImage
*m
, short field_flags
, const char *ptr
, const char **rptr
)
3654 return mono_metadata_parse_type (m
, MONO_PARSE_FIELD
, field_flags
, ptr
, rptr
);
3658 * mono_metadata_parse_param:
3659 * @m: metadata context to extract information from
3660 * @ptr: pointer to the param signature
3661 * @rptr: pointer updated to match the end of the decoded stream
3663 * Parses the param signature, and returns the type information for it.
3665 * Returns: The MonoType that was extracted from @ptr.
3668 mono_metadata_parse_param (MonoImage
*m
, const char *ptr
, const char **rptr
)
3670 return mono_metadata_parse_type (m
, MONO_PARSE_PARAM
, 0, ptr
, rptr
);
3674 * mono_metadata_token_from_dor:
3675 * @dor_token: A TypeDefOrRef coded index
3677 * dor_token is a TypeDefOrRef coded index: it contains either
3678 * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
3679 * bits contain an index into the table.
3681 * Returns: an expanded token
3684 mono_metadata_token_from_dor (guint32 dor_index
)
3688 table
= dor_index
& 0x03;
3689 idx
= dor_index
>> 2;
3692 case 0: /* TypeDef */
3693 return MONO_TOKEN_TYPE_DEF
| idx
;
3694 case 1: /* TypeRef */
3695 return MONO_TOKEN_TYPE_REF
| idx
;
3696 case 2: /* TypeSpec */
3697 return MONO_TOKEN_TYPE_SPEC
| idx
;
3699 g_assert_not_reached ();
3706 * We use this to pass context information to the row locator
3709 int idx
; /* The index that we are trying to locate */
3710 int col_idx
; /* The index in the row where idx may be stored */
3711 MonoTableInfo
*t
; /* pointer to the table */
3716 * How the row locator works.
3721 * ___|___------> _______
3724 * A column in the rows of table A references an index in table B.
3725 * For example A may be the TYPEDEF table and B the METHODDEF table.
3727 * Given an index in table B we want to get the row in table A
3728 * where the column n references our index in B.
3730 * In the locator_t structure:
3732 * col_idx is the column number
3733 * index is the index in table B
3734 * result will be the index in table A
3737 * Table A Table B column (in table A)
3738 * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
3739 * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
3740 * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
3741 * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
3742 * METHODSEM PROPERTY ASSOCIATION (encoded index)
3744 * Note that we still don't support encoded indexes.
3748 typedef_locator (const void *a
, const void *b
)
3750 locator_t
*loc
= (locator_t
*) a
;
3751 const char *bb
= (const char *) b
;
3752 int typedef_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3753 guint32 col
, col_next
;
3755 col
= mono_metadata_decode_row_col (loc
->t
, typedef_index
, loc
->col_idx
);
3761 * Need to check that the next row is valid.
3763 if (typedef_index
+ 1 < loc
->t
->rows
) {
3764 col_next
= mono_metadata_decode_row_col (loc
->t
, typedef_index
+ 1, loc
->col_idx
);
3765 if (loc
->idx
>= col_next
)
3768 if (col
== col_next
)
3772 loc
->result
= typedef_index
;
3778 table_locator (const void *a
, const void *b
)
3780 locator_t
*loc
= (locator_t
*) a
;
3781 const char *bb
= (const char *) b
;
3782 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3785 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
3787 if (loc
->idx
== col
) {
3788 loc
->result
= table_index
;
3798 declsec_locator (const void *a
, const void *b
)
3800 locator_t
*loc
= (locator_t
*) a
;
3801 const char *bb
= (const char *) b
;
3802 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3805 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
3807 if (loc
->idx
== col
) {
3808 loc
->result
= table_index
;
3820 * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
3821 * which contains IDX.
3824 search_ptr_table (MonoImage
*image
, int table
, int idx
)
3826 MonoTableInfo
*ptrdef
= &image
->tables
[table
];
3829 /* Use a linear search to find our index in the table */
3830 for (i
= 0; i
< ptrdef
->rows
; i
++)
3831 /* All the Ptr tables have the same structure */
3832 if (mono_metadata_decode_row_col (ptrdef
, i
, 0) == idx
)
3835 if (i
< ptrdef
->rows
)
3842 * mono_metadata_typedef_from_field:
3843 * @meta: metadata context
3844 * @index: FieldDef token
3846 * Returns: the 1-based index into the TypeDef table of the type that
3847 * declared the field described by @index, or 0 if not found.
3850 mono_metadata_typedef_from_field (MonoImage
*meta
, guint32 index
)
3852 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
3858 loc
.idx
= mono_metadata_token_index (index
);
3859 loc
.col_idx
= MONO_TYPEDEF_FIELD_LIST
;
3862 if (meta
->uncompressed_metadata
)
3863 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
3865 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
3868 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3869 return loc
.result
+ 1;
3873 * mono_metadata_typedef_from_method:
3874 * @meta: metadata context
3875 * @index: MethodDef token
3877 * Returns: the 1-based index into the TypeDef table of the type that
3878 * declared the method described by @index. 0 if not found.
3881 mono_metadata_typedef_from_method (MonoImage
*meta
, guint32 index
)
3883 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
3889 loc
.idx
= mono_metadata_token_index (index
);
3890 loc
.col_idx
= MONO_TYPEDEF_METHOD_LIST
;
3893 if (meta
->uncompressed_metadata
)
3894 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_METHOD_POINTER
, loc
.idx
);
3896 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
3899 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3900 return loc
.result
+ 1;
3904 * mono_metadata_interfaces_from_typedef_full:
3905 * @meta: metadata context
3906 * @index: typedef token
3907 * @interfaces: Out parameter used to store the interface array
3908 * @count: Out parameter used to store the number of interfaces
3909 * @heap_alloc_result: if TRUE the result array will be g_malloc'd
3910 * @context: The generic context
3912 * The array of interfaces that the @index typedef token implements is returned in
3913 * @interfaces. The number of elements in the array is returned in @count.
3915 * LOCKING: Assumes the loader lock is held.
3917 * Returns: TRUE on success, FALSE on failure.
3920 mono_metadata_interfaces_from_typedef_full (MonoImage
*meta
, guint32 index
, MonoClass
***interfaces
, guint
*count
, gboolean heap_alloc_result
, MonoGenericContext
*context
)
3922 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_INTERFACEIMPL
];
3925 guint32 cols
[MONO_INTERFACEIMPL_SIZE
];
3934 loc
.idx
= mono_metadata_token_index (index
);
3935 loc
.col_idx
= MONO_INTERFACEIMPL_CLASS
;
3938 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
3943 * We may end up in the middle of the rows...
3946 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_INTERFACEIMPL_CLASS
))
3952 while (pos
< tdef
->rows
) {
3953 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
3954 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
3959 if (heap_alloc_result
)
3960 result
= g_new0 (MonoClass
*, pos
- start
);
3962 result
= mono_image_alloc0 (meta
, sizeof (MonoClass
*) * (pos
- start
));
3965 while (pos
< tdef
->rows
) {
3968 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
3969 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
3971 iface
= mono_class_get_full (
3972 meta
, mono_metadata_token_from_dor (cols
[MONO_INTERFACEIMPL_INTERFACE
]), context
);
3975 result
[pos
- start
] = iface
;
3978 *count
= pos
- start
;
3979 *interfaces
= result
;
3984 * @meta: metadata context
3985 * @index: typedef token
3986 * @count: Out parameter used to store the number of interfaces
3988 * The array of interfaces that the @index typedef token implements is returned in
3989 * @interfaces. The number of elements in the array is returned in @count. The returned
3990 * array is g_malloc'd and the caller must free it.
3992 * LOCKING: Acquires the loader lock .
3994 * Returns: the interface array on success, NULL on failure.
3998 mono_metadata_interfaces_from_typedef (MonoImage
*meta
, guint32 index
, guint
*count
)
4000 MonoClass
**interfaces
;
4003 mono_loader_lock ();
4004 rv
= mono_metadata_interfaces_from_typedef_full (meta
, index
, &interfaces
, count
, TRUE
, NULL
);
4005 mono_loader_unlock ();
4013 * mono_metadata_nested_in_typedef:
4014 * @meta: metadata context
4015 * @index: typedef token
4017 * Returns: the 1-based index into the TypeDef table of the type
4018 * where the type described by @index is nested.
4019 * Retruns 0 if @index describes a non-nested type.
4022 mono_metadata_nested_in_typedef (MonoImage
*meta
, guint32 index
)
4024 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4030 loc
.idx
= mono_metadata_token_index (index
);
4031 loc
.col_idx
= MONO_NESTED_CLASS_NESTED
;
4034 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4037 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4038 return mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_NESTED_CLASS_ENCLOSING
) | MONO_TOKEN_TYPE_DEF
;
4042 * mono_metadata_nesting_typedef:
4043 * @meta: metadata context
4044 * @index: typedef token
4046 * Returns: the 1-based index into the TypeDef table of the first type
4047 * that is nested inside the type described by @index. The search starts at
4048 * @start_index. returns 0 if no such type is found.
4051 mono_metadata_nesting_typedef (MonoImage
*meta
, guint32 index
, guint32 start_index
)
4053 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4055 guint32 class_index
= mono_metadata_token_index (index
);
4060 start
= start_index
;
4062 while (start
<= tdef
->rows
) {
4063 if (class_index
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_NESTED_CLASS_ENCLOSING
))
4069 if (start
> tdef
->rows
)
4076 * mono_metadata_packing_from_typedef:
4077 * @meta: metadata context
4078 * @index: token representing a type
4080 * Returns: the info stored in the ClassLAyout table for the given typedef token
4081 * into the @packing and @size pointers.
4082 * Returns 0 if the info is not found.
4085 mono_metadata_packing_from_typedef (MonoImage
*meta
, guint32 index
, guint32
*packing
, guint32
*size
)
4087 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CLASSLAYOUT
];
4089 guint32 cols
[MONO_CLASS_LAYOUT_SIZE
];
4094 loc
.idx
= mono_metadata_token_index (index
);
4095 loc
.col_idx
= MONO_CLASS_LAYOUT_PARENT
;
4098 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4101 mono_metadata_decode_row (tdef
, loc
.result
, cols
, MONO_CLASS_LAYOUT_SIZE
);
4103 *packing
= cols
[MONO_CLASS_LAYOUT_PACKING_SIZE
];
4105 *size
= cols
[MONO_CLASS_LAYOUT_CLASS_SIZE
];
4107 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4108 return loc
.result
+ 1;
4112 * mono_metadata_custom_attrs_from_index:
4113 * @meta: metadata context
4114 * @index: token representing the parent
4116 * Returns: the 1-based index into the CustomAttribute table of the first
4117 * attribute which belongs to the metadata object described by @index.
4118 * Returns 0 if no such attribute is found.
4121 mono_metadata_custom_attrs_from_index (MonoImage
*meta
, guint32 index
)
4123 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4130 loc
.col_idx
= MONO_CUSTOM_ATTR_PARENT
;
4133 /* FIXME: Index translation */
4135 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4138 /* Find the first entry by searching backwards */
4139 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_CUSTOM_ATTR_PARENT
) == index
))
4142 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4143 return loc
.result
+ 1;
4147 * mono_metadata_declsec_from_index:
4148 * @meta: metadata context
4149 * @index: token representing the parent
4151 * Returns: the 0-based index into the DeclarativeSecurity table of the first
4152 * attribute which belongs to the metadata object described by @index.
4153 * Returns -1 if no such attribute is found.
4156 mono_metadata_declsec_from_index (MonoImage
*meta
, guint32 index
)
4158 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_DECLSECURITY
];
4165 loc
.col_idx
= MONO_DECL_SECURITY_PARENT
;
4168 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, declsec_locator
))
4171 /* Find the first entry by searching backwards */
4172 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_DECL_SECURITY_PARENT
) == index
))
4180 mono_backtrace (int limit
)
4185 backtrace (array
, limit
);
4186 names
= backtrace_symbols (array
, limit
);
4187 for (i
=0; i
< limit
; ++i
) {
4188 g_print ("\t%s\n", names
[i
]);
4195 /*#define __alignof__(a) sizeof(a)*/
4196 #define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
4201 * @t: the type to return the size of
4203 * Returns: the number of bytes required to hold an instance of this
4207 mono_type_size (MonoType
*t
, int *align
)
4214 *align
= __alignof__(gpointer
);
4215 return sizeof (gpointer
);
4219 case MONO_TYPE_VOID
:
4222 case MONO_TYPE_BOOLEAN
:
4223 *align
= __alignof__(gint8
);
4227 *align
= __alignof__(gint8
);
4229 case MONO_TYPE_CHAR
:
4232 *align
= __alignof__(gint16
);
4236 *align
= __alignof__(gint32
);
4239 *align
= __alignof__(float);
4243 *align
= __alignof__(gint64
);
4246 *align
= __alignof__(double);
4250 *align
= __alignof__(gpointer
);
4251 return sizeof (gpointer
);
4252 case MONO_TYPE_STRING
:
4253 *align
= __alignof__(gpointer
);
4254 return sizeof (gpointer
);
4255 case MONO_TYPE_OBJECT
:
4256 *align
= __alignof__(gpointer
);
4257 return sizeof (gpointer
);
4258 case MONO_TYPE_VALUETYPE
: {
4259 if (t
->data
.klass
->enumtype
)
4260 return mono_type_size (mono_class_enum_basetype (t
->data
.klass
), align
);
4262 return mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
4264 case MONO_TYPE_CLASS
:
4265 case MONO_TYPE_SZARRAY
:
4267 case MONO_TYPE_FNPTR
:
4268 case MONO_TYPE_ARRAY
:
4269 *align
= __alignof__(gpointer
);
4270 return sizeof (gpointer
);
4271 case MONO_TYPE_TYPEDBYREF
:
4272 return mono_class_value_size (mono_defaults
.typed_reference_class
, (guint32
*)align
);
4273 case MONO_TYPE_GENERICINST
: {
4274 MonoGenericClass
*gclass
= t
->data
.generic_class
;
4275 MonoClass
*container_class
= gclass
->container_class
;
4277 // g_assert (!gclass->inst->is_open);
4279 if (container_class
->valuetype
) {
4280 if (container_class
->enumtype
)
4281 return mono_type_size (mono_class_enum_basetype (container_class
), align
);
4283 return mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
4285 *align
= __alignof__(gpointer
);
4286 return sizeof (gpointer
);
4290 case MONO_TYPE_MVAR
:
4291 /* FIXME: Martin, this is wrong. */
4292 *align
= __alignof__(gpointer
);
4293 return sizeof (gpointer
);
4295 g_error ("mono_type_size: type 0x%02x unknown", t
->type
);
4301 * mono_type_stack_size:
4302 * @t: the type to return the size it uses on the stack
4304 * Returns: the number of bytes required to hold an instance of this
4305 * type on the runtime stack
4308 mono_type_stack_size (MonoType
*t
, int *align
)
4310 return mono_type_stack_size_internal (t
, align
, FALSE
);
4314 mono_type_stack_size_internal (MonoType
*t
, int *align
, gboolean allow_open
)
4317 #if SIZEOF_VOID_P == SIZEOF_REGISTER
4318 int stack_slot_size
= sizeof (gpointer
);
4319 int stack_slot_align
= __alignof__ (gpointer
);
4320 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
4321 int stack_slot_size
= SIZEOF_REGISTER
;
4322 int stack_slot_align
= SIZEOF_REGISTER
;
4325 g_assert (t
!= NULL
);
4331 *align
= stack_slot_align
;
4332 return stack_slot_size
;
4336 case MONO_TYPE_BOOLEAN
:
4337 case MONO_TYPE_CHAR
:
4346 case MONO_TYPE_STRING
:
4347 case MONO_TYPE_OBJECT
:
4348 case MONO_TYPE_CLASS
:
4349 case MONO_TYPE_SZARRAY
:
4351 case MONO_TYPE_FNPTR
:
4352 case MONO_TYPE_ARRAY
:
4353 *align
= stack_slot_align
;
4354 return stack_slot_size
;
4356 case MONO_TYPE_MVAR
:
4357 g_assert (allow_open
);
4358 *align
= stack_slot_align
;
4359 return stack_slot_size
;
4360 case MONO_TYPE_TYPEDBYREF
:
4361 *align
= stack_slot_align
;
4362 return stack_slot_size
* 3;
4364 *align
= __alignof__(float);
4365 return sizeof (float);
4368 *align
= __alignof__(gint64
);
4369 return sizeof (gint64
);
4371 *align
= __alignof__(double);
4372 return sizeof (double);
4373 case MONO_TYPE_VALUETYPE
: {
4376 if (t
->data
.klass
->enumtype
)
4377 return mono_type_stack_size_internal (mono_class_enum_basetype (t
->data
.klass
), align
, allow_open
);
4379 size
= mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
4381 *align
= *align
+ stack_slot_align
- 1;
4382 *align
&= ~(stack_slot_align
- 1);
4384 size
+= stack_slot_size
- 1;
4385 size
&= ~(stack_slot_size
- 1);
4390 case MONO_TYPE_GENERICINST
: {
4391 MonoGenericClass
*gclass
= t
->data
.generic_class
;
4392 MonoClass
*container_class
= gclass
->container_class
;
4395 g_assert (!gclass
->context
.class_inst
->is_open
);
4397 if (container_class
->valuetype
) {
4398 if (container_class
->enumtype
)
4399 return mono_type_stack_size_internal (mono_class_enum_basetype (container_class
), align
, allow_open
);
4401 guint32 size
= mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
4403 *align
= *align
+ stack_slot_align
- 1;
4404 *align
&= ~(stack_slot_align
- 1);
4406 size
+= stack_slot_size
- 1;
4407 size
&= ~(stack_slot_size
- 1);
4412 *align
= stack_slot_align
;
4413 return stack_slot_size
;
4417 g_error ("type 0x%02x unknown", t
->type
);
4423 mono_type_generic_inst_is_valuetype (MonoType
*type
)
4425 g_assert (type
->type
== MONO_TYPE_GENERICINST
);
4426 return type
->data
.generic_class
->container_class
->valuetype
;
4430 mono_metadata_generic_class_is_valuetype (MonoGenericClass
*gclass
)
4432 return gclass
->container_class
->valuetype
;
4436 _mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
, gboolean signature_only
)
4438 MonoGenericInst
*i1
= g1
->context
.class_inst
;
4439 MonoGenericInst
*i2
= g2
->context
.class_inst
;
4441 if (g1
->is_dynamic
!= g2
->is_dynamic
)
4443 if (!mono_metadata_class_equal (g1
->container_class
, g2
->container_class
, signature_only
))
4445 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
4447 return g1
->is_tb_open
== g2
->is_tb_open
;
4451 _mono_metadata_generic_class_container_equal (const MonoGenericClass
*g1
, MonoClass
*c2
, gboolean signature_only
)
4453 MonoGenericInst
*i1
= g1
->context
.class_inst
;
4454 MonoGenericInst
*i2
= c2
->generic_container
->context
.class_inst
;
4456 if (!mono_metadata_class_equal (g1
->container_class
, c2
, signature_only
))
4458 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
4460 return !g1
->is_tb_open
;
4464 mono_metadata_generic_context_hash (const MonoGenericContext
*context
)
4466 /* FIXME: check if this seed is good enough */
4467 guint hash
= 0xc01dfee7;
4468 if (context
->class_inst
)
4469 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->class_inst
);
4470 if (context
->method_inst
)
4471 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->method_inst
);
4476 mono_metadata_generic_context_equal (const MonoGenericContext
*g1
, const MonoGenericContext
*g2
)
4478 return g1
->class_inst
== g2
->class_inst
&& g1
->method_inst
== g2
->method_inst
;
4482 * mono_metadata_str_hash:
4484 * This should be used instead of g_str_hash for computing hash codes visible
4485 * outside this module, since g_str_hash () is not guaranteed to be stable
4486 * (its not the same in eglib for example).
4489 mono_metadata_str_hash (gconstpointer v1
)
4491 /* Same as g_str_hash () in glib */
4492 char *p
= (char *) v1
;
4497 hash
= (hash
<< 5) - hash
+ *p
;
4504 * mono_metadata_type_hash:
4507 * Computes an hash value for @t1 to be used in GHashTable.
4508 * The returned hash is guaranteed to be the same across executions.
4511 mono_metadata_type_hash (MonoType
*t1
)
4513 guint hash
= t1
->type
;
4515 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
4517 case MONO_TYPE_VALUETYPE
:
4518 case MONO_TYPE_CLASS
:
4519 case MONO_TYPE_SZARRAY
:
4520 /* check if the distribution is good enough */
4521 return ((hash
<< 5) - hash
) ^ mono_metadata_str_hash (t1
->data
.klass
->name
);
4523 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (t1
->data
.type
);
4524 case MONO_TYPE_ARRAY
:
4525 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (&t1
->data
.array
->eklass
->byval_arg
);
4526 case MONO_TYPE_GENERICINST
:
4527 return ((hash
<< 5) - hash
) ^ mono_generic_class_hash (t1
->data
.generic_class
);
4533 mono_metadata_generic_param_equal (MonoGenericParam
*p1
, MonoGenericParam
*p2
, gboolean signature_only
)
4537 if (mono_generic_param_num (p1
) != mono_generic_param_num (p2
))
4541 * We have to compare the image as well because if we didn't,
4542 * the generic_inst_cache lookup wouldn't care about the image
4543 * of generic params, so what could happen is that a generic
4544 * inst with params from image A is put into the cache, then
4545 * image B gets that generic inst from the cache, image A is
4546 * unloaded, so the inst is deleted, but image B still retains
4549 * The AOT runtime doesn't set the image when it's decoding
4550 * types, so we only compare it when the owner is NULL.
4552 if (mono_generic_param_owner (p1
) == mono_generic_param_owner (p2
) &&
4553 (mono_generic_param_owner (p1
) || p1
->image
== p2
->image
))
4557 * If `signature_only' is true, we're comparing two (method) signatures.
4558 * In this case, the owner of two type parameters doesn't need to match.
4561 return signature_only
;
4565 mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
)
4569 if (c1
->generic_class
&& c2
->generic_class
)
4570 return _mono_metadata_generic_class_equal (c1
->generic_class
, c2
->generic_class
, signature_only
);
4571 if (c1
->generic_class
&& c2
->generic_container
)
4572 return _mono_metadata_generic_class_container_equal (c1
->generic_class
, c2
, signature_only
);
4573 if (c1
->generic_container
&& c2
->generic_class
)
4574 return _mono_metadata_generic_class_container_equal (c2
->generic_class
, c1
, signature_only
);
4575 if ((c1
->byval_arg
.type
== MONO_TYPE_VAR
) && (c2
->byval_arg
.type
== MONO_TYPE_VAR
))
4576 return mono_metadata_generic_param_equal (
4577 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
4578 if ((c1
->byval_arg
.type
== MONO_TYPE_MVAR
) && (c2
->byval_arg
.type
== MONO_TYPE_MVAR
))
4579 return mono_metadata_generic_param_equal (
4580 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
4581 if (signature_only
&&
4582 (c1
->byval_arg
.type
== MONO_TYPE_SZARRAY
) && (c2
->byval_arg
.type
== MONO_TYPE_SZARRAY
))
4583 return mono_metadata_class_equal (c1
->byval_arg
.data
.klass
, c2
->byval_arg
.data
.klass
, signature_only
);
4588 mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
)
4590 gpointer iter1
= 0, iter2
= 0;
4594 if (s1
->call_convention
!= s2
->call_convention
)
4596 if (s1
->sentinelpos
!= s2
->sentinelpos
)
4598 if (s1
->hasthis
!= s2
->hasthis
)
4600 if (s1
->explicit_this
!= s2
->explicit_this
)
4602 if (! do_mono_metadata_type_equal (s1
->ret
, s2
->ret
, signature_only
))
4604 if (s1
->param_count
!= s2
->param_count
)
4608 MonoType
*t1
= mono_signature_get_params (s1
, &iter1
);
4609 MonoType
*t2
= mono_signature_get_params (s2
, &iter2
);
4611 if (t1
== NULL
|| t2
== NULL
)
4613 if (! do_mono_metadata_type_equal (t1
, t2
, signature_only
))
4619 * mono_metadata_type_equal:
4623 * Determine if @t1 and @t2 represent the same type.
4624 * Returns: #TRUE if @t1 and @t2 are equal.
4627 do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
4629 if (t1
->type
!= t2
->type
|| t1
->byref
!= t2
->byref
)
4633 case MONO_TYPE_VOID
:
4634 case MONO_TYPE_BOOLEAN
:
4635 case MONO_TYPE_CHAR
:
4646 case MONO_TYPE_STRING
:
4649 case MONO_TYPE_OBJECT
:
4650 case MONO_TYPE_TYPEDBYREF
:
4652 case MONO_TYPE_VALUETYPE
:
4653 case MONO_TYPE_CLASS
:
4654 case MONO_TYPE_SZARRAY
:
4655 return mono_metadata_class_equal (t1
->data
.klass
, t2
->data
.klass
, signature_only
);
4657 return do_mono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
, signature_only
);
4658 case MONO_TYPE_ARRAY
:
4659 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
4661 return mono_metadata_class_equal (t1
->data
.array
->eklass
, t2
->data
.array
->eklass
, signature_only
);
4662 case MONO_TYPE_GENERICINST
:
4663 return _mono_metadata_generic_class_equal (
4664 t1
->data
.generic_class
, t2
->data
.generic_class
, signature_only
);
4666 return mono_metadata_generic_param_equal (
4667 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
4668 case MONO_TYPE_MVAR
:
4669 return mono_metadata_generic_param_equal (
4670 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
4671 case MONO_TYPE_FNPTR
:
4672 return mono_metadata_fnptr_equal (t1
->data
.method
, t2
->data
.method
, signature_only
);
4674 g_error ("implement type compare for %0x!", t1
->type
);
4682 mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
4684 return do_mono_metadata_type_equal (t1
, t2
, FALSE
);
4688 * mono_metadata_type_equal_full:
4691 * @signature_only: if signature only comparison should be made
4693 * Determine if @t1 and @t2 are signature compatible if @signature_only is #TRUE, otherwise
4694 * behaves the same way as mono_metadata_type_equal.
4695 * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
4696 * Returns: #TRUE if @t1 and @t2 are equal taking @signature_only into account.
4699 mono_metadata_type_equal_full (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
4701 return do_mono_metadata_type_equal (t1
, t2
, signature_only
);
4705 * mono_metadata_signature_equal:
4706 * @sig1: a signature
4707 * @sig2: another signature
4709 * Determine if @sig1 and @sig2 represent the same signature, with the
4710 * same number of arguments and the same types.
4711 * Returns: #TRUE if @sig1 and @sig2 are equal.
4714 mono_metadata_signature_equal (MonoMethodSignature
*sig1
, MonoMethodSignature
*sig2
)
4718 if (sig1
->hasthis
!= sig2
->hasthis
|| sig1
->param_count
!= sig2
->param_count
)
4721 if (sig1
->generic_param_count
!= sig2
->generic_param_count
)
4725 * We're just comparing the signatures of two methods here:
4727 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
4728 * U and V are equal here.
4730 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
4733 for (i
= 0; i
< sig1
->param_count
; i
++) {
4734 MonoType
*p1
= sig1
->params
[i
];
4735 MonoType
*p2
= sig2
->params
[i
];
4737 /* if (p1->attrs != p2->attrs)
4740 if (!do_mono_metadata_type_equal (p1
, p2
, TRUE
))
4744 if (!do_mono_metadata_type_equal (sig1
->ret
, sig2
->ret
, TRUE
))
4750 * mono_metadata_type_dup:
4751 * @image: image to alloc memory from
4752 * @original: type to duplicate
4754 * Returns: copy of type allocated from the image's mempool (or from the heap, if @image is null).
4757 mono_metadata_type_dup (MonoImage
*image
, const MonoType
*o
)
4760 int sizeof_o
= MONO_SIZEOF_TYPE
;
4762 sizeof_o
+= o
->num_mods
* sizeof (MonoCustomMod
);
4764 r
= image
? mono_image_alloc0 (image
, sizeof_o
) : g_malloc (sizeof_o
);
4766 memcpy (r
, o
, sizeof_o
);
4768 if (o
->type
== MONO_TYPE_PTR
) {
4769 r
->data
.type
= mono_metadata_type_dup (image
, o
->data
.type
);
4770 } else if (o
->type
== MONO_TYPE_ARRAY
) {
4771 r
->data
.array
= mono_dup_array_type (image
, o
->data
.array
);
4772 } else if (o
->type
== MONO_TYPE_FNPTR
) {
4773 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
4774 r
->data
.method
= mono_metadata_signature_deep_dup (image
, o
->data
.method
);
4780 mono_signature_hash (MonoMethodSignature
*sig
)
4782 guint i
, res
= sig
->ret
->type
;
4784 for (i
= 0; i
< sig
->param_count
; i
++)
4785 res
= (res
<< 5) - res
+ mono_type_hash (sig
->params
[i
]);
4791 * mono_metadata_encode_value:
4792 * @value: value to encode
4793 * @buf: buffer where to write the compressed representation
4794 * @endbuf: pointer updated to point at the end of the encoded output
4796 * Encodes the value @value in the compressed representation used
4797 * in metadata and stores the result in @buf. @buf needs to be big
4798 * enough to hold the data (4 bytes).
4801 mono_metadata_encode_value (guint32 value
, char *buf
, char **endbuf
)
4807 else if (value
< 0x4000) {
4808 p
[0] = 0x80 | (value
>> 8);
4809 p
[1] = value
& 0xff;
4812 p
[0] = (value
>> 24) | 0xc0;
4813 p
[1] = (value
>> 16) & 0xff;
4814 p
[2] = (value
>> 8) & 0xff;
4815 p
[3] = value
& 0xff;
4823 * mono_metadata_field_info:
4824 * @meta: the Image the field is defined in
4825 * @index: the index in the field table representing the field
4826 * @offset: a pointer to an integer where to store the offset that
4827 * may have been specified for the field in a FieldLayout table
4828 * @rva: a pointer to the RVA of the field data in the image that
4829 * may have been defined in a FieldRVA table
4830 * @marshal_spec: a pointer to the marshal spec that may have been
4831 * defined for the field in a FieldMarshal table.
4833 * Gather info for field @index that may have been defined in the FieldLayout,
4834 * FieldRVA and FieldMarshal tables.
4835 * Either of offset, rva and marshal_spec can be NULL if you're not interested
4839 mono_metadata_field_info (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
4840 MonoMarshalSpec
**marshal_spec
)
4842 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, FALSE
);
4846 mono_metadata_field_info_with_mempool (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
4847 MonoMarshalSpec
**marshal_spec
)
4849 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, TRUE
);
4853 mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
4854 MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
)
4856 MonoTableInfo
*tdef
;
4859 loc
.idx
= index
+ 1;
4860 if (meta
->uncompressed_metadata
)
4861 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
4864 tdef
= &meta
->tables
[MONO_TABLE_FIELDLAYOUT
];
4866 loc
.col_idx
= MONO_FIELD_LAYOUT_FIELD
;
4869 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4870 *offset
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_LAYOUT_OFFSET
);
4872 *offset
= (guint32
)-1;
4876 tdef
= &meta
->tables
[MONO_TABLE_FIELDRVA
];
4878 loc
.col_idx
= MONO_FIELD_RVA_FIELD
;
4881 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4883 * LAMESPEC: There is no signature, no nothing, just the raw data.
4885 *rva
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_RVA_RVA
);
4893 if ((p
= mono_metadata_get_marshal_info (meta
, index
, TRUE
))) {
4894 *marshal_spec
= mono_metadata_parse_marshal_spec_full (alloc_from_image
? meta
: NULL
, p
);
4901 * mono_metadata_get_constant_index:
4902 * @meta: the Image the field is defined in
4903 * @index: the token that may have a row defined in the constants table
4904 * @hint: possible position for the row
4906 * @token must be a FieldDef, ParamDef or PropertyDef token.
4908 * Returns: the index into the Constants table or 0 if not found.
4911 mono_metadata_get_constant_index (MonoImage
*meta
, guint32 token
, guint32 hint
)
4913 MonoTableInfo
*tdef
;
4915 guint32 index
= mono_metadata_token_index (token
);
4917 tdef
= &meta
->tables
[MONO_TABLE_CONSTANT
];
4918 index
<<= MONO_HASCONSTANT_BITS
;
4919 switch (mono_metadata_token_table (token
)) {
4920 case MONO_TABLE_FIELD
:
4921 index
|= MONO_HASCONSTANT_FIEDDEF
;
4923 case MONO_TABLE_PARAM
:
4924 index
|= MONO_HASCONSTANT_PARAM
;
4926 case MONO_TABLE_PROPERTY
:
4927 index
|= MONO_HASCONSTANT_PROPERTY
;
4930 g_warning ("Not a valid token for the constant table: 0x%08x", token
);
4934 loc
.col_idx
= MONO_CONSTANT_PARENT
;
4937 /* FIXME: Index translation */
4939 if ((hint
> 0) && (hint
< tdef
->rows
) && (mono_metadata_decode_row_col (tdef
, hint
- 1, MONO_CONSTANT_PARENT
) == index
))
4942 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4943 return loc
.result
+ 1;
4949 * mono_metadata_events_from_typedef:
4950 * @meta: metadata context
4951 * @index: 0-based index (in the TypeDef table) describing a type
4953 * Returns: the 0-based index in the Event table for the events in the
4954 * type. The last event that belongs to the type (plus 1) is stored
4955 * in the @end_idx pointer.
4958 mono_metadata_events_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
4962 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_EVENTMAP
];
4970 loc
.col_idx
= MONO_EVENT_MAP_PARENT
;
4971 loc
.idx
= index
+ 1;
4973 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4976 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_EVENT_MAP_EVENTLIST
);
4977 if (loc
.result
+ 1 < tdef
->rows
) {
4978 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_EVENT_MAP_EVENTLIST
) - 1;
4980 end
= meta
->tables
[MONO_TABLE_EVENT
].rows
;
4988 * mono_metadata_methods_from_event:
4989 * @meta: metadata context
4990 * @index: 0-based index (in the Event table) describing a event
4992 * Returns: the 0-based index in the MethodDef table for the methods in the
4993 * event. The last method that belongs to the event (plus 1) is stored
4994 * in the @end_idx pointer.
4997 mono_metadata_methods_from_event (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5001 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
5002 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
5008 if (meta
->uncompressed_metadata
)
5009 index
= search_ptr_table (meta
, MONO_TABLE_EVENT_POINTER
, index
+ 1) - 1;
5012 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
5013 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
; /* Method association coded index */
5015 if (!bsearch (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
5020 * We may end up in the middle of the rows...
5023 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
5029 while (end
< msemt
->rows
) {
5030 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
5031 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
5040 * mono_metadata_properties_from_typedef:
5041 * @meta: metadata context
5042 * @index: 0-based index (in the TypeDef table) describing a type
5044 * Returns: the 0-based index in the Property table for the properties in the
5045 * type. The last property that belongs to the type (plus 1) is stored
5046 * in the @end_idx pointer.
5049 mono_metadata_properties_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5053 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_PROPERTYMAP
];
5061 loc
.col_idx
= MONO_PROPERTY_MAP_PARENT
;
5062 loc
.idx
= index
+ 1;
5064 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5067 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_PROPERTY_MAP_PROPERTY_LIST
);
5068 if (loc
.result
+ 1 < tdef
->rows
) {
5069 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_PROPERTY_MAP_PROPERTY_LIST
) - 1;
5071 end
= meta
->tables
[MONO_TABLE_PROPERTY
].rows
;
5079 * mono_metadata_methods_from_property:
5080 * @meta: metadata context
5081 * @index: 0-based index (in the PropertyDef table) describing a property
5083 * Returns: the 0-based index in the MethodDef table for the methods in the
5084 * property. The last method that belongs to the property (plus 1) is stored
5085 * in the @end_idx pointer.
5088 mono_metadata_methods_from_property (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5092 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
5093 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
5099 if (meta
->uncompressed_metadata
)
5100 index
= search_ptr_table (meta
, MONO_TABLE_PROPERTY_POINTER
, index
+ 1) - 1;
5103 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
5104 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
; /* Method association coded index */
5106 if (!bsearch (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
5111 * We may end up in the middle of the rows...
5114 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
5120 while (end
< msemt
->rows
) {
5121 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
5122 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
5131 mono_metadata_implmap_from_method (MonoImage
*meta
, guint32 method_idx
)
5134 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_IMPLMAP
];
5139 /* No index translation seems to be needed */
5142 loc
.col_idx
= MONO_IMPLMAP_MEMBER
;
5143 loc
.idx
= ((method_idx
+ 1) << MONO_MEMBERFORWD_BITS
) | MONO_MEMBERFORWD_METHODDEF
;
5145 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5148 return loc
.result
+ 1;
5152 * @image: context where the image is created
5153 * @type_spec: typespec token
5155 * Creates a MonoType representing the TypeSpec indexed by the @type_spec
5159 mono_type_create_from_typespec (MonoImage
*image
, guint32 type_spec
)
5161 guint32 idx
= mono_metadata_token_index (type_spec
);
5163 guint32 cols
[MONO_TYPESPEC_SIZE
];
5166 MonoType
*type
, *type2
;
5167 MonoType stack_type
;
5169 mono_loader_lock ();
5171 type
= g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
5173 mono_loader_unlock ();
5177 t
= &image
->tables
[MONO_TABLE_TYPESPEC
];
5179 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPESPEC_SIZE
);
5180 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_TYPESPEC_SIGNATURE
]);
5182 if (!mono_verifier_verify_typespec_signature (image
, cols
[MONO_TYPESPEC_SIGNATURE
], type_spec
, NULL
)) {
5183 mono_loader_unlock ();
5187 len
= mono_metadata_decode_value (ptr
, &ptr
);
5190 memset (type
, 0, MONO_SIZEOF_TYPE
);
5192 if (*ptr
== MONO_TYPE_BYREF
) {
5197 if (!do_mono_metadata_parse_type (type
, image
, NULL
, ptr
, &ptr
)) {
5198 mono_loader_unlock ();
5202 type2
= g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
5205 mono_loader_unlock ();
5209 type2
= mono_image_alloc (image
, MONO_SIZEOF_TYPE
);
5210 memcpy (type2
, type
, MONO_SIZEOF_TYPE
);
5211 g_hash_table_insert (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
), type2
);
5213 mono_loader_unlock ();
5220 mono_image_strndup (MonoImage
*image
, const char *data
, guint len
)
5224 return g_strndup (data
, len
);
5225 res
= mono_image_alloc (image
, len
+ 1);
5226 memcpy (res
, data
, len
);
5232 mono_metadata_parse_marshal_spec (MonoImage
*image
, const char *ptr
)
5234 return mono_metadata_parse_marshal_spec_full (NULL
, ptr
);
5238 mono_metadata_parse_marshal_spec_full (MonoImage
*image
, const char *ptr
)
5240 MonoMarshalSpec
*res
;
5242 const char *start
= ptr
;
5244 /* fixme: this is incomplete, but I cant find more infos in the specs */
5247 res
= mono_image_alloc0 (image
, sizeof (MonoMarshalSpec
));
5249 res
= g_new0 (MonoMarshalSpec
, 1);
5251 len
= mono_metadata_decode_value (ptr
, &ptr
);
5252 res
->native
= *ptr
++;
5254 if (res
->native
== MONO_NATIVE_LPARRAY
) {
5255 res
->data
.array_data
.param_num
= -1;
5256 res
->data
.array_data
.num_elem
= -1;
5257 res
->data
.array_data
.elem_mult
= -1;
5259 if (ptr
- start
<= len
)
5260 res
->data
.array_data
.elem_type
= *ptr
++;
5261 if (ptr
- start
<= len
)
5262 res
->data
.array_data
.param_num
= mono_metadata_decode_value (ptr
, &ptr
);
5263 if (ptr
- start
<= len
)
5264 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5265 if (ptr
- start
<= len
) {
5267 * LAMESPEC: Older spec versions say this parameter comes before
5268 * num_elem. Never spec versions don't talk about elem_mult at
5269 * all, but csc still emits it, and it is used to distinguish
5270 * between param_num being 0, and param_num being omitted.
5271 * So if (param_num == 0) && (num_elem > 0), then
5272 * elem_mult == 0 -> the array size is num_elem
5273 * elem_mult == 1 -> the array size is @param_num + num_elem
5275 res
->data
.array_data
.elem_mult
= mono_metadata_decode_value (ptr
, &ptr
);
5279 if (res
->native
== MONO_NATIVE_BYVALTSTR
) {
5280 if (ptr
- start
<= len
)
5281 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5284 if (res
->native
== MONO_NATIVE_BYVALARRAY
) {
5285 if (ptr
- start
<= len
)
5286 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5289 if (res
->native
== MONO_NATIVE_CUSTOM
) {
5290 /* skip unused type guid */
5291 len
= mono_metadata_decode_value (ptr
, &ptr
);
5293 /* skip unused native type name */
5294 len
= mono_metadata_decode_value (ptr
, &ptr
);
5296 /* read custom marshaler type name */
5297 len
= mono_metadata_decode_value (ptr
, &ptr
);
5298 res
->data
.custom_data
.custom_name
= mono_image_strndup (image
, ptr
, len
);
5300 /* read cookie string */
5301 len
= mono_metadata_decode_value (ptr
, &ptr
);
5302 res
->data
.custom_data
.cookie
= mono_image_strndup (image
, ptr
, len
);
5305 if (res
->native
== MONO_NATIVE_SAFEARRAY
) {
5306 res
->data
.safearray_data
.elem_type
= 0;
5307 res
->data
.safearray_data
.num_elem
= 0;
5308 if (ptr
- start
<= len
)
5309 res
->data
.safearray_data
.elem_type
= *ptr
++;
5310 if (ptr
- start
<= len
)
5311 res
->data
.safearray_data
.num_elem
= *ptr
++;
5317 mono_metadata_free_marshal_spec (MonoMarshalSpec
*spec
)
5319 if (spec
->native
== MONO_NATIVE_CUSTOM
) {
5320 g_free (spec
->data
.custom_data
.custom_name
);
5321 g_free (spec
->data
.custom_data
.cookie
);
5327 * mono_type_to_unmanaged:
5329 * Returns: A MonoMarshalNative enumeration value (MONO_NATIVE_) value
5330 * describing the underlying native reprensetation of the type.
5332 * In addition the value pointed by
5333 * "conv" will contain the kind of marshalling required for this
5334 * particular type one of the MONO_MARSHAL_CONV_ enumeration values.
5337 mono_type_to_unmanaged (MonoType
*type
, MonoMarshalSpec
*mspec
, gboolean as_field
,
5338 gboolean unicode
, MonoMarshalConv
*conv
)
5340 MonoMarshalConv dummy_conv
;
5346 *conv
= MONO_MARSHAL_CONV_NONE
;
5349 return MONO_NATIVE_UINT
;
5353 case MONO_TYPE_BOOLEAN
:
5355 switch (mspec
->native
) {
5356 case MONO_NATIVE_VARIANTBOOL
:
5357 *conv
= MONO_MARSHAL_CONV_BOOL_VARIANTBOOL
;
5358 return MONO_NATIVE_VARIANTBOOL
;
5359 case MONO_NATIVE_BOOLEAN
:
5360 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
5361 return MONO_NATIVE_BOOLEAN
;
5362 case MONO_NATIVE_I1
:
5363 case MONO_NATIVE_U1
:
5364 return mspec
->native
;
5366 g_error ("cant marshal bool to native type %02x", mspec
->native
);
5369 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
5370 return MONO_NATIVE_BOOLEAN
;
5371 case MONO_TYPE_CHAR
: return MONO_NATIVE_U2
;
5372 case MONO_TYPE_I1
: return MONO_NATIVE_I1
;
5373 case MONO_TYPE_U1
: return MONO_NATIVE_U1
;
5374 case MONO_TYPE_I2
: return MONO_NATIVE_I2
;
5375 case MONO_TYPE_U2
: return MONO_NATIVE_U2
;
5376 case MONO_TYPE_I4
: return MONO_NATIVE_I4
;
5377 case MONO_TYPE_U4
: return MONO_NATIVE_U4
;
5378 case MONO_TYPE_I8
: return MONO_NATIVE_I8
;
5379 case MONO_TYPE_U8
: return MONO_NATIVE_U8
;
5380 case MONO_TYPE_R4
: return MONO_NATIVE_R4
;
5381 case MONO_TYPE_R8
: return MONO_NATIVE_R8
;
5382 case MONO_TYPE_STRING
:
5384 switch (mspec
->native
) {
5385 case MONO_NATIVE_BSTR
:
5386 *conv
= MONO_MARSHAL_CONV_STR_BSTR
;
5387 return MONO_NATIVE_BSTR
;
5388 case MONO_NATIVE_LPSTR
:
5389 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
5390 return MONO_NATIVE_LPSTR
;
5391 case MONO_NATIVE_LPWSTR
:
5392 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
5393 return MONO_NATIVE_LPWSTR
;
5394 case MONO_NATIVE_LPTSTR
:
5395 *conv
= MONO_MARSHAL_CONV_STR_LPTSTR
;
5396 return MONO_NATIVE_LPTSTR
;
5397 case MONO_NATIVE_ANSIBSTR
:
5398 *conv
= MONO_MARSHAL_CONV_STR_ANSIBSTR
;
5399 return MONO_NATIVE_ANSIBSTR
;
5400 case MONO_NATIVE_TBSTR
:
5401 *conv
= MONO_MARSHAL_CONV_STR_TBSTR
;
5402 return MONO_NATIVE_TBSTR
;
5403 case MONO_NATIVE_BYVALTSTR
:
5405 *conv
= MONO_MARSHAL_CONV_STR_BYVALWSTR
;
5407 *conv
= MONO_MARSHAL_CONV_STR_BYVALSTR
;
5408 return MONO_NATIVE_BYVALTSTR
;
5410 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
);
5414 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
5415 return MONO_NATIVE_LPWSTR
;
5418 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
5419 return MONO_NATIVE_LPSTR
;
5421 case MONO_TYPE_PTR
: return MONO_NATIVE_UINT
;
5422 case MONO_TYPE_VALUETYPE
: /*FIXME*/
5423 if (type
->data
.klass
->enumtype
) {
5424 t
= mono_class_enum_basetype (type
->data
.klass
)->type
;
5427 if (type
->data
.klass
== mono_defaults
.handleref_class
){
5428 *conv
= MONO_MARSHAL_CONV_HANDLEREF
;
5429 return MONO_NATIVE_INT
;
5431 return MONO_NATIVE_STRUCT
;
5432 case MONO_TYPE_SZARRAY
:
5433 case MONO_TYPE_ARRAY
:
5435 switch (mspec
->native
) {
5436 case MONO_NATIVE_BYVALARRAY
:
5437 if ((type
->data
.klass
->element_class
== mono_defaults
.char_class
) && !unicode
)
5438 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY
;
5440 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALARRAY
;
5441 return MONO_NATIVE_BYVALARRAY
;
5442 case MONO_NATIVE_SAFEARRAY
:
5443 *conv
= MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
;
5444 return MONO_NATIVE_SAFEARRAY
;
5445 case MONO_NATIVE_LPARRAY
:
5446 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
5447 return MONO_NATIVE_LPARRAY
;
5449 g_error ("cant marshal array as native type %02x", mspec
->native
);
5453 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
5454 return MONO_NATIVE_LPARRAY
;
5455 case MONO_TYPE_I
: return MONO_NATIVE_INT
;
5456 case MONO_TYPE_U
: return MONO_NATIVE_UINT
;
5457 case MONO_TYPE_CLASS
:
5458 case MONO_TYPE_OBJECT
: {
5459 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
5461 switch (mspec
->native
) {
5462 case MONO_NATIVE_STRUCT
:
5463 return MONO_NATIVE_STRUCT
;
5464 case MONO_NATIVE_CUSTOM
:
5465 return MONO_NATIVE_CUSTOM
;
5466 case MONO_NATIVE_INTERFACE
:
5467 *conv
= MONO_MARSHAL_CONV_OBJECT_INTERFACE
;
5468 return MONO_NATIVE_INTERFACE
;
5469 case MONO_NATIVE_IDISPATCH
:
5470 *conv
= MONO_MARSHAL_CONV_OBJECT_IDISPATCH
;
5471 return MONO_NATIVE_IDISPATCH
;
5472 case MONO_NATIVE_IUNKNOWN
:
5473 *conv
= MONO_MARSHAL_CONV_OBJECT_IUNKNOWN
;
5474 return MONO_NATIVE_IUNKNOWN
;
5475 case MONO_NATIVE_FUNC
:
5476 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
5477 type
->data
.klass
== mono_defaults
.delegate_class
||
5478 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
5479 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
5480 return MONO_NATIVE_FUNC
;
5484 g_error ("cant marshal object as native type %02x", mspec
->native
);
5487 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
5488 type
->data
.klass
== mono_defaults
.delegate_class
||
5489 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
5490 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
5491 return MONO_NATIVE_FUNC
;
5493 if (mono_defaults
.safehandle_class
&& type
->data
.klass
== mono_defaults
.safehandle_class
){
5494 *conv
= MONO_MARSHAL_CONV_SAFEHANDLE
;
5495 return MONO_NATIVE_INT
;
5497 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
5498 return MONO_NATIVE_STRUCT
;
5500 case MONO_TYPE_FNPTR
: return MONO_NATIVE_FUNC
;
5501 case MONO_TYPE_GENERICINST
:
5502 type
= &type
->data
.generic_class
->container_class
->byval_arg
;
5505 case MONO_TYPE_TYPEDBYREF
:
5507 g_error ("type 0x%02x not handled in marshal", t
);
5509 return MONO_NATIVE_MAX
;
5513 mono_metadata_get_marshal_info (MonoImage
*meta
, guint32 idx
, gboolean is_field
)
5516 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_FIELDMARSHAL
];
5522 loc
.col_idx
= MONO_FIELD_MARSHAL_PARENT
;
5523 loc
.idx
= ((idx
+ 1) << MONO_HAS_FIELD_MARSHAL_BITS
) | (is_field
? MONO_HAS_FIELD_MARSHAL_FIELDSREF
: MONO_HAS_FIELD_MARSHAL_PARAMDEF
);
5525 /* FIXME: Index translation */
5527 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5530 return mono_metadata_blob_heap (meta
, mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_MARSHAL_NATIVE_TYPE
));
5534 method_from_method_def_or_ref (MonoImage
*m
, guint32 tok
, MonoGenericContext
*context
)
5536 guint32 idx
= tok
>> MONO_METHODDEFORREF_BITS
;
5538 switch (tok
& MONO_METHODDEFORREF_MASK
) {
5539 case MONO_METHODDEFORREF_METHODDEF
:
5540 return mono_get_method_full (m
, MONO_TOKEN_METHOD_DEF
| idx
, NULL
, context
);
5541 case MONO_METHODDEFORREF_METHODREF
:
5542 return mono_get_method_full (m
, MONO_TOKEN_MEMBER_REF
| idx
, NULL
, context
);
5544 g_assert_not_reached ();
5549 * mono_class_get_overrides_full:
5551 * Return the method overrides belonging to class @type_token in @overrides, and
5552 * the number of overrides in @num_overrides.
5554 * Returns: TRUE on success, FALSE on failure.
5557 mono_class_get_overrides_full (MonoImage
*image
, guint32 type_token
, MonoMethod
***overrides
, gint32
*num_overrides
,
5558 MonoGenericContext
*generic_context
)
5561 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_METHODIMPL
];
5564 guint32 cols
[MONO_METHODIMPL_SIZE
];
5565 MonoMethod
**result
;
5576 loc
.col_idx
= MONO_METHODIMPL_CLASS
;
5577 loc
.idx
= mono_metadata_token_index (type_token
);
5579 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5585 * We may end up in the middle of the rows...
5588 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_METHODIMPL_CLASS
))
5593 while (end
< tdef
->rows
) {
5594 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, end
, MONO_METHODIMPL_CLASS
))
5600 result
= g_new (MonoMethod
*, num
* 2);
5601 for (i
= 0; i
< num
; ++i
) {
5604 mono_metadata_decode_row (tdef
, start
+ i
, cols
, MONO_METHODIMPL_SIZE
);
5605 method
= method_from_method_def_or_ref (
5606 image
, cols
[MONO_METHODIMPL_DECLARATION
], generic_context
);
5609 result
[i
* 2] = method
;
5610 method
= method_from_method_def_or_ref (
5611 image
, cols
[MONO_METHODIMPL_BODY
], generic_context
);
5614 result
[i
* 2 + 1] = method
;
5617 *overrides
= result
;
5619 *num_overrides
= num
;
5624 * mono_guid_to_string:
5626 * Converts a 16 byte Microsoft GUID to the standard string representation.
5629 mono_guid_to_string (const guint8
*guid
)
5631 return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
5632 guid
[3], guid
[2], guid
[1], guid
[0],
5636 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
5640 get_constraints (MonoImage
*image
, int owner
, MonoClass
***constraints
, MonoGenericContainer
*container
)
5642 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
5643 guint32 cols
[MONO_GENPARCONSTRAINT_SIZE
];
5644 guint32 i
, token
, found
;
5645 MonoClass
*klass
, **res
;
5646 GSList
*cons
= NULL
, *tmp
;
5647 MonoGenericContext
*context
= &container
->context
;
5649 *constraints
= NULL
;
5651 for (i
= 0; i
< tdef
->rows
; ++i
) {
5652 mono_metadata_decode_row (tdef
, i
, cols
, MONO_GENPARCONSTRAINT_SIZE
);
5653 if (cols
[MONO_GENPARCONSTRAINT_GENERICPAR
] == owner
) {
5654 token
= mono_metadata_token_from_dor (cols
[MONO_GENPARCONSTRAINT_CONSTRAINT
]);
5655 klass
= mono_class_get_full (image
, token
, context
);
5657 g_slist_free (cons
);
5660 cons
= g_slist_append (cons
, klass
);
5663 /* contiguous list finished */
5670 res
= g_new0 (MonoClass
*, found
+ 1);
5671 for (i
= 0, tmp
= cons
; i
< found
; ++i
, tmp
= tmp
->next
) {
5672 res
[i
] = tmp
->data
;
5674 g_slist_free (cons
);
5680 * mono_metadata_get_generic_param_row:
5683 * @token: TypeOrMethodDef token, owner for GenericParam
5684 * @owner: coded token, set on return
5686 * Returns: 1-based row-id in the GenericParam table whose
5687 * owner is @token. 0 if not found.
5690 mono_metadata_get_generic_param_row (MonoImage
*image
, guint32 token
, guint32
*owner
)
5692 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
5699 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPEDEF
)
5700 *owner
= MONO_TYPEORMETHOD_TYPE
;
5701 else if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
5702 *owner
= MONO_TYPEORMETHOD_METHOD
;
5704 g_error ("wrong token %x to get_generic_param_row", token
);
5707 *owner
|= mono_metadata_token_index (token
) << MONO_TYPEORMETHOD_BITS
;
5710 loc
.col_idx
= MONO_GENERICPARAM_OWNER
;
5713 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5716 /* Find the first entry by searching backwards */
5717 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_GENERICPARAM_OWNER
) == loc
.idx
))
5720 return loc
.result
+ 1;
5724 mono_metadata_has_generic_params (MonoImage
*image
, guint32 token
)
5727 return mono_metadata_get_generic_param_row (image
, token
, &owner
);
5731 mono_metadata_load_generic_param_constraints_full (MonoImage
*image
, guint32 token
,
5732 MonoGenericContainer
*container
)
5735 guint32 start_row
, i
, owner
;
5736 if (! (start_row
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
5738 for (i
= 0; i
< container
->type_argc
; i
++) {
5739 if (!get_constraints (image
, start_row
+ i
, &mono_generic_container_get_param_info (container
, i
)->constraints
, container
))
5746 * mono_metadata_load_generic_param_constraints:
5748 * @image: metadata context
5749 * @token: metadata token to load the contraints, can be methodef or typedef.
5750 * @container: generic container to load into.
5752 * Load the generic parameter constraints for the newly created generic type or method
5753 * represented by @token and @container. The @container is the new container which has
5754 * been returned by a call to mono_metadata_load_generic_params() with this @token.
5757 mono_metadata_load_generic_param_constraints (MonoImage
*image
, guint32 token
,
5758 MonoGenericContainer
*container
)
5760 mono_metadata_load_generic_param_constraints_full (image
, token
, container
);
5761 /*FIXME this function can potentially exit with a pending loader error and cause all sort of havok */
5765 * mono_metadata_load_generic_params:
5767 * Load the type parameters from the type or method definition @token.
5769 * Use this method after parsing a type or method definition to figure out whether it's a generic
5770 * type / method. When parsing a method definition, @parent_container points to the generic container
5771 * of the current class, if any.
5773 * Note: This method does not load the constraints: for typedefs, this has to be done after fully
5774 * creating the type.
5776 * Returns: NULL if @token is not a generic type or method definition or the new generic container.
5778 * LOCKING: Acquires the loader lock
5781 MonoGenericContainer
*
5782 mono_metadata_load_generic_params (MonoImage
*image
, guint32 token
, MonoGenericContainer
*parent_container
)
5784 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
5785 guint32 cols
[MONO_GENERICPARAM_SIZE
];
5786 guint32 i
, owner
= 0, n
;
5787 MonoGenericContainer
*container
;
5788 MonoGenericParamFull
*params
;
5789 MonoGenericContext
*context
;
5791 if (!(i
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
5793 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
5796 container
= mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
5797 container
->image
= image
;
5800 params
= g_realloc (params
, sizeof (MonoGenericParamFull
) * n
);
5801 memset (¶ms
[n
- 1], 0, sizeof (MonoGenericParamFull
));
5802 params
[n
- 1].param
.owner
= container
;
5803 params
[n
- 1].param
.num
= cols
[MONO_GENERICPARAM_NUMBER
];
5804 params
[n
- 1].info
.token
= i
| MONO_TOKEN_GENERIC_PARAM
;
5805 params
[n
- 1].info
.flags
= cols
[MONO_GENERICPARAM_FLAGS
];
5806 params
[n
- 1].info
.name
= mono_metadata_string_heap (image
, cols
[MONO_GENERICPARAM_NAME
]);
5807 if (params
[n
- 1].param
.num
!= n
- 1)
5808 g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i
);
5809 if (++i
> tdef
->rows
)
5811 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
5812 } while (cols
[MONO_GENERICPARAM_OWNER
] == owner
);
5814 container
->type_argc
= n
;
5815 container
->type_params
= mono_image_alloc0 (image
, sizeof (MonoGenericParamFull
) * n
);
5816 memcpy (container
->type_params
, params
, sizeof (MonoGenericParamFull
) * n
);
5818 container
->parent
= parent_container
;
5820 if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
5821 container
->is_method
= 1;
5823 g_assert (container
->parent
== NULL
|| container
->is_method
);
5825 context
= &container
->context
;
5826 if (container
->is_method
) {
5827 context
->class_inst
= container
->parent
? container
->parent
->context
.class_inst
: NULL
;
5828 context
->method_inst
= mono_get_shared_generic_inst (container
);
5830 context
->class_inst
= mono_get_shared_generic_inst (container
);
5837 mono_get_shared_generic_inst (MonoGenericContainer
*container
)
5839 MonoType
**type_argv
;
5841 MonoGenericInst
*nginst
;
5844 type_argv
= g_new0 (MonoType
*, container
->type_argc
);
5845 helper
= g_new0 (MonoType
, container
->type_argc
);
5847 for (i
= 0; i
< container
->type_argc
; i
++) {
5848 MonoType
*t
= &helper
[i
];
5850 t
->type
= container
->is_method
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
5851 t
->data
.generic_param
= mono_generic_container_get_param (container
, i
);
5856 nginst
= mono_metadata_get_generic_inst (container
->type_argc
, type_argv
);
5865 * mono_type_is_byref:
5866 * @type: the MonoType operated on
5868 * Returns: #TRUE if @type represents a type passed by reference,
5872 mono_type_is_byref (MonoType
*type
)
5878 * mono_type_get_type:
5879 * @type: the MonoType operated on
5881 * Returns: the IL type value for @type. This is one of the MonoTypeEnum
5882 * enum members like MONO_TYPE_I4 or MONO_TYPE_STRING.
5885 mono_type_get_type (MonoType
*type
)
5891 * mono_type_get_signature:
5892 * @type: the MonoType operated on
5894 * It is only valid to call this function if @type is a MONO_TYPE_FNPTR.
5896 * Returns: the MonoMethodSignature pointer that describes the signature
5897 * of the function pointer @type represents.
5899 MonoMethodSignature
*
5900 mono_type_get_signature (MonoType
*type
)
5902 g_assert (type
->type
== MONO_TYPE_FNPTR
);
5903 return type
->data
.method
;
5907 * mono_type_get_class:
5908 * @type: the MonoType operated on
5910 * It is only valid to call this function if @type is a MONO_TYPE_CLASS or a
5911 * MONO_TYPE_VALUETYPE. For more general functionality, use mono_class_from_mono_type (),
5914 * Returns: the MonoClass pointer that describes the class that @type represents.
5917 mono_type_get_class (MonoType
*type
)
5919 /* FIXME: review the runtime users before adding the assert here */
5920 return type
->data
.klass
;
5924 * mono_type_get_array_type:
5925 * @type: the MonoType operated on
5927 * It is only valid to call this function if @type is a MONO_TYPE_ARRAY.
5929 * Returns: a MonoArrayType struct describing the array type that @type
5930 * represents. The info includes details such as rank, array element type
5931 * and the sizes and bounds of multidimensional arrays.
5934 mono_type_get_array_type (MonoType
*type
)
5936 return type
->data
.array
;
5940 * mono_type_get_ptr_type:
5941 * @type: the MonoType operated on
5943 * It is only valid to call this function if @type is a MONO_TYPE_PTR.
5946 * Returns: the MonoType pointer that describes the type that @type
5947 * represents a pointer to.
5950 mono_type_get_ptr_type (MonoType
*type
)
5952 g_assert (type
->type
== MONO_TYPE_PTR
);
5953 return type
->data
.type
;
5957 mono_type_get_modifiers (MonoType
*type
, gboolean
*is_required
, gpointer
*iter
)
5959 /* FIXME: implement */
5964 * mono_type_is_struct:
5965 * @type: the MonoType operated on
5967 * Returns: #TRUE is @type is a struct, that is a ValueType but not en enum
5968 * or a basic type like System.Int32. #FALSE otherwise.
5971 mono_type_is_struct (MonoType
*type
)
5973 return (!type
->byref
&& ((type
->type
== MONO_TYPE_VALUETYPE
&&
5974 !type
->data
.klass
->enumtype
) || (type
->type
== MONO_TYPE_TYPEDBYREF
) ||
5975 ((type
->type
== MONO_TYPE_GENERICINST
) &&
5976 mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
) &&
5977 !type
->data
.generic_class
->container_class
->enumtype
)));
5981 * mono_type_is_void:
5982 * @type: the MonoType operated on
5984 * Returns: #TRUE is @type is System.Void. #FALSE otherwise.
5987 mono_type_is_void (MonoType
*type
)
5989 return (type
&& (type
->type
== MONO_TYPE_VOID
) && !type
->byref
);
5993 * mono_type_is_pointer:
5994 * @type: the MonoType operated on
5996 * Returns: #TRUE is @type is a managed or unmanaged pointer type. #FALSE otherwise.
5999 mono_type_is_pointer (MonoType
*type
)
6001 return (type
&& ((type
->byref
|| (type
->type
== MONO_TYPE_I
) || type
->type
== MONO_TYPE_STRING
)
6002 || (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
6003 (type
->type
== MONO_TYPE_U
) || (type
->type
== MONO_TYPE_OBJECT
) ||
6004 (type
->type
== MONO_TYPE_ARRAY
) || (type
->type
== MONO_TYPE_PTR
) ||
6005 (type
->type
== MONO_TYPE_FNPTR
)));
6009 * mono_type_is_reference:
6010 * @type: the MonoType operated on
6012 * Returns: #TRUE is @type represents an object reference . #FALSE otherwise.
6015 mono_type_is_reference (MonoType
*type
)
6017 return (type
&& (((type
->type
== MONO_TYPE_STRING
) ||
6018 (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
6019 (type
->type
== MONO_TYPE_OBJECT
) || (type
->type
== MONO_TYPE_ARRAY
)) ||
6020 ((type
->type
== MONO_TYPE_GENERICINST
) &&
6021 !mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
))));
6025 * mono_signature_get_return_type:
6026 * @sig: the method signature inspected
6028 * Returns: the return type of the method signature @sig
6031 mono_signature_get_return_type (MonoMethodSignature
*sig
)
6037 * mono_signature_get_params:
6038 * @sig: the method signature inspected
6039 * #iter: pointer to an iterator
6041 * Iterates over the parameters for the method signature @sig.
6042 * A void* pointer must be initualized to #NULL to start the iteration
6043 * and it's address is passed to this function repeteadly until it returns
6046 * Returns: the next parameter type of the method signature @sig,
6047 * #NULL when finished.
6050 mono_signature_get_params (MonoMethodSignature
*sig
, gpointer
*iter
)
6056 /* start from the first */
6057 if (sig
->param_count
) {
6058 *iter
= &sig
->params
[0];
6059 return sig
->params
[0];
6067 if (type
< &sig
->params
[sig
->param_count
]) {
6075 * mono_signature_get_param_count:
6076 * @sig: the method signature inspected
6078 * Returns: the number of parameters in the method signature @sig.
6081 mono_signature_get_param_count (MonoMethodSignature
*sig
)
6083 return sig
->param_count
;
6087 * mono_signature_get_call_conv:
6088 * @sig: the method signature inspected
6090 * Returns: the call convention of the method signature @sig.
6093 mono_signature_get_call_conv (MonoMethodSignature
*sig
)
6095 return sig
->call_convention
;
6099 * mono_signature_vararg_start:
6100 * @sig: the method signature inspected
6102 * Returns: the number of the first vararg parameter in the
6103 * method signature @sig. -1 if this is not a vararg signature.
6106 mono_signature_vararg_start (MonoMethodSignature
*sig
)
6108 return sig
->sentinelpos
;
6112 * mono_signature_is_instance:
6113 * @sig: the method signature inspected
6115 * Returns: #TRUE if this the method signature @sig has an implicit
6116 * first instance argument. #FALSE otherwise.
6119 mono_signature_is_instance (MonoMethodSignature
*sig
)
6121 return sig
->hasthis
;
6125 * mono_signature_explicit_this:
6126 * @sig: the method signature inspected
6128 * Returns: #TRUE if this the method signature @sig has an explicit
6129 * instance argument. #FALSE otherwise.
6132 mono_signature_explicit_this (MonoMethodSignature
*sig
)
6134 return sig
->explicit_this
;
6137 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
6139 mono_aligned_addr_hash (gconstpointer ptr
)
6141 return GPOINTER_TO_UINT (ptr
) >> 3;
6145 * If @field belongs to an inflated generic class, return the corresponding field of the
6146 * generic type definition class.
6149 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField
*field
)
6154 if (!field
->parent
->generic_class
)
6157 gtd
= field
->parent
->generic_class
->container_class
;
6158 offset
= field
- field
->parent
->fields
;
6159 return gtd
->fields
+ offset
;
6163 * If @event belongs to an inflated generic class, return the corresponding event of the
6164 * generic type definition class.
6167 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent
*event
)
6172 if (!event
->parent
->generic_class
)
6175 gtd
= event
->parent
->generic_class
->container_class
;
6176 offset
= event
- event
->parent
->ext
->events
;
6177 return gtd
->ext
->events
+ offset
;
6181 * If @property belongs to an inflated generic class, return the corresponding property of the
6182 * generic type definition class.
6185 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty
*property
)
6190 if (!property
->parent
->generic_class
)
6193 gtd
= property
->parent
->generic_class
->container_class
;
6194 offset
= property
- property
->parent
->ext
->properties
;
6195 return gtd
->ext
->properties
+ offset
;