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
, gboolean transient
,
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_internal:
1249 * @m: a metadata context.
1250 * @transient: whenever to allocate data from the heap
1251 * @ptr: a pointer to an encoded array description.
1252 * @rptr: pointer updated to match the end of the decoded stream
1254 * Decodes the compressed array description found in the metadata @m at @ptr.
1256 * Returns: a #MonoArrayType structure describing the array type
1257 * and dimensions. Memory is allocated from the heap or from the image mempool, depending
1258 * on the value of @transient.
1260 * LOCKING: Acquires the loader lock
1262 static MonoArrayType
*
1263 mono_metadata_parse_array_internal (MonoImage
*m
, MonoGenericContainer
*container
,
1264 gboolean transient
, const char *ptr
, const char **rptr
)
1267 MonoArrayType
*array
;
1270 array
= transient
? g_malloc0 (sizeof (MonoArrayType
)) : mono_image_alloc0 (m
, sizeof (MonoArrayType
));
1271 etype
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
1274 array
->eklass
= mono_class_from_mono_type (etype
);
1275 array
->rank
= mono_metadata_decode_value (ptr
, &ptr
);
1277 array
->numsizes
= mono_metadata_decode_value (ptr
, &ptr
);
1278 if (array
->numsizes
)
1279 array
->sizes
= transient
? g_malloc0 (sizeof (int) * array
->numsizes
) : mono_image_alloc0 (m
, sizeof (int) * array
->numsizes
);
1280 for (i
= 0; i
< array
->numsizes
; ++i
)
1281 array
->sizes
[i
] = mono_metadata_decode_value (ptr
, &ptr
);
1283 array
->numlobounds
= mono_metadata_decode_value (ptr
, &ptr
);
1284 if (array
->numlobounds
)
1285 array
->lobounds
= transient
? g_malloc0 (sizeof (int) * array
->numlobounds
) : mono_image_alloc0 (m
, sizeof (int) * array
->numlobounds
);
1286 for (i
= 0; i
< array
->numlobounds
; ++i
)
1287 array
->lobounds
[i
] = mono_metadata_decode_signed_value (ptr
, &ptr
);
1295 mono_metadata_parse_array_full (MonoImage
*m
, MonoGenericContainer
*container
,
1296 const char *ptr
, const char **rptr
)
1298 return mono_metadata_parse_array_internal (m
, container
, FALSE
, ptr
, rptr
);
1302 mono_metadata_parse_array (MonoImage
*m
, const char *ptr
, const char **rptr
)
1304 return mono_metadata_parse_array_full (m
, NULL
, ptr
, rptr
);
1308 * mono_metadata_free_array:
1309 * @array: array description
1311 * Frees the array description returned from mono_metadata_parse_array().
1314 mono_metadata_free_array (MonoArrayType
*array
)
1316 g_free (array
->sizes
);
1317 g_free (array
->lobounds
);
1322 * need to add common field and param attributes combinations:
1325 * public static literal
1328 * private static literal
1330 static const MonoType
1332 /* data, attrs, type, nmods, byref, pinned */
1333 {{NULL
}, 0, MONO_TYPE_VOID
, 0, 0, 0},
1334 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 0, 0},
1335 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 1, 0},
1336 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 0, 0},
1337 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 1, 0},
1338 {{NULL
}, 0, MONO_TYPE_I1
, 0, 0, 0},
1339 {{NULL
}, 0, MONO_TYPE_I1
, 0, 1, 0},
1340 {{NULL
}, 0, MONO_TYPE_U1
, 0, 0, 0},
1341 {{NULL
}, 0, MONO_TYPE_U1
, 0, 1, 0},
1342 {{NULL
}, 0, MONO_TYPE_I2
, 0, 0, 0},
1343 {{NULL
}, 0, MONO_TYPE_I2
, 0, 1, 0},
1344 {{NULL
}, 0, MONO_TYPE_U2
, 0, 0, 0},
1345 {{NULL
}, 0, MONO_TYPE_U2
, 0, 1, 0},
1346 {{NULL
}, 0, MONO_TYPE_I4
, 0, 0, 0},
1347 {{NULL
}, 0, MONO_TYPE_I4
, 0, 1, 0},
1348 {{NULL
}, 0, MONO_TYPE_U4
, 0, 0, 0},
1349 {{NULL
}, 0, MONO_TYPE_U4
, 0, 1, 0},
1350 {{NULL
}, 0, MONO_TYPE_I8
, 0, 0, 0},
1351 {{NULL
}, 0, MONO_TYPE_I8
, 0, 1, 0},
1352 {{NULL
}, 0, MONO_TYPE_U8
, 0, 0, 0},
1353 {{NULL
}, 0, MONO_TYPE_U8
, 0, 1, 0},
1354 {{NULL
}, 0, MONO_TYPE_R4
, 0, 0, 0},
1355 {{NULL
}, 0, MONO_TYPE_R4
, 0, 1, 0},
1356 {{NULL
}, 0, MONO_TYPE_R8
, 0, 0, 0},
1357 {{NULL
}, 0, MONO_TYPE_R8
, 0, 1, 0},
1358 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 0, 0},
1359 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 1, 0},
1360 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 0, 0},
1361 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 1, 0},
1362 {{NULL
}, 0, MONO_TYPE_TYPEDBYREF
, 0, 0, 0},
1363 {{NULL
}, 0, MONO_TYPE_I
, 0, 0, 0},
1364 {{NULL
}, 0, MONO_TYPE_I
, 0, 1, 0},
1365 {{NULL
}, 0, MONO_TYPE_U
, 0, 0, 0},
1366 {{NULL
}, 0, MONO_TYPE_U
, 0, 1, 0},
1369 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1371 static GHashTable
*type_cache
= NULL
;
1372 static int next_generic_inst_id
= 0;
1374 static guint
mono_generic_class_hash (gconstpointer data
);
1377 * MonoTypes with modifies are never cached, so we never check or use that field.
1380 mono_type_hash (gconstpointer data
)
1382 const MonoType
*type
= (const MonoType
*) data
;
1383 if (type
->type
== MONO_TYPE_GENERICINST
)
1384 return mono_generic_class_hash (type
->data
.generic_class
);
1386 return type
->type
| (type
->byref
<< 8) | (type
->attrs
<< 9);
1390 mono_type_equal (gconstpointer ka
, gconstpointer kb
)
1392 const MonoType
*a
= (const MonoType
*) ka
;
1393 const MonoType
*b
= (const MonoType
*) kb
;
1395 if (a
->type
!= b
->type
|| a
->byref
!= b
->byref
|| a
->attrs
!= b
->attrs
|| a
->pinned
!= b
->pinned
)
1397 /* need other checks */
1402 mono_metadata_generic_inst_hash (gconstpointer data
)
1404 const MonoGenericInst
*ginst
= (const MonoGenericInst
*) data
;
1408 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
1410 hash
+= mono_metadata_type_hash (ginst
->type_argv
[i
]);
1413 return hash
^ (ginst
->is_open
<< 8);
1417 mono_generic_inst_equal_full (const MonoGenericInst
*a
, const MonoGenericInst
*b
, gboolean signature_only
)
1421 #ifndef MONO_SMALL_CONFIG
1422 if (a
->id
&& b
->id
) {
1425 if (!signature_only
)
1430 if (a
->is_open
!= b
->is_open
|| a
->type_argc
!= b
->type_argc
)
1432 for (i
= 0; i
< a
->type_argc
; ++i
) {
1433 if (!do_mono_metadata_type_equal (a
->type_argv
[i
], b
->type_argv
[i
], signature_only
))
1440 mono_metadata_generic_inst_equal (gconstpointer ka
, gconstpointer kb
)
1442 const MonoGenericInst
*a
= (const MonoGenericInst
*) ka
;
1443 const MonoGenericInst
*b
= (const MonoGenericInst
*) kb
;
1445 return mono_generic_inst_equal_full (a
, b
, FALSE
);
1449 mono_generic_class_hash (gconstpointer data
)
1451 const MonoGenericClass
*gclass
= (const MonoGenericClass
*) data
;
1452 guint hash
= mono_metadata_type_hash (&gclass
->container_class
->byval_arg
);
1455 hash
+= gclass
->is_tb_open
;
1456 hash
+= mono_metadata_generic_context_hash (&gclass
->context
);
1462 mono_generic_class_equal (gconstpointer ka
, gconstpointer kb
)
1464 const MonoGenericClass
*a
= (const MonoGenericClass
*) ka
;
1465 const MonoGenericClass
*b
= (const MonoGenericClass
*) kb
;
1467 return _mono_metadata_generic_class_equal (a
, b
, FALSE
);
1471 * mono_metadata_init:
1473 * Initialize the global variables of this module.
1474 * This is a Mono runtime internal function.
1477 mono_metadata_init (void)
1481 type_cache
= g_hash_table_new (mono_type_hash
, mono_type_equal
);
1483 for (i
= 0; i
< NBUILTIN_TYPES (); ++i
)
1484 g_hash_table_insert (type_cache
, (gpointer
) &builtin_types
[i
], (gpointer
) &builtin_types
[i
]);
1488 * mono_metadata_cleanup:
1490 * Free all resources used by this module.
1491 * This is a Mono runtime internal function.
1494 mono_metadata_cleanup (void)
1496 g_hash_table_destroy (type_cache
);
1501 * mono_metadata_parse_type:
1502 * @m: metadata context
1503 * @mode: king of type that may be found at @ptr
1504 * @opt_attrs: optional attributes to store in the returned type
1505 * @ptr: pointer to the type representation
1506 * @rptr: pointer updated to match the end of the decoded stream
1507 * @transient: whenever to allocate the result from the heap or from a mempool
1509 * Decode a compressed type description found at @ptr in @m.
1510 * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
1511 * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
1512 * This function can be used to decode type descriptions in method signatures,
1513 * field signatures, locals signatures etc.
1515 * To parse a generic type, `generic_container' points to the current class'es
1516 * (the `generic_container' field in the MonoClass) or the current generic method's
1517 * (stored in image->property_hash) generic container.
1518 * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
1519 * this MonoGenericContainer.
1521 * LOCKING: Acquires the loader lock.
1523 * Returns: a #MonoType structure representing the decoded type.
1526 mono_metadata_parse_type_internal (MonoImage
*m
, MonoGenericContainer
*container
, MonoParseTypeMode mode
,
1527 short opt_attrs
, gboolean transient
, const char *ptr
, const char **rptr
)
1529 MonoType
*type
, *cached
;
1531 gboolean byref
= FALSE
;
1532 gboolean pinned
= FALSE
;
1533 const char *tmp_ptr
;
1538 * According to the spec, custom modifiers should come before the byref
1539 * flag, but the IL produced by ilasm from the following signature:
1540 * object modopt(...) &
1541 * starts with a byref flag, followed by the modifiers. (bug #49802)
1542 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1543 * it would be better to treat byref as real type constructor instead of
1545 * Also, pinned should come before anything else, but some MSV++ produced
1546 * assemblies violate this (#bug 61990).
1549 /* Count the modifiers first */
1554 case MONO_TYPE_PINNED
:
1555 case MONO_TYPE_BYREF
:
1558 case MONO_TYPE_CMOD_REQD
:
1559 case MONO_TYPE_CMOD_OPT
:
1561 mono_metadata_parse_custom_mod (m
, NULL
, tmp_ptr
, &tmp_ptr
);
1571 size
= MONO_SIZEOF_TYPE
+ ((gint32
)count
) * sizeof (MonoCustomMod
);
1572 type
= transient
? g_malloc0 (size
) : mono_image_alloc0 (m
, size
);
1573 type
->num_mods
= count
;
1575 g_warning ("got more than 64 modifiers in type");
1578 memset (type
, 0, MONO_SIZEOF_TYPE
);
1581 /* Parse pinned, byref and custom modifiers */
1586 case MONO_TYPE_PINNED
:
1590 case MONO_TYPE_BYREF
:
1594 case MONO_TYPE_CMOD_REQD
:
1595 case MONO_TYPE_CMOD_OPT
:
1596 mono_metadata_parse_custom_mod (m
, &(type
->modifiers
[count
]), ptr
, &ptr
);
1604 type
->attrs
= opt_attrs
;
1605 type
->byref
= byref
;
1606 type
->pinned
= pinned
? 1 : 0;
1608 if (!do_mono_metadata_parse_type (type
, m
, container
, transient
, ptr
, &ptr
)) {
1615 if (!type
->num_mods
&& !transient
) {
1616 /* no need to free type here, because it is on the stack */
1617 if ((type
->type
== MONO_TYPE_CLASS
|| type
->type
== MONO_TYPE_VALUETYPE
) && !type
->pinned
&& !type
->attrs
) {
1618 MonoType
*ret
= type
->byref
? &type
->data
.klass
->this_arg
: &type
->data
.klass
->byval_arg
;
1620 /* Consider the case:
1622 class Foo<T> { class Bar {} }
1623 class Test : Foo<Test>.Bar {}
1625 When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
1626 a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1628 We ensure that the MonoClass is in a state that we can canonicalize to:
1630 klass->byval_arg.data.klass == klass
1631 klass->this_arg.data.klass == klass
1633 If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1635 LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1636 of a MonoClass which currently holds the loader lock. 'type' is local.
1638 if (ret
->data
.klass
== type
->data
.klass
) {
1642 /* No need to use locking since nobody is modifying the hash table */
1643 if ((cached
= g_hash_table_lookup (type_cache
, type
))) {
1648 /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1650 if (type
== &stype
) {
1651 type
= transient
? g_malloc (MONO_SIZEOF_TYPE
) : mono_image_alloc (m
, MONO_SIZEOF_TYPE
);
1652 memcpy (type
, &stype
, MONO_SIZEOF_TYPE
);
1658 mono_metadata_parse_type_full (MonoImage
*m
, MonoGenericContainer
*container
, MonoParseTypeMode mode
,
1659 short opt_attrs
, const char *ptr
, const char **rptr
)
1661 return mono_metadata_parse_type_internal (m
, container
, mode
, opt_attrs
, FALSE
, ptr
, rptr
);
1665 * LOCKING: Acquires the loader lock.
1668 mono_metadata_parse_type (MonoImage
*m
, MonoParseTypeMode mode
, short opt_attrs
,
1669 const char *ptr
, const char **rptr
)
1671 return mono_metadata_parse_type_full (m
, NULL
, mode
, opt_attrs
, ptr
, rptr
);
1675 mono_metadata_method_has_param_attrs (MonoImage
*m
, int def
)
1677 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1678 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1679 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1681 if (def
< methodt
->rows
)
1682 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1684 lastp
= m
->tables
[MONO_TABLE_PARAM
].rows
+ 1;
1686 for (i
= param_index
; i
< lastp
; ++i
) {
1687 guint32 flags
= mono_metadata_decode_row_col (paramt
, i
- 1, MONO_PARAM_FLAGS
);
1696 * mono_metadata_get_param_attrs:
1698 * @m The image to loader parameter attributes from
1699 * @def method def token (one based)
1700 * @param_count number of params to decode including the return value
1702 * Return the parameter attributes for the method whose MethodDef index is DEF. The
1703 * returned memory needs to be freed by the caller. If all the param attributes are
1704 * 0, then NULL is returned.
1707 mono_metadata_get_param_attrs (MonoImage
*m
, int def
, int param_count
)
1709 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1710 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1711 guint32 cols
[MONO_PARAM_SIZE
];
1712 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1715 if (def
< methodt
->rows
)
1716 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1718 lastp
= paramt
->rows
+ 1;
1720 for (i
= param_index
; i
< lastp
; ++i
) {
1721 mono_metadata_decode_row (paramt
, i
- 1, cols
, MONO_PARAM_SIZE
);
1722 if (cols
[MONO_PARAM_FLAGS
]) {
1724 pattrs
= g_new0 (int, param_count
);
1725 /* at runtime we just ignore this kind of malformed file:
1726 * the verifier can signal the error to the user
1728 if (cols
[MONO_PARAM_SEQUENCE
] >= param_count
)
1730 pattrs
[cols
[MONO_PARAM_SEQUENCE
]] = cols
[MONO_PARAM_FLAGS
];
1738 * mono_metadata_parse_signature_full:
1739 * @image: metadata context
1740 * @generic_container: generic container
1741 * @toke: metadata token
1743 * Decode a method signature stored in the STANDALONESIG table
1745 * LOCKING: Assumes the loader lock is held.
1747 * Returns: a MonoMethodSignature describing the signature.
1749 MonoMethodSignature
*
1750 mono_metadata_parse_signature_full (MonoImage
*image
, MonoGenericContainer
*generic_container
, guint32 token
)
1752 MonoTableInfo
*tables
= image
->tables
;
1753 guint32 idx
= mono_metadata_token_index (token
);
1758 return mono_lookup_dynamic_token (image
, token
, NULL
);
1760 g_assert (mono_metadata_token_table(token
) == MONO_TABLE_STANDALONESIG
);
1762 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
1764 ptr
= mono_metadata_blob_heap (image
, sig
);
1765 mono_metadata_decode_blob_size (ptr
, &ptr
);
1767 return mono_metadata_parse_method_signature_full (image
, generic_container
, 0, ptr
, NULL
);
1771 * mono_metadata_parse_signature:
1772 * @image: metadata context
1773 * @toke: metadata token
1775 * Decode a method signature stored in the STANDALONESIG table
1777 * Returns: a MonoMethodSignature describing the signature.
1779 MonoMethodSignature
*
1780 mono_metadata_parse_signature (MonoImage
*image
, guint32 token
)
1782 return mono_metadata_parse_signature_full (image
, NULL
, token
);
1786 * mono_metadata_signature_alloc:
1787 * @image: metadata context
1788 * @nparmas: number of parameters in the signature
1790 * Allocate a MonoMethodSignature structure with the specified number of params.
1791 * The return type and the params types need to be filled later.
1792 * This is a Mono runtime internal function.
1794 * LOCKING: Assumes the loader lock is held.
1796 * Returns: the new MonoMethodSignature structure.
1798 MonoMethodSignature
*
1799 mono_metadata_signature_alloc (MonoImage
*m
, guint32 nparams
)
1801 MonoMethodSignature
*sig
;
1803 sig
= mono_image_alloc0 (m
, MONO_SIZEOF_METHOD_SIGNATURE
+ ((gint32
)nparams
) * sizeof (MonoType
*));
1804 sig
->param_count
= nparams
;
1805 sig
->sentinelpos
= -1;
1810 static MonoMethodSignature
*
1811 mono_metadata_signature_dup_internal (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1814 MonoMethodSignature
*ret
;
1815 sigsize
= MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*);
1818 ret
= mono_image_alloc (image
, sigsize
);
1820 ret
= mono_mempool_alloc (mp
, sigsize
);
1822 ret
= g_malloc (sigsize
);
1824 memcpy (ret
, sig
, sigsize
);
1828 MonoMethodSignature
*
1829 mono_metadata_signature_dup_full (MonoImage
*image
, MonoMethodSignature
*sig
)
1831 return mono_metadata_signature_dup_internal (image
, NULL
, sig
);
1834 /*The mempool is accessed without synchronization*/
1835 MonoMethodSignature
*
1836 mono_metadata_signature_dup_mempool (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1838 return mono_metadata_signature_dup_internal (NULL
, mp
, sig
);
1842 * mono_metadata_signature_dup:
1843 * @sig: method signature
1845 * Duplicate an existing MonoMethodSignature so it can be modified.
1846 * This is a Mono runtime internal function.
1848 * Returns: the new MonoMethodSignature structure.
1850 MonoMethodSignature
*
1851 mono_metadata_signature_dup (MonoMethodSignature
*sig
)
1853 return mono_metadata_signature_dup_full (NULL
, sig
);
1857 * mono_metadata_signature_size:
1859 * Return the amount of memory allocated to SIG.
1862 mono_metadata_signature_size (MonoMethodSignature
*sig
)
1864 return MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*);
1868 * mono_metadata_parse_method_signature:
1869 * @m: metadata context
1870 * @generic_container: generics container
1871 * @def: the MethodDef index or 0 for Ref signatures.
1872 * @ptr: pointer to the signature metadata representation
1873 * @rptr: pointer updated to match the end of the decoded stream
1875 * Decode a method signature stored at @ptr.
1876 * This is a Mono runtime internal function.
1878 * LOCKING: Assumes the loader lock is held.
1880 * Returns: a MonoMethodSignature describing the signature.
1882 MonoMethodSignature
*
1883 mono_metadata_parse_method_signature_full (MonoImage
*m
, MonoGenericContainer
*container
,
1884 int def
, const char *ptr
, const char **rptr
)
1886 MonoMethodSignature
*method
;
1887 int i
, *pattrs
= NULL
;
1888 guint32 hasthis
= 0, explicit_this
= 0, call_convention
, param_count
;
1889 guint32 gen_param_count
= 0;
1890 gboolean is_open
= FALSE
;
1893 gen_param_count
= 1;
1898 call_convention
= *ptr
& 0x0F;
1900 if (gen_param_count
)
1901 gen_param_count
= mono_metadata_decode_value (ptr
, &ptr
);
1902 param_count
= mono_metadata_decode_value (ptr
, &ptr
);
1905 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 */
1907 method
= mono_metadata_signature_alloc (m
, param_count
);
1908 method
->hasthis
= hasthis
;
1909 method
->explicit_this
= explicit_this
;
1910 method
->call_convention
= call_convention
;
1911 method
->generic_param_count
= gen_param_count
;
1913 if (call_convention
!= 0xa) {
1914 method
->ret
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_RET
, pattrs
? pattrs
[0] : 0, ptr
, &ptr
);
1916 mono_metadata_free_method_signature (method
);
1920 is_open
= mono_class_is_open_constructed_type (method
->ret
);
1923 for (i
= 0; i
< method
->param_count
; ++i
) {
1924 if (*ptr
== MONO_TYPE_SENTINEL
) {
1925 if (method
->call_convention
!= MONO_CALL_VARARG
|| def
) {
1926 g_warning ("found sentinel for methoddef or no vararg method 0x%08x on image %s", def
, m
->name
);
1930 if (method
->sentinelpos
>= 0) {
1931 g_warning ("found sentinel twice in the same signature for method 0x%08x on image %s", def
, m
->name
);
1935 method
->sentinelpos
= i
;
1938 method
->params
[i
] = mono_metadata_parse_type_full (m
, container
, MONO_PARSE_PARAM
, pattrs
? pattrs
[i
+1] : 0, ptr
, &ptr
);
1939 if (!method
->params
[i
]) {
1940 mono_metadata_free_method_signature (method
);
1945 is_open
= mono_class_is_open_constructed_type (method
->params
[i
]);
1948 /* The sentinel could be missing if the caller does not pass any additional arguments */
1949 if (!def
&& method
->call_convention
== MONO_CALL_VARARG
&& method
->sentinelpos
< 0)
1950 method
->sentinelpos
= method
->param_count
;
1952 method
->has_type_parameters
= is_open
;
1954 if (def
&& (method
->call_convention
== MONO_CALL_VARARG
))
1955 method
->sentinelpos
= method
->param_count
;
1962 * Add signature to a cache and increase ref count...
1969 * mono_metadata_parse_method_signature:
1970 * @m: metadata context
1971 * @def: the MethodDef index or 0 for Ref signatures.
1972 * @ptr: pointer to the signature metadata representation
1973 * @rptr: pointer updated to match the end of the decoded stream
1975 * Decode a method signature stored at @ptr.
1976 * This is a Mono runtime internal function.
1978 * LOCKING: Assumes the loader lock is held.
1980 * Returns: a MonoMethodSignature describing the signature.
1982 MonoMethodSignature
*
1983 mono_metadata_parse_method_signature (MonoImage
*m
, int def
, const char *ptr
, const char **rptr
)
1985 return mono_metadata_parse_method_signature_full (m
, NULL
, def
, ptr
, rptr
);
1989 * mono_metadata_free_method_signature:
1990 * @sig: signature to destroy
1992 * Free the memory allocated in the signature @sig.
1993 * This method needs to be robust and work also on partially-built
1994 * signatures, so it does extra checks.
1997 mono_metadata_free_method_signature (MonoMethodSignature
*sig
)
1999 /* Everything is allocated from mempools */
2003 mono_metadata_free_type (sig->ret);
2004 for (i = 0; i < sig->param_count; ++i) {
2005 if (sig->params [i])
2006 mono_metadata_free_type (sig->params [i]);
2012 mono_metadata_free_inflated_signature (MonoMethodSignature
*sig
)
2016 /* Allocated in inflate_generic_signature () */
2018 mono_metadata_free_type (sig
->ret
);
2019 for (i
= 0; i
< sig
->param_count
; ++i
) {
2020 if (sig
->params
[i
])
2021 mono_metadata_free_type (sig
->params
[i
]);
2027 inflated_method_equal (gconstpointer a
, gconstpointer b
)
2029 const MonoMethodInflated
*ma
= a
;
2030 const MonoMethodInflated
*mb
= b
;
2031 if (ma
->declaring
!= mb
->declaring
)
2033 if (ma
->method
.method
.is_mb_open
!= mb
->method
.method
.is_mb_open
)
2035 return mono_metadata_generic_context_equal (&ma
->context
, &mb
->context
);
2039 inflated_method_hash (gconstpointer a
)
2041 const MonoMethodInflated
*ma
= a
;
2042 return (mono_metadata_generic_context_hash (&ma
->context
) ^ mono_aligned_addr_hash (ma
->declaring
)) + ma
->method
.method
.is_mb_open
;
2046 inflated_signature_equal (gconstpointer a
, gconstpointer b
)
2048 const MonoInflatedMethodSignature
*sig1
= a
;
2049 const MonoInflatedMethodSignature
*sig2
= b
;
2051 /* sig->sig is assumed to be canonized */
2052 if (sig1
->sig
!= sig2
->sig
)
2054 /* The generic instances are canonized */
2055 return mono_metadata_generic_context_equal (&sig1
->context
, &sig2
->context
);
2059 inflated_signature_hash (gconstpointer a
)
2061 const MonoInflatedMethodSignature
*sig
= a
;
2063 /* sig->sig is assumed to be canonized */
2064 return mono_metadata_generic_context_hash (&sig
->context
) ^ mono_aligned_addr_hash (sig
->sig
);
2068 dump_ginst (MonoGenericInst *ginst)
2073 g_print ("Ginst: <");
2074 for (i = 0; i < ginst->type_argc; ++i) {
2077 name = mono_type_get_name (ginst->type_argv [i]);
2078 g_print ("%s", name);
2084 static gboolean
type_in_image (MonoType
*type
, MonoImage
*image
);
2087 signature_in_image (MonoMethodSignature
*sig
, MonoImage
*image
)
2089 gpointer iter
= NULL
;
2092 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2093 if (type_in_image (p
, image
))
2096 return type_in_image (mono_signature_get_return_type (sig
), image
);
2100 ginst_in_image (MonoGenericInst
*ginst
, MonoImage
*image
)
2104 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2105 if (type_in_image (ginst
->type_argv
[i
], image
))
2113 gclass_in_image (MonoGenericClass
*gclass
, MonoImage
*image
)
2115 return gclass
->container_class
->image
== image
||
2116 ginst_in_image (gclass
->context
.class_inst
, image
);
2120 type_in_image (MonoType
*type
, MonoImage
*image
)
2123 switch (type
->type
) {
2124 case MONO_TYPE_GENERICINST
:
2125 return gclass_in_image (type
->data
.generic_class
, image
);
2127 type
= type
->data
.type
;
2129 case MONO_TYPE_SZARRAY
:
2130 type
= &type
->data
.klass
->byval_arg
;
2132 case MONO_TYPE_ARRAY
:
2133 type
= &type
->data
.array
->eklass
->byval_arg
;
2135 case MONO_TYPE_FNPTR
:
2136 return signature_in_image (type
->data
.method
, image
);
2137 case MONO_TYPE_VAR
: {
2138 MonoGenericContainer
*container
= mono_type_get_generic_param_owner (type
);
2140 g_assert (!container
->is_method
);
2142 * FIXME: The following check is here solely
2143 * for monodis, which uses the internal
2145 * mono_metadata_load_generic_params(). The
2146 * caller of that function needs to fill in
2147 * owner->klass or owner->method of the
2148 * returned struct, but monodis doesn't do
2149 * that. The image unloading depends on that,
2150 * however, so a crash results without this
2153 if (!container
->owner
.klass
)
2154 return container
->image
== image
;
2155 return container
->owner
.klass
->image
== image
;
2157 return type
->data
.generic_param
->image
== image
;
2160 case MONO_TYPE_MVAR
: {
2161 MonoGenericContainer
*container
= mono_type_get_generic_param_owner (type
);
2162 if (type
->data
.generic_param
->image
== image
)
2165 g_assert (container
->is_method
);
2166 if (!container
->owner
.method
)
2167 /* RefEmit created generic param whose method is not finished */
2168 return container
->image
== image
;
2169 return container
->owner
.method
->klass
->image
== image
;
2171 return type
->data
.generic_param
->image
== image
;
2175 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2176 return image
== mono_class_from_mono_type (type
)->image
;
2180 static MonoImageSet
*mscorlib_image_set
;
2181 static GPtrArray
*image_sets
;
2186 * Return a MonoImageSet representing the set of images in IMAGES.
2188 * LOCKING: Assumes the loader lock is held.
2190 static MonoImageSet
*
2191 get_image_set (MonoImage
**images
, int nimages
)
2198 image_sets
= g_ptr_array_new ();
2201 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
&& mscorlib_image_set
)
2202 return mscorlib_image_set
;
2204 /* Happens with empty generic instances */
2206 return mscorlib_image_set
;
2208 if (images
[0] == mono_defaults
.corlib
&& nimages
> 1)
2209 l
= images
[1]->image_sets
;
2211 l
= images
[0]->image_sets
;
2214 for (; l
; l
= l
->next
) {
2217 if (set
->nimages
== nimages
) {
2218 for (j
= 0; j
< nimages
; ++j
) {
2219 for (k
= 0; k
< nimages
; ++k
)
2220 if (set
->images
[k
] == images
[j
])
2234 set
= g_new0 (MonoImageSet
, 1);
2235 set
->nimages
= nimages
;
2236 set
->images
= g_new0 (MonoImage
*, nimages
);
2237 InitializeCriticalSection (&set
->lock
);
2238 for (i
= 0; i
< nimages
; ++i
)
2239 set
->images
[i
] = images
[i
];
2240 set
->gclass_cache
= g_hash_table_new_full (mono_generic_class_hash
, mono_generic_class_equal
, NULL
, (GDestroyNotify
)free_generic_class
);
2241 set
->ginst_cache
= g_hash_table_new_full (mono_metadata_generic_inst_hash
, mono_metadata_generic_inst_equal
, NULL
, (GDestroyNotify
)free_generic_inst
);
2242 set
->gmethod_cache
= g_hash_table_new_full (inflated_method_hash
, inflated_method_equal
, NULL
, (GDestroyNotify
)free_inflated_method
);
2243 set
->gsignature_cache
= g_hash_table_new_full (inflated_signature_hash
, inflated_signature_equal
, NULL
, (GDestroyNotify
)free_inflated_signature
);
2245 for (i
= 0; i
< nimages
; ++i
)
2246 set
->images
[i
]->image_sets
= g_slist_prepend (set
->images
[i
]->image_sets
, set
);
2248 g_ptr_array_add (image_sets
, set
);
2251 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
)
2252 mscorlib_image_set
= set
;
2258 delete_image_set (MonoImageSet
*set
)
2262 g_hash_table_destroy (set
->gclass_cache
);
2263 g_hash_table_destroy (set
->ginst_cache
);
2264 g_hash_table_destroy (set
->gmethod_cache
);
2265 g_hash_table_destroy (set
->gsignature_cache
);
2267 for (i
= 0; i
< set
->nimages
; ++i
)
2268 set
->images
[i
]->image_sets
= g_slist_remove (set
->images
[i
]->image_sets
, set
);
2270 g_ptr_array_remove (image_sets
, set
);
2273 mono_mempool_destroy (set
->mempool
);
2274 g_free (set
->images
);
2275 DeleteCriticalSection (&set
->lock
);
2280 * Structure used by the collect_..._images functions to store the image list.
2283 MonoImage
*image_buf
[64];
2285 int nimages
, images_len
;
2289 collect_data_init (CollectData
*data
)
2291 data
->images
= data
->image_buf
;
2292 data
->images_len
= 64;
2297 collect_data_free (CollectData
*data
)
2299 if (data
->images
!= data
->image_buf
)
2300 g_free (data
->images
);
2304 enlarge_data (CollectData
*data
)
2306 int new_len
= data
->images_len
< 16 ? 16 : data
->images_len
* 2;
2307 MonoImage
**d
= g_new (MonoImage
*, new_len
);
2310 g_assert_not_reached ();
2311 memcpy (d
, data
->images
, data
->images_len
);
2312 if (data
->images
!= data
->image_buf
)
2313 g_free (data
->images
);
2315 data
->images_len
= new_len
;
2319 add_image (MonoImage
*image
, CollectData
*data
)
2323 /* The arrays are small, so use a linear search instead of a hash table */
2324 for (i
= 0; i
< data
->nimages
; ++i
)
2325 if (data
->images
[i
] == image
)
2328 if (data
->nimages
== data
->images_len
)
2329 enlarge_data (data
);
2331 data
->images
[data
->nimages
++] = image
;
2335 collect_type_images (MonoType
*type
, CollectData
*data
);
2338 collect_ginst_images (MonoGenericInst
*ginst
, CollectData
*data
)
2342 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2343 collect_type_images (ginst
->type_argv
[i
], data
);
2348 collect_gclass_images (MonoGenericClass
*gclass
, CollectData
*data
)
2350 add_image (gclass
->container_class
->image
, data
);
2351 if (gclass
->context
.class_inst
)
2352 collect_ginst_images (gclass
->context
.class_inst
, data
);
2356 collect_signature_images (MonoMethodSignature
*sig
, CollectData
*data
)
2358 gpointer iter
= NULL
;
2361 collect_type_images (mono_signature_get_return_type (sig
), data
);
2362 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2363 collect_type_images (p
, data
);
2367 collect_inflated_signature_images (MonoInflatedMethodSignature
*sig
, CollectData
*data
)
2369 collect_signature_images (sig
->sig
, data
);
2370 if (sig
->context
.class_inst
)
2371 collect_ginst_images (sig
->context
.class_inst
, data
);
2372 if (sig
->context
.method_inst
)
2373 collect_ginst_images (sig
->context
.method_inst
, data
);
2377 collect_method_images (MonoMethodInflated
*method
, CollectData
*data
)
2379 add_image (method
->declaring
->klass
->image
, data
);
2380 if (method
->context
.class_inst
)
2381 collect_ginst_images (method
->context
.class_inst
, data
);
2382 if (method
->context
.method_inst
)
2383 collect_ginst_images (method
->context
.method_inst
, data
);
2385 if (((MonoMethod*)method)->signature)
2386 collect_signature_images (mono_method_signature ((MonoMethod*)method), data);
2391 collect_type_images (MonoType
*type
, CollectData
*data
)
2394 switch (type
->type
) {
2395 case MONO_TYPE_GENERICINST
:
2396 collect_gclass_images (type
->data
.generic_class
, data
);
2399 type
= type
->data
.type
;
2401 case MONO_TYPE_SZARRAY
:
2402 type
= &type
->data
.klass
->byval_arg
;
2404 case MONO_TYPE_ARRAY
:
2405 type
= &type
->data
.array
->eklass
->byval_arg
;
2407 case MONO_TYPE_FNPTR
:
2408 //return signature_in_image (type->data.method, image);
2409 g_assert_not_reached ();
2410 case MONO_TYPE_VAR
: {
2411 MonoGenericContainer
*container
= mono_type_get_generic_param_owner (type
);
2413 g_assert (!container
->is_method
);
2415 * FIXME: The following check is here solely
2416 * for monodis, which uses the internal
2418 * mono_metadata_load_generic_params(). The
2419 * caller of that function needs to fill in
2420 * owner->klass or owner->method of the
2421 * returned struct, but monodis doesn't do
2422 * that. The image unloading depends on that,
2423 * however, so a crash results without this
2426 if (!container
->owner
.klass
)
2427 add_image (container
->image
, data
);
2429 add_image (container
->owner
.klass
->image
, data
);
2431 add_image (type
->data
.generic_param
->image
, data
);
2435 case MONO_TYPE_MVAR
: {
2436 MonoGenericContainer
*container
= mono_type_get_generic_param_owner (type
);
2437 if (type
->data
.generic_param
->image
)
2438 add_image (type
->data
.generic_param
->image
, data
);
2440 if (!container
->owner
.method
) {
2441 /* RefEmit created generic param whose method is not finished */
2442 add_image (container
->image
, data
);
2444 g_assert (container
->is_method
);
2445 add_image (container
->owner
.method
->klass
->image
, data
);
2448 add_image (type
->data
.generic_param
->image
, data
);
2452 case MONO_TYPE_CLASS
:
2453 case MONO_TYPE_VALUETYPE
:
2454 add_image (mono_class_from_mono_type (type
)->image
, data
);
2457 add_image (mono_defaults
.corlib
, data
);
2464 } CleanForImageUserData
;
2467 steal_gclass_in_image (gpointer key
, gpointer value
, gpointer data
)
2469 MonoGenericClass
*gclass
= key
;
2470 CleanForImageUserData
*user_data
= data
;
2472 g_assert (gclass_in_image (gclass
, user_data
->image
));
2474 user_data
->list
= g_slist_prepend (user_data
->list
, gclass
);
2479 steal_ginst_in_image (gpointer key
, gpointer value
, gpointer data
)
2481 MonoGenericInst
*ginst
= key
;
2482 CleanForImageUserData
*user_data
= data
;
2484 // This doesn't work during corlib compilation
2485 //g_assert (ginst_in_image (ginst, user_data->image));
2487 user_data
->list
= g_slist_prepend (user_data
->list
, ginst
);
2492 inflated_method_in_image (gpointer key
, gpointer value
, gpointer data
)
2494 MonoImage
*image
= data
;
2495 MonoMethodInflated
*method
= key
;
2498 // https://bugzilla.novell.com/show_bug.cgi?id=458168
2499 g_assert (method
->declaring
->klass
->image
== image
||
2500 (method
->context
.class_inst
&& ginst_in_image (method
->context
.class_inst
, image
)) ||
2501 (method
->context
.method_inst
&& ginst_in_image (method
->context
.method_inst
, image
)) || (((MonoMethod
*)method
)->signature
&& signature_in_image (mono_method_signature ((MonoMethod
*)method
), image
)));
2507 inflated_signature_in_image (gpointer key
, gpointer value
, gpointer data
)
2509 MonoImage
*image
= data
;
2510 MonoInflatedMethodSignature
*sig
= key
;
2512 return signature_in_image (sig
->sig
, image
) ||
2513 (sig
->context
.class_inst
&& ginst_in_image (sig
->context
.class_inst
, image
)) ||
2514 (sig
->context
.method_inst
&& ginst_in_image (sig
->context
.method_inst
, image
));
2518 check_gmethod (gpointer key
, gpointer value
, gpointer data
)
2520 MonoMethodInflated
*method
= key
;
2521 MonoImage
*image
= data
;
2523 if (method
->context
.class_inst
)
2524 g_assert (!ginst_in_image (method
->context
.class_inst
, image
));
2525 if (method
->context
.method_inst
)
2526 g_assert (!ginst_in_image (method
->context
.method_inst
, image
));
2527 if (((MonoMethod
*)method
)->signature
)
2528 g_assert (!signature_in_image (mono_method_signature ((MonoMethod
*)method
), image
));
2534 * Run a consistency check on the image set data structures.
2536 static G_GNUC_UNUSED
void
2537 check_image_sets (MonoImage
*image
)
2540 GSList
*l
= image
->image_sets
;
2545 for (i
= 0; i
< image_sets
->len
; ++i
) {
2546 MonoImageSet
*set
= g_ptr_array_index (image_sets
, i
);
2548 if (!g_slist_find (l
, set
)) {
2549 g_hash_table_foreach (set
->gmethod_cache
, check_gmethod
, image
);
2555 mono_metadata_clean_for_image (MonoImage
*image
)
2557 CleanForImageUserData ginst_data
, gclass_data
;
2558 GSList
*l
, *set_list
, *free_list
= NULL
;
2560 //check_image_sets (image);
2562 /* The data structures could reference each other so we delete them in two phases */
2563 ginst_data
.image
= gclass_data
.image
= image
;
2564 ginst_data
.list
= gclass_data
.list
= NULL
;
2565 mono_loader_lock ();
2567 /* Collect the items to delete */
2568 /* delete_image_set () modifies the lists so make a copy */
2569 for (l
= image
->image_sets
; l
; l
= l
->next
) {
2570 MonoImageSet
*set
= l
->data
;
2572 g_hash_table_foreach_steal (set
->gclass_cache
, steal_gclass_in_image
, &gclass_data
);
2573 g_hash_table_foreach_steal (set
->ginst_cache
, steal_ginst_in_image
, &ginst_data
);
2574 g_hash_table_foreach_remove (set
->gmethod_cache
, inflated_method_in_image
, image
);
2575 g_hash_table_foreach_remove (set
->gsignature_cache
, inflated_signature_in_image
, image
);
2578 /* Delete the removed items */
2579 for (l
= ginst_data
.list
; l
; l
= l
->next
)
2580 free_list
= g_slist_concat (free_generic_inst_dependents (l
->data
), free_list
);
2581 for (l
= gclass_data
.list
; l
; l
= l
->next
)
2582 free_list
= g_slist_concat (free_generic_class_dependents (l
->data
), free_list
);
2583 g_slist_free (ginst_data
.list
);
2584 g_slist_free (gclass_data
.list
);
2585 /* delete_image_set () modifies the lists so make a copy */
2586 set_list
= g_slist_copy (image
->image_sets
);
2587 for (l
= set_list
; l
; l
= l
->next
) {
2588 MonoImageSet
*set
= l
->data
;
2590 delete_image_set (set
);
2592 g_slist_free (set_list
);
2594 mono_loader_unlock ();
2600 free_inflated_method (MonoMethodInflated
*imethod
)
2603 MonoMethod
*method
= (MonoMethod
*)imethod
;
2605 mono_marshal_free_inflated_wrappers (method
);
2607 if (method
->signature
)
2608 mono_metadata_free_inflated_signature (method
->signature
);
2610 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
))) {
2611 MonoMethodHeader
*header
= imethod
->header
;
2614 /* Allocated in inflate_generic_header () */
2615 for (i
= 0; i
< header
->num_locals
; ++i
)
2616 mono_metadata_free_type (header
->locals
[i
]);
2617 g_free (header
->clauses
);
2626 free_list_with_data (GSList
*l
)
2630 l
= g_slist_delete_link (l
, l
);
2635 free_generic_inst_dependents (MonoGenericInst
*ginst
)
2639 for (i
= 0; i
< ginst
->type_argc
; ++i
)
2640 mono_metadata_free_type (ginst
->type_argv
[i
]);
2641 return g_slist_prepend (NULL
, ginst
);
2645 free_generic_inst (MonoGenericInst
*ginst
)
2647 free_list_with_data (free_generic_inst_dependents (ginst
));
2651 free_generic_class_dependents (MonoGenericClass
*gclass
)
2656 /* FIXME: The dynamic case */
2657 if (gclass
->cached_class
&& !gclass
->cached_class
->image
->dynamic
&& !mono_generic_class_is_generic_type_definition (gclass
)) {
2658 MonoClass
*class = gclass
->cached_class
;
2660 /* Allocated in mono_class_init () */
2661 g_free (class->methods
);
2663 g_free (class->ext
->properties
);
2664 g_free (class->ext
->field_def_values
);
2666 /* Allocated in mono_class_setup_fields () */
2667 g_free (class->fields
);
2668 /* Allocated in mono_class_setup_vtable_general () */
2669 g_free (class->vtable
);
2670 /* Allocated in mono_generic_class_get_class () */
2671 g_free (class->interfaces
);
2672 /* Allocated in setup_interface_offsets () */
2673 g_free (class->interfaces_packed
);
2674 g_free (class->interface_offsets_packed
);
2675 g_free (class->interface_bitmap
);
2676 /* Allocated in mono_class_setup_supertypes () */
2677 g_free (class->supertypes
);
2678 l
= g_slist_prepend (l
, class);
2679 } else if (gclass
->is_dynamic
) {
2680 MonoDynamicGenericClass
*dgclass
= (MonoDynamicGenericClass
*)gclass
;
2682 for (i
= 0; i
< dgclass
->count_fields
; ++i
) {
2683 MonoClassField
*field
= dgclass
->fields
+ i
;
2684 mono_metadata_free_type (field
->type
);
2685 g_free ((char*)field
->name
);
2687 MONO_GC_UNREGISTER_ROOT (dgclass
->field_objects
[i
]);
2691 g_free (dgclass
->methods
);
2692 g_free (dgclass
->ctors
);
2693 g_free (dgclass
->fields
);
2694 g_free (dgclass
->field_objects
);
2695 g_free (dgclass
->field_generic_types
);
2696 if (!mono_generic_class_is_generic_type_definition (gclass
))
2697 l
= g_slist_prepend (l
, gclass
->cached_class
);
2699 return g_slist_prepend (l
, gclass
);
2703 free_generic_class (MonoGenericClass
*gclass
)
2705 free_list_with_data (free_generic_class_dependents (gclass
));
2709 free_inflated_signature (MonoInflatedMethodSignature
*sig
)
2711 mono_metadata_free_inflated_signature (sig
->sig
);
2716 * LOCKING: assumes the loader lock is held.
2719 mono_method_inflated_lookup (MonoMethodInflated
* method
, gboolean cache
)
2724 collect_data_init (&data
);
2726 collect_method_images (method
, &data
);
2728 set
= get_image_set (data
.images
, data
.nimages
);
2730 collect_data_free (&data
);
2733 g_hash_table_insert (set
->gmethod_cache
, method
, method
);
2737 return g_hash_table_lookup (set
->gmethod_cache
, method
);
2742 * mono_metadata_get_inflated_signature:
2744 * Given an inflated signature and a generic context, return a canonical copy of the
2745 * signature. The returned signature might be equal to SIG or it might be a cached copy.
2747 MonoMethodSignature
*
2748 mono_metadata_get_inflated_signature (MonoMethodSignature
*sig
, MonoGenericContext
*context
)
2750 MonoInflatedMethodSignature helper
;
2751 MonoInflatedMethodSignature
*res
;
2755 mono_loader_lock ();
2758 helper
.context
.class_inst
= context
->class_inst
;
2759 helper
.context
.method_inst
= context
->method_inst
;
2761 collect_data_init (&data
);
2763 collect_inflated_signature_images (&helper
, &data
);
2765 set
= get_image_set (data
.images
, data
.nimages
);
2767 collect_data_free (&data
);
2769 res
= g_hash_table_lookup (set
->gsignature_cache
, &helper
);
2771 res
= g_new0 (MonoInflatedMethodSignature
, 1);
2773 res
->context
.class_inst
= context
->class_inst
;
2774 res
->context
.method_inst
= context
->method_inst
;
2775 g_hash_table_insert (set
->gsignature_cache
, res
, res
);
2778 mono_loader_unlock ();
2783 * mono_metadata_get_generic_inst:
2785 * Given a list of types, return a MonoGenericInst that represents that list.
2786 * The returned MonoGenericInst has its own copy of the list of types. The list
2787 * passed in the argument can be freed, modified or disposed of.
2791 mono_metadata_get_generic_inst (int type_argc
, MonoType
**type_argv
)
2793 MonoGenericInst
*ginst
;
2796 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
2800 for (i
= 0; i
< type_argc
; ++i
)
2801 if (mono_class_is_open_constructed_type (type_argv
[i
]))
2803 is_open
= (i
< type_argc
);
2805 ginst
= alloca (size
);
2806 #ifndef MONO_SMALL_CONFIG
2809 ginst
->is_open
= is_open
;
2810 ginst
->type_argc
= type_argc
;
2811 memcpy (ginst
->type_argv
, type_argv
, type_argc
* sizeof (MonoType
*));
2813 mono_loader_lock ();
2815 collect_data_init (&data
);
2817 collect_ginst_images (ginst
, &data
);
2819 set
= get_image_set (data
.images
, data
.nimages
);
2821 collect_data_free (&data
);
2823 ginst
= g_hash_table_lookup (set
->ginst_cache
, ginst
);
2825 ginst
= g_malloc (size
);
2826 #ifndef MONO_SMALL_CONFIG
2827 ginst
->id
= ++next_generic_inst_id
;
2829 ginst
->is_open
= is_open
;
2830 ginst
->type_argc
= type_argc
;
2832 for (i
= 0; i
< type_argc
; ++i
)
2833 ginst
->type_argv
[i
] = mono_metadata_type_dup (NULL
, type_argv
[i
]);
2835 g_hash_table_insert (set
->ginst_cache
, ginst
, ginst
);
2838 mono_loader_unlock ();
2843 mono_metadata_is_type_builder_generic_type_definition (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
2845 MonoGenericContainer
*container
= container_class
->generic_container
;
2847 if (!is_dynamic
|| container_class
->wastypebuilder
|| container
->type_argc
!= inst
->type_argc
)
2849 return inst
== container
->context
.class_inst
;
2853 * mono_metadata_lookup_generic_class:
2855 * Returns a MonoGenericClass with the given properties.
2859 mono_metadata_lookup_generic_class (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
2861 MonoGenericClass
*gclass
;
2862 MonoGenericClass helper
;
2863 gboolean is_tb_open
= mono_metadata_is_type_builder_generic_type_definition (container_class
, inst
, is_dynamic
);
2867 helper
.container_class
= container_class
;
2868 helper
.context
.class_inst
= inst
;
2869 helper
.context
.method_inst
= NULL
;
2870 helper
.is_dynamic
= is_dynamic
; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
2871 helper
.is_tb_open
= is_tb_open
;
2872 helper
.cached_class
= NULL
;
2874 mono_loader_lock ();
2876 collect_data_init (&data
);
2878 collect_gclass_images (&helper
, &data
);
2880 set
= get_image_set (data
.images
, data
.nimages
);
2882 collect_data_free (&data
);
2884 gclass
= g_hash_table_lookup (set
->gclass_cache
, &helper
);
2886 /* A tripwire just to keep us honest */
2887 g_assert (!helper
.cached_class
);
2890 mono_loader_unlock ();
2895 MonoDynamicGenericClass
*dgclass
= g_new0 (MonoDynamicGenericClass
, 1);
2896 gclass
= &dgclass
->generic_class
;
2897 gclass
->is_dynamic
= 1;
2899 gclass
= g_new0 (MonoGenericClass
, 1);
2902 gclass
->is_tb_open
= is_tb_open
;
2903 gclass
->container_class
= container_class
;
2904 gclass
->context
.class_inst
= inst
;
2905 gclass
->context
.method_inst
= NULL
;
2906 if (inst
== container_class
->generic_container
->context
.class_inst
&& !is_tb_open
)
2907 gclass
->cached_class
= container_class
;
2909 g_hash_table_insert (set
->gclass_cache
, gclass
, gclass
);
2911 mono_loader_unlock ();
2917 * mono_metadata_inflate_generic_inst:
2919 * Instantiate the generic instance @ginst with the context @context.
2920 * Check @error for success.
2924 mono_metadata_inflate_generic_inst (MonoGenericInst
*ginst
, MonoGenericContext
*context
, MonoError
*error
)
2926 MonoType
**type_argv
;
2927 MonoGenericInst
*nginst
= NULL
;
2930 mono_error_init (error
);
2932 if (!ginst
->is_open
)
2935 type_argv
= g_new0 (MonoType
*, ginst
->type_argc
);
2937 for (i
= 0; i
< ginst
->type_argc
; i
++) {
2938 type_argv
[i
] = mono_class_inflate_generic_type_checked (ginst
->type_argv
[i
], context
, error
);
2939 if (!mono_error_ok (error
))
2944 nginst
= mono_metadata_get_generic_inst (ginst
->type_argc
, type_argv
);
2947 for (i
= 0; i
< count
; i
++)
2948 mono_metadata_free_type (type_argv
[i
]);
2955 mono_metadata_parse_generic_inst (MonoImage
*m
, MonoGenericContainer
*container
,
2956 int count
, const char *ptr
, const char **rptr
)
2958 MonoType
**type_argv
;
2959 MonoGenericInst
*ginst
;
2962 type_argv
= g_new0 (MonoType
*, count
);
2964 for (i
= 0; i
< count
; i
++) {
2965 MonoType
*t
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
2976 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
2984 do_mono_metadata_parse_generic_class (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
2985 const char *ptr
, const char **rptr
)
2987 MonoGenericInst
*inst
;
2992 gtype
= mono_metadata_parse_type (m
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
2996 gklass
= mono_class_from_mono_type (gtype
);
2997 if (!gklass
->generic_container
)
3000 count
= mono_metadata_decode_value (ptr
, &ptr
);
3001 inst
= mono_metadata_parse_generic_inst (m
, container
, count
, ptr
, &ptr
);
3008 type
->data
.generic_class
= mono_metadata_lookup_generic_class (gklass
, inst
, FALSE
);
3014 * @gc: The generic container to normalize
3015 * @type: The kind of generic parameters the resulting generic-container should contain
3018 static MonoGenericContainer
*
3019 select_container (MonoGenericContainer
*gc
, MonoTypeEnum type
)
3021 gboolean is_var
= (type
== MONO_TYPE_VAR
);
3025 g_assert (is_var
|| type
== MONO_TYPE_MVAR
);
3028 if (gc
->is_method
|| gc
->parent
)
3030 * The current MonoGenericContainer is a generic method -> its `parent'
3031 * points to the containing class'es container.
3040 * mono_metadata_parse_generic_param:
3041 * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3042 * see mono_metadata_parse_type_full() for details.
3043 * Internal routine to parse a generic type parameter.
3044 * LOCKING: Acquires the loader lock
3046 static MonoGenericParam
*
3047 mono_metadata_parse_generic_param (MonoImage
*m
, MonoGenericContainer
*generic_container
,
3048 MonoTypeEnum type
, const char *ptr
, const char **rptr
)
3050 int index
= mono_metadata_decode_value (ptr
, &ptr
);
3054 generic_container
= select_container (generic_container
, type
);
3055 if (!generic_container
) {
3056 /* Create dummy MonoGenericParam */
3057 MonoGenericParam
*param
;
3059 param
= mono_image_alloc0 (m
, sizeof (MonoGenericParam
));
3066 if (index
>= generic_container
->type_argc
)
3069 return mono_generic_container_get_param (generic_container
, index
);
3073 * mono_metadata_get_shared_type:
3075 * Return a shared instance of TYPE, if available, NULL otherwise.
3076 * Shared MonoType instances help save memory. Their contents should not be modified
3077 * by the caller. They do not need to be freed as their lifetime is bound by either
3078 * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3079 * instance they are embedded in. If they are freed, they should be freed using
3080 * mono_metadata_free_type () instead of g_free ().
3083 mono_metadata_get_shared_type (MonoType
*type
)
3087 /* No need to use locking since nobody is modifying the hash table */
3088 if ((cached
= g_hash_table_lookup (type_cache
, type
)))
3091 switch (type
->type
){
3092 case MONO_TYPE_CLASS
:
3093 case MONO_TYPE_VALUETYPE
:
3094 if (type
== &type
->data
.klass
->byval_arg
)
3096 if (type
== &type
->data
.klass
->this_arg
)
3105 * do_mono_metadata_parse_type:
3106 * @type: MonoType to be filled in with the return value
3108 * @generic_context: generics_context
3109 * @transient: whenever to allocate data from the heap
3110 * @ptr: pointer to the encoded type
3111 * @rptr: pointer where the end of the encoded type is saved
3113 * Internal routine used to "fill" the contents of @type from an
3114 * allocated pointer. This is done this way to avoid doing too
3115 * many mini-allocations (particularly for the MonoFieldType which
3116 * most of the time is just a MonoType, but sometimes might be augmented).
3118 * This routine is used by mono_metadata_parse_type and
3119 * mono_metadata_parse_field_type
3121 * This extracts a Type as specified in Partition II (22.2.12)
3123 * Returns: FALSE if the type could not be loaded
3126 do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
3127 gboolean transient
, const char *ptr
, const char **rptr
)
3130 type
->type
= mono_metadata_decode_value (ptr
, &ptr
);
3132 switch (type
->type
){
3133 case MONO_TYPE_VOID
:
3134 case MONO_TYPE_BOOLEAN
:
3135 case MONO_TYPE_CHAR
:
3148 case MONO_TYPE_STRING
:
3149 case MONO_TYPE_OBJECT
:
3150 case MONO_TYPE_TYPEDBYREF
:
3152 case MONO_TYPE_VALUETYPE
:
3153 case MONO_TYPE_CLASS
: {
3155 token
= mono_metadata_parse_typedef_or_ref (m
, ptr
, &ptr
);
3156 type
->data
.klass
= mono_class_get (m
, token
);
3157 if (!type
->data
.klass
)
3161 case MONO_TYPE_SZARRAY
: {
3162 MonoType
*etype
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_MOD_TYPE
, 0, ptr
, &ptr
);
3165 type
->data
.klass
= mono_class_from_mono_type (etype
);
3166 if (!type
->data
.klass
)
3171 type
->data
.type
= mono_metadata_parse_type_internal (m
, container
, MONO_PARSE_MOD_TYPE
, 0, transient
, ptr
, &ptr
);
3172 if (!type
->data
.type
)
3175 case MONO_TYPE_FNPTR
:
3176 type
->data
.method
= mono_metadata_parse_method_signature_full (m
, container
, 0, ptr
, &ptr
);
3177 if (!type
->data
.method
)
3180 case MONO_TYPE_ARRAY
:
3181 type
->data
.array
= mono_metadata_parse_array_internal (m
, container
, transient
, ptr
, &ptr
);
3182 if (!type
->data
.array
)
3185 case MONO_TYPE_MVAR
:
3186 if (container
&& !container
->is_method
)
3189 type
->data
.generic_param
= mono_metadata_parse_generic_param (m
, container
, type
->type
, ptr
, &ptr
);
3190 if (!type
->data
.generic_param
)
3193 case MONO_TYPE_GENERICINST
:
3194 ok
= do_mono_metadata_parse_generic_class (type
, m
, container
, ptr
, &ptr
);
3197 g_warning ("type 0x%02x not handled in do_mono_metadata_parse_type on image %s", type
->type
, m
->name
);
3207 * mono_metadata_free_type:
3208 * @type: type to free
3210 * Free the memory allocated for type @type which is allocated on the heap.
3213 mono_metadata_free_type (MonoType
*type
)
3215 if (type
>= builtin_types
&& type
< builtin_types
+ NBUILTIN_TYPES ())
3218 switch (type
->type
){
3219 case MONO_TYPE_OBJECT
:
3220 case MONO_TYPE_STRING
:
3221 if (!type
->data
.klass
)
3224 case MONO_TYPE_CLASS
:
3225 case MONO_TYPE_VALUETYPE
:
3226 if (type
== &type
->data
.klass
->byval_arg
|| type
== &type
->data
.klass
->this_arg
)
3230 mono_metadata_free_type (type
->data
.type
);
3232 case MONO_TYPE_FNPTR
:
3233 mono_metadata_free_method_signature (type
->data
.method
);
3235 case MONO_TYPE_ARRAY
:
3236 mono_metadata_free_array (type
->data
.array
);
3245 hex_dump (const char *buffer
, int base
, int count
)
3247 int show_header
= 1;
3255 for (i
= 0; i
< count
; i
++){
3258 printf ("\n0x%08x: ", (unsigned char) base
+ i
);
3260 printf ("%02x ", (unsigned char) (buffer
[i
]));
3267 * @ptr: Points to the beginning of the Section Data (25.3)
3269 static MonoExceptionClause
*
3270 parse_section_data (MonoImage
*m
, int *num_clauses
, const unsigned char *ptr
)
3272 unsigned char sect_data_flags
;
3273 const unsigned char *sptr
;
3275 guint32 sect_data_len
;
3276 MonoExceptionClause
* clauses
= NULL
;
3279 /* align on 32-bit boundary */
3280 sptr
= ptr
= dword_align (ptr
);
3281 sect_data_flags
= *ptr
;
3284 is_fat
= sect_data_flags
& METHOD_HEADER_SECTION_FAT_FORMAT
;
3286 sect_data_len
= (ptr
[2] << 16) | (ptr
[1] << 8) | ptr
[0];
3289 sect_data_len
= ptr
[0];
3293 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
3294 hex_dump (sptr, 0, sect_data_len+8);
3295 g_print ("\nheader: ");
3296 hex_dump (sptr-4, 0, 4);
3300 if (sect_data_flags
& METHOD_HEADER_SECTION_EHTABLE
) {
3301 const unsigned char *p
= dword_align (ptr
);
3303 *num_clauses
= is_fat
? sect_data_len
/ 24: sect_data_len
/ 12;
3304 /* we could just store a pointer if we don't need to byteswap */
3305 clauses
= g_malloc0 (sizeof (MonoExceptionClause
) * (*num_clauses
));
3306 for (i
= 0; i
< *num_clauses
; ++i
) {
3307 MonoExceptionClause
*ec
= &clauses
[i
];
3310 ec
->flags
= read32 (p
);
3311 ec
->try_offset
= read32 (p
+ 4);
3312 ec
->try_len
= read32 (p
+ 8);
3313 ec
->handler_offset
= read32 (p
+ 12);
3314 ec
->handler_len
= read32 (p
+ 16);
3315 tof_value
= read32 (p
+ 20);
3318 ec
->flags
= read16 (p
);
3319 ec
->try_offset
= read16 (p
+ 2);
3320 ec
->try_len
= *(p
+ 4);
3321 ec
->handler_offset
= read16 (p
+ 5);
3322 ec
->handler_len
= *(p
+ 7);
3323 tof_value
= read32 (p
+ 8);
3326 if (ec
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
) {
3327 ec
->data
.filter_offset
= tof_value
;
3328 } else if (ec
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) {
3329 ec
->data
.catch_class
= tof_value
? mono_class_get (m
, tof_value
): 0;
3331 ec
->data
.catch_class
= NULL
;
3333 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
3337 if (sect_data_flags
& METHOD_HEADER_SECTION_MORE_SECTS
)
3338 ptr
+= sect_data_len
- 4; /* LAMESPEC: it seems the size includes the header */
3345 * mono_method_get_header_summary:
3346 * @method: The method to get the header.
3347 * @summary: Where to store the header
3350 * Returns: true if the header was properly decoded.
3353 mono_method_get_header_summary (MonoMethod
*method
, MonoMethodHeaderSummary
*summary
)
3359 unsigned char flags
, format
;
3362 /*Only the GMD has a pointer to the metadata.*/
3363 while (method
->is_inflated
)
3364 method
= ((MonoMethodInflated
*)method
)->declaring
;
3366 summary
->code_size
= 0;
3367 summary
->has_clauses
= FALSE
;
3369 /*FIXME extract this into a MACRO and share it with mono_method_get_header*/
3370 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
))
3373 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| method
->sre_method
) {
3374 MonoMethodHeader
*header
= ((MonoMethodWrapper
*)method
)->header
;
3377 summary
->code_size
= header
->code_size
;
3378 summary
->has_clauses
= header
->num_clauses
> 0;
3383 idx
= mono_metadata_token_index (method
->token
);
3384 img
= method
->klass
->image
;
3385 rva
= mono_metadata_decode_row_col (&img
->tables
[MONO_TABLE_METHOD
], idx
- 1, MONO_METHOD_RVA
);
3387 /*We must run the verifier since we'll be decoding it.*/
3388 if (!mono_verifier_verify_method_header (img
, rva
, NULL
))
3391 ptr
= mono_image_rva_map (img
, rva
);
3394 flags
= *(const unsigned char *)ptr
;
3395 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
3398 case METHOD_HEADER_TINY_FORMAT
:
3400 summary
->code_size
= flags
>> 2;
3402 case METHOD_HEADER_FAT_FORMAT
:
3403 fat_flags
= read16 (ptr
);
3405 summary
->code_size
= read32 (ptr
);
3406 if (fat_flags
& METHOD_HEADER_MORE_SECTS
)
3407 summary
->has_clauses
= TRUE
;
3416 * mono_metadata_parse_mh_full:
3417 * @m: metadata context
3418 * @generic_context: generics context
3419 * @ptr: pointer to the method header.
3421 * Decode the method header at @ptr, including pointer to the IL code,
3422 * info about local variables and optional exception tables.
3423 * This is a Mono runtime internal function.
3425 * LOCKING: Acquires the loader lock.
3427 * Returns: a transient MonoMethodHeader allocated from the heap.
3430 mono_metadata_parse_mh_full (MonoImage
*m
, MonoGenericContainer
*container
, const char *ptr
)
3432 MonoMethodHeader
*mh
;
3433 unsigned char flags
= *(const unsigned char *) ptr
;
3434 unsigned char format
= flags
& METHOD_HEADER_FORMAT_MASK
;
3436 guint32 local_var_sig_tok
, max_stack
, code_size
, init_locals
;
3437 const unsigned char *code
;
3438 MonoExceptionClause
* clauses
= NULL
;
3439 int hsize
, num_clauses
= 0;
3440 MonoTableInfo
*t
= &m
->tables
[MONO_TABLE_STANDALONESIG
];
3441 guint32 cols
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
3443 g_return_val_if_fail (ptr
!= NULL
, NULL
);
3446 case METHOD_HEADER_TINY_FORMAT
:
3447 mh
= g_malloc0 (MONO_SIZEOF_METHOD_HEADER
);
3450 mh
->is_transient
= TRUE
;
3451 local_var_sig_tok
= 0;
3452 mh
->code_size
= flags
>> 2;
3453 mh
->code
= (unsigned char*)ptr
;
3455 case METHOD_HEADER_FAT_FORMAT
:
3456 fat_flags
= read16 (ptr
);
3458 hsize
= (fat_flags
>> 12) & 0xf;
3459 max_stack
= read16 (ptr
);
3461 code_size
= read32 (ptr
);
3463 local_var_sig_tok
= read32 (ptr
);
3466 if (fat_flags
& METHOD_HEADER_INIT_LOCALS
)
3471 code
= (unsigned char*)ptr
;
3473 if (!(fat_flags
& METHOD_HEADER_MORE_SECTS
))
3477 * There are more sections
3479 ptr
= (char*)code
+ code_size
;
3485 if (local_var_sig_tok
) {
3486 int idx
= (local_var_sig_tok
& 0xffffff)-1;
3489 mono_metadata_decode_row (t
, idx
, cols
, 1);
3491 if (!mono_verifier_verify_standalone_signature (m
, cols
[MONO_STAND_ALONE_SIGNATURE
], NULL
))
3494 if (fat_flags
& METHOD_HEADER_MORE_SECTS
)
3495 clauses
= parse_section_data (m
, &num_clauses
, (const unsigned char*)ptr
);
3496 if (local_var_sig_tok
) {
3497 const char *locals_ptr
;
3498 int len
=0, i
, bsize
;
3500 locals_ptr
= mono_metadata_blob_heap (m
, cols
[MONO_STAND_ALONE_SIGNATURE
]);
3501 bsize
= mono_metadata_decode_blob_size (locals_ptr
, &locals_ptr
);
3502 if (*locals_ptr
!= 0x07)
3503 g_warning ("wrong signature for locals blob");
3505 len
= mono_metadata_decode_value (locals_ptr
, &locals_ptr
);
3506 mh
= g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ len
* sizeof (MonoType
*) + num_clauses
* sizeof (MonoExceptionClause
));
3507 mh
->num_locals
= len
;
3508 for (i
= 0; i
< len
; ++i
) {
3509 mh
->locals
[i
] = mono_metadata_parse_type_internal (m
, container
,
3510 MONO_PARSE_LOCAL
, 0, TRUE
, locals_ptr
, &locals_ptr
);
3511 if (!mh
->locals
[i
]) {
3518 mh
= g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ num_clauses
* sizeof (MonoExceptionClause
));
3521 mh
->code_size
= code_size
;
3522 mh
->max_stack
= max_stack
;
3523 mh
->is_transient
= TRUE
;
3524 mh
->init_locals
= init_locals
;
3526 MonoExceptionClause
* clausesp
= (MonoExceptionClause
*)&mh
->locals
[mh
->num_locals
];
3527 memcpy (clausesp
, clauses
, num_clauses
* sizeof (MonoExceptionClause
));
3529 mh
->clauses
= clausesp
;
3530 mh
->num_clauses
= num_clauses
;
3536 * mono_metadata_parse_mh:
3537 * @generic_context: generics context
3538 * @ptr: pointer to the method header.
3540 * Decode the method header at @ptr, including pointer to the IL code,
3541 * info about local variables and optional exception tables.
3542 * This is a Mono runtime internal function.
3544 * Returns: a MonoMethodHeader.
3547 mono_metadata_parse_mh (MonoImage
*m
, const char *ptr
)
3549 MonoMethodHeader
*res
;
3551 mono_loader_lock ();
3553 res
= mono_metadata_parse_mh_full (m
, NULL
, ptr
);
3555 mono_loader_unlock ();
3561 * mono_metadata_free_mh:
3562 * @mh: a method header
3564 * Free the memory allocated for the method header.
3567 mono_metadata_free_mh (MonoMethodHeader
*mh
)
3571 /* If it is not transient it means it's part of a wrapper method,
3572 * or a SRE-generated method, so the lifetime in that case is
3573 * dictated by the method's own lifetime
3575 if (mh
->is_transient
) {
3576 for (i
= 0; i
< mh
->num_locals
; ++i
)
3577 mono_metadata_free_type (mh
->locals
[i
]);
3583 * mono_method_header_get_code:
3584 * @header: a MonoMethodHeader pointer
3585 * @code_size: memory location for returning the code size
3586 * @max_stack: memory location for returning the max stack
3588 * Method header accessor to retreive info about the IL code properties:
3589 * a pointer to the IL code itself, the size of the code and the max number
3590 * of stack slots used by the code.
3592 * Returns: pointer to the IL code represented by the method header.
3594 const unsigned char*
3595 mono_method_header_get_code (MonoMethodHeader
*header
, guint32
* code_size
, guint32
* max_stack
)
3598 *code_size
= header
->code_size
;
3600 *max_stack
= header
->max_stack
;
3601 return header
->code
;
3605 * mono_method_header_get_locals:
3606 * @header: a MonoMethodHeader pointer
3607 * @num_locals: memory location for returning the number of local variables
3608 * @init_locals: memory location for returning the init_locals flag
3610 * Method header accessor to retreive info about the local variables:
3611 * an array of local types, the number of locals and whether the locals
3612 * are supposed to be initialized to 0 on method entry
3614 * Returns: pointer to an array of types of the local variables
3617 mono_method_header_get_locals (MonoMethodHeader
*header
, guint32
* num_locals
, gboolean
*init_locals
)
3620 *num_locals
= header
->num_locals
;
3622 *init_locals
= header
->init_locals
;
3623 return header
->locals
;
3627 * mono_method_header_get_num_clauses:
3628 * @header: a MonoMethodHeader pointer
3630 * Method header accessor to retreive the number of exception clauses.
3632 * Returns: the number of exception clauses present
3635 mono_method_header_get_num_clauses (MonoMethodHeader
*header
)
3637 return header
->num_clauses
;
3641 * mono_method_header_get_clauses:
3642 * @header: a MonoMethodHeader pointer
3643 * @method: MonoMethod the header belongs to
3644 * @iter: pointer to a iterator
3645 * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
3647 * Get the info about the exception clauses in the method. Set *iter to NULL to
3648 * initiate the iteration, then call the method repeatedly until it returns FALSE.
3649 * At each iteration, the structure pointed to by clause if filled with the
3650 * exception clause information.
3652 * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
3656 mono_method_header_get_clauses (MonoMethodHeader
*header
, MonoMethod
*method
, gpointer
*iter
, MonoExceptionClause
*clause
)
3658 MonoExceptionClause
*sc
;
3659 /* later we'll be able to use this interface to parse the clause info on demand,
3660 * without allocating anything.
3662 if (!iter
|| !header
->num_clauses
)
3665 *iter
= sc
= header
->clauses
;
3671 if (sc
< header
->clauses
+ header
->num_clauses
) {
3680 * mono_metadata_parse_field_type:
3681 * @m: metadata context to extract information from
3682 * @ptr: pointer to the field signature
3683 * @rptr: pointer updated to match the end of the decoded stream
3685 * Parses the field signature, and returns the type information for it.
3687 * Returns: The MonoType that was extracted from @ptr.
3690 mono_metadata_parse_field_type (MonoImage
*m
, short field_flags
, const char *ptr
, const char **rptr
)
3692 return mono_metadata_parse_type (m
, MONO_PARSE_FIELD
, field_flags
, ptr
, rptr
);
3696 * mono_metadata_parse_param:
3697 * @m: metadata context to extract information from
3698 * @ptr: pointer to the param signature
3699 * @rptr: pointer updated to match the end of the decoded stream
3701 * Parses the param signature, and returns the type information for it.
3703 * Returns: The MonoType that was extracted from @ptr.
3706 mono_metadata_parse_param (MonoImage
*m
, const char *ptr
, const char **rptr
)
3708 return mono_metadata_parse_type (m
, MONO_PARSE_PARAM
, 0, ptr
, rptr
);
3712 * mono_metadata_token_from_dor:
3713 * @dor_token: A TypeDefOrRef coded index
3715 * dor_token is a TypeDefOrRef coded index: it contains either
3716 * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
3717 * bits contain an index into the table.
3719 * Returns: an expanded token
3722 mono_metadata_token_from_dor (guint32 dor_index
)
3726 table
= dor_index
& 0x03;
3727 idx
= dor_index
>> 2;
3730 case 0: /* TypeDef */
3731 return MONO_TOKEN_TYPE_DEF
| idx
;
3732 case 1: /* TypeRef */
3733 return MONO_TOKEN_TYPE_REF
| idx
;
3734 case 2: /* TypeSpec */
3735 return MONO_TOKEN_TYPE_SPEC
| idx
;
3737 g_assert_not_reached ();
3744 * We use this to pass context information to the row locator
3747 int idx
; /* The index that we are trying to locate */
3748 int col_idx
; /* The index in the row where idx may be stored */
3749 MonoTableInfo
*t
; /* pointer to the table */
3754 * How the row locator works.
3759 * ___|___------> _______
3762 * A column in the rows of table A references an index in table B.
3763 * For example A may be the TYPEDEF table and B the METHODDEF table.
3765 * Given an index in table B we want to get the row in table A
3766 * where the column n references our index in B.
3768 * In the locator_t structure:
3770 * col_idx is the column number
3771 * index is the index in table B
3772 * result will be the index in table A
3775 * Table A Table B column (in table A)
3776 * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
3777 * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
3778 * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
3779 * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
3780 * METHODSEM PROPERTY ASSOCIATION (encoded index)
3782 * Note that we still don't support encoded indexes.
3786 typedef_locator (const void *a
, const void *b
)
3788 locator_t
*loc
= (locator_t
*) a
;
3789 const char *bb
= (const char *) b
;
3790 int typedef_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3791 guint32 col
, col_next
;
3793 col
= mono_metadata_decode_row_col (loc
->t
, typedef_index
, loc
->col_idx
);
3799 * Need to check that the next row is valid.
3801 if (typedef_index
+ 1 < loc
->t
->rows
) {
3802 col_next
= mono_metadata_decode_row_col (loc
->t
, typedef_index
+ 1, loc
->col_idx
);
3803 if (loc
->idx
>= col_next
)
3806 if (col
== col_next
)
3810 loc
->result
= typedef_index
;
3816 table_locator (const void *a
, const void *b
)
3818 locator_t
*loc
= (locator_t
*) a
;
3819 const char *bb
= (const char *) b
;
3820 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3823 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
3825 if (loc
->idx
== col
) {
3826 loc
->result
= table_index
;
3836 declsec_locator (const void *a
, const void *b
)
3838 locator_t
*loc
= (locator_t
*) a
;
3839 const char *bb
= (const char *) b
;
3840 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3843 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
3845 if (loc
->idx
== col
) {
3846 loc
->result
= table_index
;
3858 * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
3859 * which contains IDX.
3862 search_ptr_table (MonoImage
*image
, int table
, int idx
)
3864 MonoTableInfo
*ptrdef
= &image
->tables
[table
];
3867 /* Use a linear search to find our index in the table */
3868 for (i
= 0; i
< ptrdef
->rows
; i
++)
3869 /* All the Ptr tables have the same structure */
3870 if (mono_metadata_decode_row_col (ptrdef
, i
, 0) == idx
)
3873 if (i
< ptrdef
->rows
)
3880 * mono_metadata_typedef_from_field:
3881 * @meta: metadata context
3882 * @index: FieldDef token
3884 * Returns: the 1-based index into the TypeDef table of the type that
3885 * declared the field described by @index, or 0 if not found.
3888 mono_metadata_typedef_from_field (MonoImage
*meta
, guint32 index
)
3890 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
3896 loc
.idx
= mono_metadata_token_index (index
);
3897 loc
.col_idx
= MONO_TYPEDEF_FIELD_LIST
;
3900 if (meta
->uncompressed_metadata
)
3901 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
3903 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
3906 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3907 return loc
.result
+ 1;
3911 * mono_metadata_typedef_from_method:
3912 * @meta: metadata context
3913 * @index: MethodDef token
3915 * Returns: the 1-based index into the TypeDef table of the type that
3916 * declared the method described by @index. 0 if not found.
3919 mono_metadata_typedef_from_method (MonoImage
*meta
, guint32 index
)
3921 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
3927 loc
.idx
= mono_metadata_token_index (index
);
3928 loc
.col_idx
= MONO_TYPEDEF_METHOD_LIST
;
3931 if (meta
->uncompressed_metadata
)
3932 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_METHOD_POINTER
, loc
.idx
);
3934 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
3937 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3938 return loc
.result
+ 1;
3942 * mono_metadata_interfaces_from_typedef_full:
3943 * @meta: metadata context
3944 * @index: typedef token
3945 * @interfaces: Out parameter used to store the interface array
3946 * @count: Out parameter used to store the number of interfaces
3947 * @heap_alloc_result: if TRUE the result array will be g_malloc'd
3948 * @context: The generic context
3950 * The array of interfaces that the @index typedef token implements is returned in
3951 * @interfaces. The number of elements in the array is returned in @count.
3953 * LOCKING: Assumes the loader lock is held.
3955 * Returns: TRUE on success, FALSE on failure.
3958 mono_metadata_interfaces_from_typedef_full (MonoImage
*meta
, guint32 index
, MonoClass
***interfaces
, guint
*count
, gboolean heap_alloc_result
, MonoGenericContext
*context
)
3960 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_INTERFACEIMPL
];
3963 guint32 cols
[MONO_INTERFACEIMPL_SIZE
];
3972 loc
.idx
= mono_metadata_token_index (index
);
3973 loc
.col_idx
= MONO_INTERFACEIMPL_CLASS
;
3976 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
3981 * We may end up in the middle of the rows...
3984 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_INTERFACEIMPL_CLASS
))
3990 while (pos
< tdef
->rows
) {
3991 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
3992 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
3997 if (heap_alloc_result
)
3998 result
= g_new0 (MonoClass
*, pos
- start
);
4000 result
= mono_image_alloc0 (meta
, sizeof (MonoClass
*) * (pos
- start
));
4003 while (pos
< tdef
->rows
) {
4006 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
4007 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
4009 iface
= mono_class_get_full (
4010 meta
, mono_metadata_token_from_dor (cols
[MONO_INTERFACEIMPL_INTERFACE
]), context
);
4013 result
[pos
- start
] = iface
;
4016 *count
= pos
- start
;
4017 *interfaces
= result
;
4022 * @meta: metadata context
4023 * @index: typedef token
4024 * @count: Out parameter used to store the number of interfaces
4026 * The array of interfaces that the @index typedef token implements is returned in
4027 * @interfaces. The number of elements in the array is returned in @count. The returned
4028 * array is g_malloc'd and the caller must free it.
4030 * LOCKING: Acquires the loader lock .
4032 * Returns: the interface array on success, NULL on failure.
4036 mono_metadata_interfaces_from_typedef (MonoImage
*meta
, guint32 index
, guint
*count
)
4038 MonoClass
**interfaces
;
4041 mono_loader_lock ();
4042 rv
= mono_metadata_interfaces_from_typedef_full (meta
, index
, &interfaces
, count
, TRUE
, NULL
);
4043 mono_loader_unlock ();
4051 * mono_metadata_nested_in_typedef:
4052 * @meta: metadata context
4053 * @index: typedef token
4055 * Returns: the 1-based index into the TypeDef table of the type
4056 * where the type described by @index is nested.
4057 * Retruns 0 if @index describes a non-nested type.
4060 mono_metadata_nested_in_typedef (MonoImage
*meta
, guint32 index
)
4062 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4068 loc
.idx
= mono_metadata_token_index (index
);
4069 loc
.col_idx
= MONO_NESTED_CLASS_NESTED
;
4072 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4075 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4076 return mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_NESTED_CLASS_ENCLOSING
) | MONO_TOKEN_TYPE_DEF
;
4080 * mono_metadata_nesting_typedef:
4081 * @meta: metadata context
4082 * @index: typedef token
4084 * Returns: the 1-based index into the TypeDef table of the first type
4085 * that is nested inside the type described by @index. The search starts at
4086 * @start_index. returns 0 if no such type is found.
4089 mono_metadata_nesting_typedef (MonoImage
*meta
, guint32 index
, guint32 start_index
)
4091 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4093 guint32 class_index
= mono_metadata_token_index (index
);
4098 start
= start_index
;
4100 while (start
<= tdef
->rows
) {
4101 if (class_index
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_NESTED_CLASS_ENCLOSING
))
4107 if (start
> tdef
->rows
)
4114 * mono_metadata_packing_from_typedef:
4115 * @meta: metadata context
4116 * @index: token representing a type
4118 * Returns: the info stored in the ClassLAyout table for the given typedef token
4119 * into the @packing and @size pointers.
4120 * Returns 0 if the info is not found.
4123 mono_metadata_packing_from_typedef (MonoImage
*meta
, guint32 index
, guint32
*packing
, guint32
*size
)
4125 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CLASSLAYOUT
];
4127 guint32 cols
[MONO_CLASS_LAYOUT_SIZE
];
4132 loc
.idx
= mono_metadata_token_index (index
);
4133 loc
.col_idx
= MONO_CLASS_LAYOUT_PARENT
;
4136 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4139 mono_metadata_decode_row (tdef
, loc
.result
, cols
, MONO_CLASS_LAYOUT_SIZE
);
4141 *packing
= cols
[MONO_CLASS_LAYOUT_PACKING_SIZE
];
4143 *size
= cols
[MONO_CLASS_LAYOUT_CLASS_SIZE
];
4145 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4146 return loc
.result
+ 1;
4150 * mono_metadata_custom_attrs_from_index:
4151 * @meta: metadata context
4152 * @index: token representing the parent
4154 * Returns: the 1-based index into the CustomAttribute table of the first
4155 * attribute which belongs to the metadata object described by @index.
4156 * Returns 0 if no such attribute is found.
4159 mono_metadata_custom_attrs_from_index (MonoImage
*meta
, guint32 index
)
4161 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4168 loc
.col_idx
= MONO_CUSTOM_ATTR_PARENT
;
4171 /* FIXME: Index translation */
4173 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4176 /* Find the first entry by searching backwards */
4177 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_CUSTOM_ATTR_PARENT
) == index
))
4180 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4181 return loc
.result
+ 1;
4185 * mono_metadata_declsec_from_index:
4186 * @meta: metadata context
4187 * @index: token representing the parent
4189 * Returns: the 0-based index into the DeclarativeSecurity table of the first
4190 * attribute which belongs to the metadata object described by @index.
4191 * Returns -1 if no such attribute is found.
4194 mono_metadata_declsec_from_index (MonoImage
*meta
, guint32 index
)
4196 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_DECLSECURITY
];
4203 loc
.col_idx
= MONO_DECL_SECURITY_PARENT
;
4206 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, declsec_locator
))
4209 /* Find the first entry by searching backwards */
4210 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_DECL_SECURITY_PARENT
) == index
))
4218 mono_backtrace (int limit
)
4223 backtrace (array
, limit
);
4224 names
= backtrace_symbols (array
, limit
);
4225 for (i
=0; i
< limit
; ++i
) {
4226 g_print ("\t%s\n", names
[i
]);
4233 /*#define __alignof__(a) sizeof(a)*/
4234 #define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
4239 * @t: the type to return the size of
4241 * Returns: the number of bytes required to hold an instance of this
4245 mono_type_size (MonoType
*t
, int *align
)
4252 *align
= __alignof__(gpointer
);
4253 return sizeof (gpointer
);
4257 case MONO_TYPE_VOID
:
4260 case MONO_TYPE_BOOLEAN
:
4261 *align
= __alignof__(gint8
);
4265 *align
= __alignof__(gint8
);
4267 case MONO_TYPE_CHAR
:
4270 *align
= __alignof__(gint16
);
4274 *align
= __alignof__(gint32
);
4277 *align
= __alignof__(float);
4281 *align
= __alignof__(gint64
);
4284 *align
= __alignof__(double);
4288 *align
= __alignof__(gpointer
);
4289 return sizeof (gpointer
);
4290 case MONO_TYPE_STRING
:
4291 *align
= __alignof__(gpointer
);
4292 return sizeof (gpointer
);
4293 case MONO_TYPE_OBJECT
:
4294 *align
= __alignof__(gpointer
);
4295 return sizeof (gpointer
);
4296 case MONO_TYPE_VALUETYPE
: {
4297 if (t
->data
.klass
->enumtype
)
4298 return mono_type_size (mono_class_enum_basetype (t
->data
.klass
), align
);
4300 return mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
4302 case MONO_TYPE_CLASS
:
4303 case MONO_TYPE_SZARRAY
:
4305 case MONO_TYPE_FNPTR
:
4306 case MONO_TYPE_ARRAY
:
4307 *align
= __alignof__(gpointer
);
4308 return sizeof (gpointer
);
4309 case MONO_TYPE_TYPEDBYREF
:
4310 return mono_class_value_size (mono_defaults
.typed_reference_class
, (guint32
*)align
);
4311 case MONO_TYPE_GENERICINST
: {
4312 MonoGenericClass
*gclass
= t
->data
.generic_class
;
4313 MonoClass
*container_class
= gclass
->container_class
;
4315 // g_assert (!gclass->inst->is_open);
4317 if (container_class
->valuetype
) {
4318 if (container_class
->enumtype
)
4319 return mono_type_size (mono_class_enum_basetype (container_class
), align
);
4321 return mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
4323 *align
= __alignof__(gpointer
);
4324 return sizeof (gpointer
);
4328 case MONO_TYPE_MVAR
:
4329 /* FIXME: Martin, this is wrong. */
4330 *align
= __alignof__(gpointer
);
4331 return sizeof (gpointer
);
4333 g_error ("mono_type_size: type 0x%02x unknown", t
->type
);
4339 * mono_type_stack_size:
4340 * @t: the type to return the size it uses on the stack
4342 * Returns: the number of bytes required to hold an instance of this
4343 * type on the runtime stack
4346 mono_type_stack_size (MonoType
*t
, int *align
)
4348 return mono_type_stack_size_internal (t
, align
, FALSE
);
4352 mono_type_stack_size_internal (MonoType
*t
, int *align
, gboolean allow_open
)
4355 #if SIZEOF_VOID_P == SIZEOF_REGISTER
4356 int stack_slot_size
= sizeof (gpointer
);
4357 int stack_slot_align
= __alignof__ (gpointer
);
4358 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
4359 int stack_slot_size
= SIZEOF_REGISTER
;
4360 int stack_slot_align
= SIZEOF_REGISTER
;
4363 g_assert (t
!= NULL
);
4369 *align
= stack_slot_align
;
4370 return stack_slot_size
;
4374 case MONO_TYPE_BOOLEAN
:
4375 case MONO_TYPE_CHAR
:
4384 case MONO_TYPE_STRING
:
4385 case MONO_TYPE_OBJECT
:
4386 case MONO_TYPE_CLASS
:
4387 case MONO_TYPE_SZARRAY
:
4389 case MONO_TYPE_FNPTR
:
4390 case MONO_TYPE_ARRAY
:
4391 *align
= stack_slot_align
;
4392 return stack_slot_size
;
4394 case MONO_TYPE_MVAR
:
4395 g_assert (allow_open
);
4396 *align
= stack_slot_align
;
4397 return stack_slot_size
;
4398 case MONO_TYPE_TYPEDBYREF
:
4399 *align
= stack_slot_align
;
4400 return stack_slot_size
* 3;
4402 *align
= __alignof__(float);
4403 return sizeof (float);
4406 *align
= __alignof__(gint64
);
4407 return sizeof (gint64
);
4409 *align
= __alignof__(double);
4410 return sizeof (double);
4411 case MONO_TYPE_VALUETYPE
: {
4414 if (t
->data
.klass
->enumtype
)
4415 return mono_type_stack_size_internal (mono_class_enum_basetype (t
->data
.klass
), align
, allow_open
);
4417 size
= mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
4419 *align
= *align
+ stack_slot_align
- 1;
4420 *align
&= ~(stack_slot_align
- 1);
4422 size
+= stack_slot_size
- 1;
4423 size
&= ~(stack_slot_size
- 1);
4428 case MONO_TYPE_GENERICINST
: {
4429 MonoGenericClass
*gclass
= t
->data
.generic_class
;
4430 MonoClass
*container_class
= gclass
->container_class
;
4433 g_assert (!gclass
->context
.class_inst
->is_open
);
4435 if (container_class
->valuetype
) {
4436 if (container_class
->enumtype
)
4437 return mono_type_stack_size_internal (mono_class_enum_basetype (container_class
), align
, allow_open
);
4439 guint32 size
= mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
4441 *align
= *align
+ stack_slot_align
- 1;
4442 *align
&= ~(stack_slot_align
- 1);
4444 size
+= stack_slot_size
- 1;
4445 size
&= ~(stack_slot_size
- 1);
4450 *align
= stack_slot_align
;
4451 return stack_slot_size
;
4455 g_error ("type 0x%02x unknown", t
->type
);
4461 mono_type_generic_inst_is_valuetype (MonoType
*type
)
4463 g_assert (type
->type
== MONO_TYPE_GENERICINST
);
4464 return type
->data
.generic_class
->container_class
->valuetype
;
4468 mono_metadata_generic_class_is_valuetype (MonoGenericClass
*gclass
)
4470 return gclass
->container_class
->valuetype
;
4474 _mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
, gboolean signature_only
)
4476 MonoGenericInst
*i1
= g1
->context
.class_inst
;
4477 MonoGenericInst
*i2
= g2
->context
.class_inst
;
4479 if (g1
->is_dynamic
!= g2
->is_dynamic
)
4481 if (!mono_metadata_class_equal (g1
->container_class
, g2
->container_class
, signature_only
))
4483 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
4485 return g1
->is_tb_open
== g2
->is_tb_open
;
4489 _mono_metadata_generic_class_container_equal (const MonoGenericClass
*g1
, MonoClass
*c2
, gboolean signature_only
)
4491 MonoGenericInst
*i1
= g1
->context
.class_inst
;
4492 MonoGenericInst
*i2
= c2
->generic_container
->context
.class_inst
;
4494 if (!mono_metadata_class_equal (g1
->container_class
, c2
, signature_only
))
4496 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
4498 return !g1
->is_tb_open
;
4502 mono_metadata_generic_context_hash (const MonoGenericContext
*context
)
4504 /* FIXME: check if this seed is good enough */
4505 guint hash
= 0xc01dfee7;
4506 if (context
->class_inst
)
4507 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->class_inst
);
4508 if (context
->method_inst
)
4509 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->method_inst
);
4514 mono_metadata_generic_context_equal (const MonoGenericContext
*g1
, const MonoGenericContext
*g2
)
4516 return g1
->class_inst
== g2
->class_inst
&& g1
->method_inst
== g2
->method_inst
;
4520 * mono_metadata_str_hash:
4522 * This should be used instead of g_str_hash for computing hash codes visible
4523 * outside this module, since g_str_hash () is not guaranteed to be stable
4524 * (its not the same in eglib for example).
4527 mono_metadata_str_hash (gconstpointer v1
)
4529 /* Same as g_str_hash () in glib */
4530 char *p
= (char *) v1
;
4535 hash
= (hash
<< 5) - hash
+ *p
;
4542 * mono_metadata_type_hash:
4545 * Computes an hash value for @t1 to be used in GHashTable.
4546 * The returned hash is guaranteed to be the same across executions.
4549 mono_metadata_type_hash (MonoType
*t1
)
4551 guint hash
= t1
->type
;
4553 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
4555 case MONO_TYPE_VALUETYPE
:
4556 case MONO_TYPE_CLASS
:
4557 case MONO_TYPE_SZARRAY
: {
4558 MonoClass
*class = t1
->data
.klass
;
4560 * Dynamic classes must not be hashed on their type since it can change
4561 * during runtime. For example, if we hash a reference type that is
4562 * later made into a valuetype.
4564 * This is specially problematic with generic instances since they are
4565 * inserted in a bunch of hash tables before been finished.
4567 if (class->image
->dynamic
)
4568 return (t1
->byref
<< 6) | mono_metadata_str_hash (class->name
);
4569 return ((hash
<< 5) - hash
) ^ mono_metadata_str_hash (class->name
);
4572 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (t1
->data
.type
);
4573 case MONO_TYPE_ARRAY
:
4574 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (&t1
->data
.array
->eklass
->byval_arg
);
4575 case MONO_TYPE_GENERICINST
:
4576 return ((hash
<< 5) - hash
) ^ mono_generic_class_hash (t1
->data
.generic_class
);
4582 mono_metadata_generic_param_equal (MonoGenericParam
*p1
, MonoGenericParam
*p2
, gboolean signature_only
)
4586 if (mono_generic_param_num (p1
) != mono_generic_param_num (p2
))
4590 * We have to compare the image as well because if we didn't,
4591 * the generic_inst_cache lookup wouldn't care about the image
4592 * of generic params, so what could happen is that a generic
4593 * inst with params from image A is put into the cache, then
4594 * image B gets that generic inst from the cache, image A is
4595 * unloaded, so the inst is deleted, but image B still retains
4598 * The AOT runtime doesn't set the image when it's decoding
4599 * types, so we only compare it when the owner is NULL.
4601 if (mono_generic_param_owner (p1
) == mono_generic_param_owner (p2
) &&
4602 (mono_generic_param_owner (p1
) || p1
->image
== p2
->image
))
4606 * If `signature_only' is true, we're comparing two (method) signatures.
4607 * In this case, the owner of two type parameters doesn't need to match.
4610 return signature_only
;
4614 mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
)
4618 if (c1
->generic_class
&& c2
->generic_class
)
4619 return _mono_metadata_generic_class_equal (c1
->generic_class
, c2
->generic_class
, signature_only
);
4620 if (c1
->generic_class
&& c2
->generic_container
)
4621 return _mono_metadata_generic_class_container_equal (c1
->generic_class
, c2
, signature_only
);
4622 if (c1
->generic_container
&& c2
->generic_class
)
4623 return _mono_metadata_generic_class_container_equal (c2
->generic_class
, c1
, signature_only
);
4624 if ((c1
->byval_arg
.type
== MONO_TYPE_VAR
) && (c2
->byval_arg
.type
== MONO_TYPE_VAR
))
4625 return mono_metadata_generic_param_equal (
4626 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
4627 if ((c1
->byval_arg
.type
== MONO_TYPE_MVAR
) && (c2
->byval_arg
.type
== MONO_TYPE_MVAR
))
4628 return mono_metadata_generic_param_equal (
4629 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
4630 if (signature_only
&&
4631 (c1
->byval_arg
.type
== MONO_TYPE_SZARRAY
) && (c2
->byval_arg
.type
== MONO_TYPE_SZARRAY
))
4632 return mono_metadata_class_equal (c1
->byval_arg
.data
.klass
, c2
->byval_arg
.data
.klass
, signature_only
);
4637 mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
)
4639 gpointer iter1
= 0, iter2
= 0;
4643 if (s1
->call_convention
!= s2
->call_convention
)
4645 if (s1
->sentinelpos
!= s2
->sentinelpos
)
4647 if (s1
->hasthis
!= s2
->hasthis
)
4649 if (s1
->explicit_this
!= s2
->explicit_this
)
4651 if (! do_mono_metadata_type_equal (s1
->ret
, s2
->ret
, signature_only
))
4653 if (s1
->param_count
!= s2
->param_count
)
4657 MonoType
*t1
= mono_signature_get_params (s1
, &iter1
);
4658 MonoType
*t2
= mono_signature_get_params (s2
, &iter2
);
4660 if (t1
== NULL
|| t2
== NULL
)
4662 if (! do_mono_metadata_type_equal (t1
, t2
, signature_only
))
4668 * mono_metadata_type_equal:
4672 * Determine if @t1 and @t2 represent the same type.
4673 * Returns: #TRUE if @t1 and @t2 are equal.
4676 do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
4678 if (t1
->type
!= t2
->type
|| t1
->byref
!= t2
->byref
)
4682 case MONO_TYPE_VOID
:
4683 case MONO_TYPE_BOOLEAN
:
4684 case MONO_TYPE_CHAR
:
4695 case MONO_TYPE_STRING
:
4698 case MONO_TYPE_OBJECT
:
4699 case MONO_TYPE_TYPEDBYREF
:
4701 case MONO_TYPE_VALUETYPE
:
4702 case MONO_TYPE_CLASS
:
4703 case MONO_TYPE_SZARRAY
:
4704 return mono_metadata_class_equal (t1
->data
.klass
, t2
->data
.klass
, signature_only
);
4706 return do_mono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
, signature_only
);
4707 case MONO_TYPE_ARRAY
:
4708 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
4710 return mono_metadata_class_equal (t1
->data
.array
->eklass
, t2
->data
.array
->eklass
, signature_only
);
4711 case MONO_TYPE_GENERICINST
:
4712 return _mono_metadata_generic_class_equal (
4713 t1
->data
.generic_class
, t2
->data
.generic_class
, signature_only
);
4715 return mono_metadata_generic_param_equal (
4716 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
4717 case MONO_TYPE_MVAR
:
4718 return mono_metadata_generic_param_equal (
4719 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
4720 case MONO_TYPE_FNPTR
:
4721 return mono_metadata_fnptr_equal (t1
->data
.method
, t2
->data
.method
, signature_only
);
4723 g_error ("implement type compare for %0x!", t1
->type
);
4731 mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
4733 return do_mono_metadata_type_equal (t1
, t2
, FALSE
);
4737 * mono_metadata_type_equal_full:
4740 * @signature_only: if signature only comparison should be made
4742 * Determine if @t1 and @t2 are signature compatible if @signature_only is #TRUE, otherwise
4743 * behaves the same way as mono_metadata_type_equal.
4744 * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
4745 * Returns: #TRUE if @t1 and @t2 are equal taking @signature_only into account.
4748 mono_metadata_type_equal_full (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
4750 return do_mono_metadata_type_equal (t1
, t2
, signature_only
);
4754 * mono_metadata_signature_equal:
4755 * @sig1: a signature
4756 * @sig2: another signature
4758 * Determine if @sig1 and @sig2 represent the same signature, with the
4759 * same number of arguments and the same types.
4760 * Returns: #TRUE if @sig1 and @sig2 are equal.
4763 mono_metadata_signature_equal (MonoMethodSignature
*sig1
, MonoMethodSignature
*sig2
)
4767 if (sig1
->hasthis
!= sig2
->hasthis
|| sig1
->param_count
!= sig2
->param_count
)
4770 if (sig1
->generic_param_count
!= sig2
->generic_param_count
)
4774 * We're just comparing the signatures of two methods here:
4776 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
4777 * U and V are equal here.
4779 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
4782 for (i
= 0; i
< sig1
->param_count
; i
++) {
4783 MonoType
*p1
= sig1
->params
[i
];
4784 MonoType
*p2
= sig2
->params
[i
];
4786 /* if (p1->attrs != p2->attrs)
4789 if (!do_mono_metadata_type_equal (p1
, p2
, TRUE
))
4793 if (!do_mono_metadata_type_equal (sig1
->ret
, sig2
->ret
, TRUE
))
4799 * mono_metadata_type_dup:
4800 * @image: image to alloc memory from
4801 * @original: type to duplicate
4803 * Returns: copy of type allocated from the image's mempool (or from the heap, if @image is null).
4806 mono_metadata_type_dup (MonoImage
*image
, const MonoType
*o
)
4809 int sizeof_o
= MONO_SIZEOF_TYPE
;
4811 sizeof_o
+= o
->num_mods
* sizeof (MonoCustomMod
);
4813 r
= image
? mono_image_alloc0 (image
, sizeof_o
) : g_malloc (sizeof_o
);
4815 memcpy (r
, o
, sizeof_o
);
4817 if (o
->type
== MONO_TYPE_PTR
) {
4818 r
->data
.type
= mono_metadata_type_dup (image
, o
->data
.type
);
4819 } else if (o
->type
== MONO_TYPE_ARRAY
) {
4820 r
->data
.array
= mono_dup_array_type (image
, o
->data
.array
);
4821 } else if (o
->type
== MONO_TYPE_FNPTR
) {
4822 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
4823 r
->data
.method
= mono_metadata_signature_deep_dup (image
, o
->data
.method
);
4829 mono_signature_hash (MonoMethodSignature
*sig
)
4831 guint i
, res
= sig
->ret
->type
;
4833 for (i
= 0; i
< sig
->param_count
; i
++)
4834 res
= (res
<< 5) - res
+ mono_type_hash (sig
->params
[i
]);
4840 * mono_metadata_encode_value:
4841 * @value: value to encode
4842 * @buf: buffer where to write the compressed representation
4843 * @endbuf: pointer updated to point at the end of the encoded output
4845 * Encodes the value @value in the compressed representation used
4846 * in metadata and stores the result in @buf. @buf needs to be big
4847 * enough to hold the data (4 bytes).
4850 mono_metadata_encode_value (guint32 value
, char *buf
, char **endbuf
)
4856 else if (value
< 0x4000) {
4857 p
[0] = 0x80 | (value
>> 8);
4858 p
[1] = value
& 0xff;
4861 p
[0] = (value
>> 24) | 0xc0;
4862 p
[1] = (value
>> 16) & 0xff;
4863 p
[2] = (value
>> 8) & 0xff;
4864 p
[3] = value
& 0xff;
4872 * mono_metadata_field_info:
4873 * @meta: the Image the field is defined in
4874 * @index: the index in the field table representing the field
4875 * @offset: a pointer to an integer where to store the offset that
4876 * may have been specified for the field in a FieldLayout table
4877 * @rva: a pointer to the RVA of the field data in the image that
4878 * may have been defined in a FieldRVA table
4879 * @marshal_spec: a pointer to the marshal spec that may have been
4880 * defined for the field in a FieldMarshal table.
4882 * Gather info for field @index that may have been defined in the FieldLayout,
4883 * FieldRVA and FieldMarshal tables.
4884 * Either of offset, rva and marshal_spec can be NULL if you're not interested
4888 mono_metadata_field_info (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
4889 MonoMarshalSpec
**marshal_spec
)
4891 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, FALSE
);
4895 mono_metadata_field_info_with_mempool (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
4896 MonoMarshalSpec
**marshal_spec
)
4898 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, TRUE
);
4902 mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
4903 MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
)
4905 MonoTableInfo
*tdef
;
4908 loc
.idx
= index
+ 1;
4909 if (meta
->uncompressed_metadata
)
4910 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
4913 tdef
= &meta
->tables
[MONO_TABLE_FIELDLAYOUT
];
4915 loc
.col_idx
= MONO_FIELD_LAYOUT_FIELD
;
4918 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4919 *offset
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_LAYOUT_OFFSET
);
4921 *offset
= (guint32
)-1;
4925 tdef
= &meta
->tables
[MONO_TABLE_FIELDRVA
];
4927 loc
.col_idx
= MONO_FIELD_RVA_FIELD
;
4930 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4932 * LAMESPEC: There is no signature, no nothing, just the raw data.
4934 *rva
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_RVA_RVA
);
4942 if ((p
= mono_metadata_get_marshal_info (meta
, index
, TRUE
))) {
4943 *marshal_spec
= mono_metadata_parse_marshal_spec_full (alloc_from_image
? meta
: NULL
, p
);
4950 * mono_metadata_get_constant_index:
4951 * @meta: the Image the field is defined in
4952 * @index: the token that may have a row defined in the constants table
4953 * @hint: possible position for the row
4955 * @token must be a FieldDef, ParamDef or PropertyDef token.
4957 * Returns: the index into the Constants table or 0 if not found.
4960 mono_metadata_get_constant_index (MonoImage
*meta
, guint32 token
, guint32 hint
)
4962 MonoTableInfo
*tdef
;
4964 guint32 index
= mono_metadata_token_index (token
);
4966 tdef
= &meta
->tables
[MONO_TABLE_CONSTANT
];
4967 index
<<= MONO_HASCONSTANT_BITS
;
4968 switch (mono_metadata_token_table (token
)) {
4969 case MONO_TABLE_FIELD
:
4970 index
|= MONO_HASCONSTANT_FIEDDEF
;
4972 case MONO_TABLE_PARAM
:
4973 index
|= MONO_HASCONSTANT_PARAM
;
4975 case MONO_TABLE_PROPERTY
:
4976 index
|= MONO_HASCONSTANT_PROPERTY
;
4979 g_warning ("Not a valid token for the constant table: 0x%08x", token
);
4983 loc
.col_idx
= MONO_CONSTANT_PARENT
;
4986 /* FIXME: Index translation */
4988 if ((hint
> 0) && (hint
< tdef
->rows
) && (mono_metadata_decode_row_col (tdef
, hint
- 1, MONO_CONSTANT_PARENT
) == index
))
4991 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4992 return loc
.result
+ 1;
4998 * mono_metadata_events_from_typedef:
4999 * @meta: metadata context
5000 * @index: 0-based index (in the TypeDef table) describing a type
5002 * Returns: the 0-based index in the Event table for the events in the
5003 * type. The last event that belongs to the type (plus 1) is stored
5004 * in the @end_idx pointer.
5007 mono_metadata_events_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5011 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_EVENTMAP
];
5019 loc
.col_idx
= MONO_EVENT_MAP_PARENT
;
5020 loc
.idx
= index
+ 1;
5022 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5025 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_EVENT_MAP_EVENTLIST
);
5026 if (loc
.result
+ 1 < tdef
->rows
) {
5027 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_EVENT_MAP_EVENTLIST
) - 1;
5029 end
= meta
->tables
[MONO_TABLE_EVENT
].rows
;
5037 * mono_metadata_methods_from_event:
5038 * @meta: metadata context
5039 * @index: 0-based index (in the Event table) describing a event
5041 * Returns: the 0-based index in the MethodDef table for the methods in the
5042 * event. The last method that belongs to the event (plus 1) is stored
5043 * in the @end_idx pointer.
5046 mono_metadata_methods_from_event (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5050 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
5051 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
5057 if (meta
->uncompressed_metadata
)
5058 index
= search_ptr_table (meta
, MONO_TABLE_EVENT_POINTER
, index
+ 1) - 1;
5061 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
5062 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
; /* Method association coded index */
5064 if (!bsearch (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
5069 * We may end up in the middle of the rows...
5072 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
5078 while (end
< msemt
->rows
) {
5079 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
5080 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
5089 * mono_metadata_properties_from_typedef:
5090 * @meta: metadata context
5091 * @index: 0-based index (in the TypeDef table) describing a type
5093 * Returns: the 0-based index in the Property table for the properties in the
5094 * type. The last property that belongs to the type (plus 1) is stored
5095 * in the @end_idx pointer.
5098 mono_metadata_properties_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5102 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_PROPERTYMAP
];
5110 loc
.col_idx
= MONO_PROPERTY_MAP_PARENT
;
5111 loc
.idx
= index
+ 1;
5113 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5116 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_PROPERTY_MAP_PROPERTY_LIST
);
5117 if (loc
.result
+ 1 < tdef
->rows
) {
5118 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_PROPERTY_MAP_PROPERTY_LIST
) - 1;
5120 end
= meta
->tables
[MONO_TABLE_PROPERTY
].rows
;
5128 * mono_metadata_methods_from_property:
5129 * @meta: metadata context
5130 * @index: 0-based index (in the PropertyDef table) describing a property
5132 * Returns: the 0-based index in the MethodDef table for the methods in the
5133 * property. The last method that belongs to the property (plus 1) is stored
5134 * in the @end_idx pointer.
5137 mono_metadata_methods_from_property (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5141 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
5142 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
5148 if (meta
->uncompressed_metadata
)
5149 index
= search_ptr_table (meta
, MONO_TABLE_PROPERTY_POINTER
, index
+ 1) - 1;
5152 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
5153 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
; /* Method association coded index */
5155 if (!bsearch (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
5160 * We may end up in the middle of the rows...
5163 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
5169 while (end
< msemt
->rows
) {
5170 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
5171 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
5180 mono_metadata_implmap_from_method (MonoImage
*meta
, guint32 method_idx
)
5183 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_IMPLMAP
];
5188 /* No index translation seems to be needed */
5191 loc
.col_idx
= MONO_IMPLMAP_MEMBER
;
5192 loc
.idx
= ((method_idx
+ 1) << MONO_MEMBERFORWD_BITS
) | MONO_MEMBERFORWD_METHODDEF
;
5194 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5197 return loc
.result
+ 1;
5201 * @image: context where the image is created
5202 * @type_spec: typespec token
5204 * Creates a MonoType representing the TypeSpec indexed by the @type_spec
5208 mono_type_create_from_typespec (MonoImage
*image
, guint32 type_spec
)
5210 guint32 idx
= mono_metadata_token_index (type_spec
);
5212 guint32 cols
[MONO_TYPESPEC_SIZE
];
5215 MonoType
*type
, *type2
;
5216 MonoType stack_type
;
5218 mono_loader_lock ();
5220 type
= g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
5222 mono_loader_unlock ();
5226 t
= &image
->tables
[MONO_TABLE_TYPESPEC
];
5228 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPESPEC_SIZE
);
5229 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_TYPESPEC_SIGNATURE
]);
5231 if (!mono_verifier_verify_typespec_signature (image
, cols
[MONO_TYPESPEC_SIGNATURE
], type_spec
, NULL
)) {
5232 mono_loader_unlock ();
5236 len
= mono_metadata_decode_value (ptr
, &ptr
);
5239 memset (type
, 0, MONO_SIZEOF_TYPE
);
5241 if (*ptr
== MONO_TYPE_BYREF
) {
5246 if (!do_mono_metadata_parse_type (type
, image
, NULL
, FALSE
, ptr
, &ptr
)) {
5247 mono_loader_unlock ();
5251 type2
= g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
5254 mono_loader_unlock ();
5258 type2
= mono_image_alloc (image
, MONO_SIZEOF_TYPE
);
5259 memcpy (type2
, type
, MONO_SIZEOF_TYPE
);
5260 g_hash_table_insert (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
), type2
);
5262 mono_loader_unlock ();
5269 mono_image_strndup (MonoImage
*image
, const char *data
, guint len
)
5273 return g_strndup (data
, len
);
5274 res
= mono_image_alloc (image
, len
+ 1);
5275 memcpy (res
, data
, len
);
5281 mono_metadata_parse_marshal_spec (MonoImage
*image
, const char *ptr
)
5283 return mono_metadata_parse_marshal_spec_full (NULL
, ptr
);
5287 mono_metadata_parse_marshal_spec_full (MonoImage
*image
, const char *ptr
)
5289 MonoMarshalSpec
*res
;
5291 const char *start
= ptr
;
5293 /* fixme: this is incomplete, but I cant find more infos in the specs */
5296 res
= mono_image_alloc0 (image
, sizeof (MonoMarshalSpec
));
5298 res
= g_new0 (MonoMarshalSpec
, 1);
5300 len
= mono_metadata_decode_value (ptr
, &ptr
);
5301 res
->native
= *ptr
++;
5303 if (res
->native
== MONO_NATIVE_LPARRAY
) {
5304 res
->data
.array_data
.param_num
= -1;
5305 res
->data
.array_data
.num_elem
= -1;
5306 res
->data
.array_data
.elem_mult
= -1;
5308 if (ptr
- start
<= len
)
5309 res
->data
.array_data
.elem_type
= *ptr
++;
5310 if (ptr
- start
<= len
)
5311 res
->data
.array_data
.param_num
= mono_metadata_decode_value (ptr
, &ptr
);
5312 if (ptr
- start
<= len
)
5313 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5314 if (ptr
- start
<= len
) {
5316 * LAMESPEC: Older spec versions say this parameter comes before
5317 * num_elem. Never spec versions don't talk about elem_mult at
5318 * all, but csc still emits it, and it is used to distinguish
5319 * between param_num being 0, and param_num being omitted.
5320 * So if (param_num == 0) && (num_elem > 0), then
5321 * elem_mult == 0 -> the array size is num_elem
5322 * elem_mult == 1 -> the array size is @param_num + num_elem
5324 res
->data
.array_data
.elem_mult
= mono_metadata_decode_value (ptr
, &ptr
);
5328 if (res
->native
== MONO_NATIVE_BYVALTSTR
) {
5329 if (ptr
- start
<= len
)
5330 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5333 if (res
->native
== MONO_NATIVE_BYVALARRAY
) {
5334 if (ptr
- start
<= len
)
5335 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5338 if (res
->native
== MONO_NATIVE_CUSTOM
) {
5339 /* skip unused type guid */
5340 len
= mono_metadata_decode_value (ptr
, &ptr
);
5342 /* skip unused native type name */
5343 len
= mono_metadata_decode_value (ptr
, &ptr
);
5345 /* read custom marshaler type name */
5346 len
= mono_metadata_decode_value (ptr
, &ptr
);
5347 res
->data
.custom_data
.custom_name
= mono_image_strndup (image
, ptr
, len
);
5349 /* read cookie string */
5350 len
= mono_metadata_decode_value (ptr
, &ptr
);
5351 res
->data
.custom_data
.cookie
= mono_image_strndup (image
, ptr
, len
);
5354 if (res
->native
== MONO_NATIVE_SAFEARRAY
) {
5355 res
->data
.safearray_data
.elem_type
= 0;
5356 res
->data
.safearray_data
.num_elem
= 0;
5357 if (ptr
- start
<= len
)
5358 res
->data
.safearray_data
.elem_type
= *ptr
++;
5359 if (ptr
- start
<= len
)
5360 res
->data
.safearray_data
.num_elem
= *ptr
++;
5366 mono_metadata_free_marshal_spec (MonoMarshalSpec
*spec
)
5368 if (spec
->native
== MONO_NATIVE_CUSTOM
) {
5369 g_free (spec
->data
.custom_data
.custom_name
);
5370 g_free (spec
->data
.custom_data
.cookie
);
5376 * mono_type_to_unmanaged:
5378 * Returns: A MonoMarshalNative enumeration value (MONO_NATIVE_) value
5379 * describing the underlying native reprensetation of the type.
5381 * In addition the value pointed by
5382 * "conv" will contain the kind of marshalling required for this
5383 * particular type one of the MONO_MARSHAL_CONV_ enumeration values.
5386 mono_type_to_unmanaged (MonoType
*type
, MonoMarshalSpec
*mspec
, gboolean as_field
,
5387 gboolean unicode
, MonoMarshalConv
*conv
)
5389 MonoMarshalConv dummy_conv
;
5395 *conv
= MONO_MARSHAL_CONV_NONE
;
5398 return MONO_NATIVE_UINT
;
5402 case MONO_TYPE_BOOLEAN
:
5404 switch (mspec
->native
) {
5405 case MONO_NATIVE_VARIANTBOOL
:
5406 *conv
= MONO_MARSHAL_CONV_BOOL_VARIANTBOOL
;
5407 return MONO_NATIVE_VARIANTBOOL
;
5408 case MONO_NATIVE_BOOLEAN
:
5409 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
5410 return MONO_NATIVE_BOOLEAN
;
5411 case MONO_NATIVE_I1
:
5412 case MONO_NATIVE_U1
:
5413 return mspec
->native
;
5415 g_error ("cant marshal bool to native type %02x", mspec
->native
);
5418 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
5419 return MONO_NATIVE_BOOLEAN
;
5420 case MONO_TYPE_CHAR
: return MONO_NATIVE_U2
;
5421 case MONO_TYPE_I1
: return MONO_NATIVE_I1
;
5422 case MONO_TYPE_U1
: return MONO_NATIVE_U1
;
5423 case MONO_TYPE_I2
: return MONO_NATIVE_I2
;
5424 case MONO_TYPE_U2
: return MONO_NATIVE_U2
;
5425 case MONO_TYPE_I4
: return MONO_NATIVE_I4
;
5426 case MONO_TYPE_U4
: return MONO_NATIVE_U4
;
5427 case MONO_TYPE_I8
: return MONO_NATIVE_I8
;
5428 case MONO_TYPE_U8
: return MONO_NATIVE_U8
;
5429 case MONO_TYPE_R4
: return MONO_NATIVE_R4
;
5430 case MONO_TYPE_R8
: return MONO_NATIVE_R8
;
5431 case MONO_TYPE_STRING
:
5433 switch (mspec
->native
) {
5434 case MONO_NATIVE_BSTR
:
5435 *conv
= MONO_MARSHAL_CONV_STR_BSTR
;
5436 return MONO_NATIVE_BSTR
;
5437 case MONO_NATIVE_LPSTR
:
5438 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
5439 return MONO_NATIVE_LPSTR
;
5440 case MONO_NATIVE_LPWSTR
:
5441 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
5442 return MONO_NATIVE_LPWSTR
;
5443 case MONO_NATIVE_LPTSTR
:
5444 *conv
= MONO_MARSHAL_CONV_STR_LPTSTR
;
5445 return MONO_NATIVE_LPTSTR
;
5446 case MONO_NATIVE_ANSIBSTR
:
5447 *conv
= MONO_MARSHAL_CONV_STR_ANSIBSTR
;
5448 return MONO_NATIVE_ANSIBSTR
;
5449 case MONO_NATIVE_TBSTR
:
5450 *conv
= MONO_MARSHAL_CONV_STR_TBSTR
;
5451 return MONO_NATIVE_TBSTR
;
5452 case MONO_NATIVE_BYVALTSTR
:
5454 *conv
= MONO_MARSHAL_CONV_STR_BYVALWSTR
;
5456 *conv
= MONO_MARSHAL_CONV_STR_BYVALSTR
;
5457 return MONO_NATIVE_BYVALTSTR
;
5459 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
);
5463 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
5464 return MONO_NATIVE_LPWSTR
;
5467 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
5468 return MONO_NATIVE_LPSTR
;
5470 case MONO_TYPE_PTR
: return MONO_NATIVE_UINT
;
5471 case MONO_TYPE_VALUETYPE
: /*FIXME*/
5472 if (type
->data
.klass
->enumtype
) {
5473 t
= mono_class_enum_basetype (type
->data
.klass
)->type
;
5476 if (type
->data
.klass
== mono_defaults
.handleref_class
){
5477 *conv
= MONO_MARSHAL_CONV_HANDLEREF
;
5478 return MONO_NATIVE_INT
;
5480 return MONO_NATIVE_STRUCT
;
5481 case MONO_TYPE_SZARRAY
:
5482 case MONO_TYPE_ARRAY
:
5484 switch (mspec
->native
) {
5485 case MONO_NATIVE_BYVALARRAY
:
5486 if ((type
->data
.klass
->element_class
== mono_defaults
.char_class
) && !unicode
)
5487 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY
;
5489 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALARRAY
;
5490 return MONO_NATIVE_BYVALARRAY
;
5491 case MONO_NATIVE_SAFEARRAY
:
5492 *conv
= MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
;
5493 return MONO_NATIVE_SAFEARRAY
;
5494 case MONO_NATIVE_LPARRAY
:
5495 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
5496 return MONO_NATIVE_LPARRAY
;
5498 g_error ("cant marshal array as native type %02x", mspec
->native
);
5502 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
5503 return MONO_NATIVE_LPARRAY
;
5504 case MONO_TYPE_I
: return MONO_NATIVE_INT
;
5505 case MONO_TYPE_U
: return MONO_NATIVE_UINT
;
5506 case MONO_TYPE_CLASS
:
5507 case MONO_TYPE_OBJECT
: {
5508 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
5510 switch (mspec
->native
) {
5511 case MONO_NATIVE_STRUCT
:
5512 return MONO_NATIVE_STRUCT
;
5513 case MONO_NATIVE_CUSTOM
:
5514 return MONO_NATIVE_CUSTOM
;
5515 case MONO_NATIVE_INTERFACE
:
5516 *conv
= MONO_MARSHAL_CONV_OBJECT_INTERFACE
;
5517 return MONO_NATIVE_INTERFACE
;
5518 case MONO_NATIVE_IDISPATCH
:
5519 *conv
= MONO_MARSHAL_CONV_OBJECT_IDISPATCH
;
5520 return MONO_NATIVE_IDISPATCH
;
5521 case MONO_NATIVE_IUNKNOWN
:
5522 *conv
= MONO_MARSHAL_CONV_OBJECT_IUNKNOWN
;
5523 return MONO_NATIVE_IUNKNOWN
;
5524 case MONO_NATIVE_FUNC
:
5525 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
5526 type
->data
.klass
== mono_defaults
.delegate_class
||
5527 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
5528 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
5529 return MONO_NATIVE_FUNC
;
5533 g_error ("cant marshal object as native type %02x", mspec
->native
);
5536 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
5537 type
->data
.klass
== mono_defaults
.delegate_class
||
5538 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
5539 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
5540 return MONO_NATIVE_FUNC
;
5542 if (mono_defaults
.safehandle_class
&& type
->data
.klass
== mono_defaults
.safehandle_class
){
5543 *conv
= MONO_MARSHAL_CONV_SAFEHANDLE
;
5544 return MONO_NATIVE_INT
;
5546 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
5547 return MONO_NATIVE_STRUCT
;
5549 case MONO_TYPE_FNPTR
: return MONO_NATIVE_FUNC
;
5550 case MONO_TYPE_GENERICINST
:
5551 type
= &type
->data
.generic_class
->container_class
->byval_arg
;
5554 case MONO_TYPE_TYPEDBYREF
:
5556 g_error ("type 0x%02x not handled in marshal", t
);
5558 return MONO_NATIVE_MAX
;
5562 mono_metadata_get_marshal_info (MonoImage
*meta
, guint32 idx
, gboolean is_field
)
5565 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_FIELDMARSHAL
];
5571 loc
.col_idx
= MONO_FIELD_MARSHAL_PARENT
;
5572 loc
.idx
= ((idx
+ 1) << MONO_HAS_FIELD_MARSHAL_BITS
) | (is_field
? MONO_HAS_FIELD_MARSHAL_FIELDSREF
: MONO_HAS_FIELD_MARSHAL_PARAMDEF
);
5574 /* FIXME: Index translation */
5576 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5579 return mono_metadata_blob_heap (meta
, mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_MARSHAL_NATIVE_TYPE
));
5583 method_from_method_def_or_ref (MonoImage
*m
, guint32 tok
, MonoGenericContext
*context
)
5585 guint32 idx
= tok
>> MONO_METHODDEFORREF_BITS
;
5587 switch (tok
& MONO_METHODDEFORREF_MASK
) {
5588 case MONO_METHODDEFORREF_METHODDEF
:
5589 return mono_get_method_full (m
, MONO_TOKEN_METHOD_DEF
| idx
, NULL
, context
);
5590 case MONO_METHODDEFORREF_METHODREF
:
5591 return mono_get_method_full (m
, MONO_TOKEN_MEMBER_REF
| idx
, NULL
, context
);
5593 g_assert_not_reached ();
5598 * mono_class_get_overrides_full:
5600 * Return the method overrides belonging to class @type_token in @overrides, and
5601 * the number of overrides in @num_overrides.
5603 * Returns: TRUE on success, FALSE on failure.
5606 mono_class_get_overrides_full (MonoImage
*image
, guint32 type_token
, MonoMethod
***overrides
, gint32
*num_overrides
,
5607 MonoGenericContext
*generic_context
)
5610 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_METHODIMPL
];
5613 guint32 cols
[MONO_METHODIMPL_SIZE
];
5614 MonoMethod
**result
;
5625 loc
.col_idx
= MONO_METHODIMPL_CLASS
;
5626 loc
.idx
= mono_metadata_token_index (type_token
);
5628 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5634 * We may end up in the middle of the rows...
5637 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_METHODIMPL_CLASS
))
5642 while (end
< tdef
->rows
) {
5643 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, end
, MONO_METHODIMPL_CLASS
))
5649 result
= g_new (MonoMethod
*, num
* 2);
5650 for (i
= 0; i
< num
; ++i
) {
5653 mono_metadata_decode_row (tdef
, start
+ i
, cols
, MONO_METHODIMPL_SIZE
);
5654 method
= method_from_method_def_or_ref (
5655 image
, cols
[MONO_METHODIMPL_DECLARATION
], generic_context
);
5658 result
[i
* 2] = method
;
5659 method
= method_from_method_def_or_ref (
5660 image
, cols
[MONO_METHODIMPL_BODY
], generic_context
);
5663 result
[i
* 2 + 1] = method
;
5666 *overrides
= result
;
5668 *num_overrides
= num
;
5673 * mono_guid_to_string:
5675 * Converts a 16 byte Microsoft GUID to the standard string representation.
5678 mono_guid_to_string (const guint8
*guid
)
5680 return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
5681 guid
[3], guid
[2], guid
[1], guid
[0],
5685 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
5689 get_constraints (MonoImage
*image
, int owner
, MonoClass
***constraints
, MonoGenericContainer
*container
)
5691 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
5692 guint32 cols
[MONO_GENPARCONSTRAINT_SIZE
];
5693 guint32 i
, token
, found
;
5694 MonoClass
*klass
, **res
;
5695 GSList
*cons
= NULL
, *tmp
;
5696 MonoGenericContext
*context
= &container
->context
;
5698 *constraints
= NULL
;
5700 for (i
= 0; i
< tdef
->rows
; ++i
) {
5701 mono_metadata_decode_row (tdef
, i
, cols
, MONO_GENPARCONSTRAINT_SIZE
);
5702 if (cols
[MONO_GENPARCONSTRAINT_GENERICPAR
] == owner
) {
5703 token
= mono_metadata_token_from_dor (cols
[MONO_GENPARCONSTRAINT_CONSTRAINT
]);
5704 klass
= mono_class_get_full (image
, token
, context
);
5706 g_slist_free (cons
);
5709 cons
= g_slist_append (cons
, klass
);
5712 /* contiguous list finished */
5719 res
= g_new0 (MonoClass
*, found
+ 1);
5720 for (i
= 0, tmp
= cons
; i
< found
; ++i
, tmp
= tmp
->next
) {
5721 res
[i
] = tmp
->data
;
5723 g_slist_free (cons
);
5729 * mono_metadata_get_generic_param_row:
5732 * @token: TypeOrMethodDef token, owner for GenericParam
5733 * @owner: coded token, set on return
5735 * Returns: 1-based row-id in the GenericParam table whose
5736 * owner is @token. 0 if not found.
5739 mono_metadata_get_generic_param_row (MonoImage
*image
, guint32 token
, guint32
*owner
)
5741 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
5748 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPEDEF
)
5749 *owner
= MONO_TYPEORMETHOD_TYPE
;
5750 else if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
5751 *owner
= MONO_TYPEORMETHOD_METHOD
;
5753 g_error ("wrong token %x to get_generic_param_row", token
);
5756 *owner
|= mono_metadata_token_index (token
) << MONO_TYPEORMETHOD_BITS
;
5759 loc
.col_idx
= MONO_GENERICPARAM_OWNER
;
5762 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5765 /* Find the first entry by searching backwards */
5766 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_GENERICPARAM_OWNER
) == loc
.idx
))
5769 return loc
.result
+ 1;
5773 mono_metadata_has_generic_params (MonoImage
*image
, guint32 token
)
5776 return mono_metadata_get_generic_param_row (image
, token
, &owner
);
5780 mono_metadata_load_generic_param_constraints_full (MonoImage
*image
, guint32 token
,
5781 MonoGenericContainer
*container
)
5784 guint32 start_row
, i
, owner
;
5785 if (! (start_row
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
5787 for (i
= 0; i
< container
->type_argc
; i
++) {
5788 if (!get_constraints (image
, start_row
+ i
, &mono_generic_container_get_param_info (container
, i
)->constraints
, container
))
5795 * mono_metadata_load_generic_param_constraints:
5797 * @image: metadata context
5798 * @token: metadata token to load the contraints, can be methodef or typedef.
5799 * @container: generic container to load into.
5801 * Load the generic parameter constraints for the newly created generic type or method
5802 * represented by @token and @container. The @container is the new container which has
5803 * been returned by a call to mono_metadata_load_generic_params() with this @token.
5806 mono_metadata_load_generic_param_constraints (MonoImage
*image
, guint32 token
,
5807 MonoGenericContainer
*container
)
5809 mono_metadata_load_generic_param_constraints_full (image
, token
, container
);
5810 /*FIXME this function can potentially exit with a pending loader error and cause all sort of havok */
5814 * mono_metadata_load_generic_params:
5816 * Load the type parameters from the type or method definition @token.
5818 * Use this method after parsing a type or method definition to figure out whether it's a generic
5819 * type / method. When parsing a method definition, @parent_container points to the generic container
5820 * of the current class, if any.
5822 * Note: This method does not load the constraints: for typedefs, this has to be done after fully
5823 * creating the type.
5825 * Returns: NULL if @token is not a generic type or method definition or the new generic container.
5827 * LOCKING: Acquires the loader lock
5830 MonoGenericContainer
*
5831 mono_metadata_load_generic_params (MonoImage
*image
, guint32 token
, MonoGenericContainer
*parent_container
)
5833 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
5834 guint32 cols
[MONO_GENERICPARAM_SIZE
];
5835 guint32 i
, owner
= 0, n
;
5836 MonoGenericContainer
*container
;
5837 MonoGenericParamFull
*params
;
5838 MonoGenericContext
*context
;
5840 if (!(i
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
5842 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
5845 container
= mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
5846 container
->image
= image
;
5849 params
= g_realloc (params
, sizeof (MonoGenericParamFull
) * n
);
5850 memset (¶ms
[n
- 1], 0, sizeof (MonoGenericParamFull
));
5851 params
[n
- 1].param
.owner
= container
;
5852 params
[n
- 1].param
.num
= cols
[MONO_GENERICPARAM_NUMBER
];
5853 params
[n
- 1].info
.token
= i
| MONO_TOKEN_GENERIC_PARAM
;
5854 params
[n
- 1].info
.flags
= cols
[MONO_GENERICPARAM_FLAGS
];
5855 params
[n
- 1].info
.name
= mono_metadata_string_heap (image
, cols
[MONO_GENERICPARAM_NAME
]);
5856 if (params
[n
- 1].param
.num
!= n
- 1)
5857 g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i
);
5858 if (++i
> tdef
->rows
)
5860 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
5861 } while (cols
[MONO_GENERICPARAM_OWNER
] == owner
);
5863 container
->type_argc
= n
;
5864 container
->type_params
= mono_image_alloc0 (image
, sizeof (MonoGenericParamFull
) * n
);
5865 memcpy (container
->type_params
, params
, sizeof (MonoGenericParamFull
) * n
);
5867 container
->parent
= parent_container
;
5869 if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
5870 container
->is_method
= 1;
5872 g_assert (container
->parent
== NULL
|| container
->is_method
);
5874 context
= &container
->context
;
5875 if (container
->is_method
) {
5876 context
->class_inst
= container
->parent
? container
->parent
->context
.class_inst
: NULL
;
5877 context
->method_inst
= mono_get_shared_generic_inst (container
);
5879 context
->class_inst
= mono_get_shared_generic_inst (container
);
5886 mono_get_shared_generic_inst (MonoGenericContainer
*container
)
5888 MonoType
**type_argv
;
5890 MonoGenericInst
*nginst
;
5893 type_argv
= g_new0 (MonoType
*, container
->type_argc
);
5894 helper
= g_new0 (MonoType
, container
->type_argc
);
5896 for (i
= 0; i
< container
->type_argc
; i
++) {
5897 MonoType
*t
= &helper
[i
];
5899 t
->type
= container
->is_method
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
5900 t
->data
.generic_param
= mono_generic_container_get_param (container
, i
);
5905 nginst
= mono_metadata_get_generic_inst (container
->type_argc
, type_argv
);
5914 * mono_type_is_byref:
5915 * @type: the MonoType operated on
5917 * Returns: #TRUE if @type represents a type passed by reference,
5921 mono_type_is_byref (MonoType
*type
)
5927 * mono_type_get_type:
5928 * @type: the MonoType operated on
5930 * Returns: the IL type value for @type. This is one of the MonoTypeEnum
5931 * enum members like MONO_TYPE_I4 or MONO_TYPE_STRING.
5934 mono_type_get_type (MonoType
*type
)
5940 * mono_type_get_signature:
5941 * @type: the MonoType operated on
5943 * It is only valid to call this function if @type is a MONO_TYPE_FNPTR.
5945 * Returns: the MonoMethodSignature pointer that describes the signature
5946 * of the function pointer @type represents.
5948 MonoMethodSignature
*
5949 mono_type_get_signature (MonoType
*type
)
5951 g_assert (type
->type
== MONO_TYPE_FNPTR
);
5952 return type
->data
.method
;
5956 * mono_type_get_class:
5957 * @type: the MonoType operated on
5959 * It is only valid to call this function if @type is a MONO_TYPE_CLASS or a
5960 * MONO_TYPE_VALUETYPE. For more general functionality, use mono_class_from_mono_type (),
5963 * Returns: the MonoClass pointer that describes the class that @type represents.
5966 mono_type_get_class (MonoType
*type
)
5968 /* FIXME: review the runtime users before adding the assert here */
5969 return type
->data
.klass
;
5973 * mono_type_get_array_type:
5974 * @type: the MonoType operated on
5976 * It is only valid to call this function if @type is a MONO_TYPE_ARRAY.
5978 * Returns: a MonoArrayType struct describing the array type that @type
5979 * represents. The info includes details such as rank, array element type
5980 * and the sizes and bounds of multidimensional arrays.
5983 mono_type_get_array_type (MonoType
*type
)
5985 return type
->data
.array
;
5989 * mono_type_get_ptr_type:
5990 * @type: the MonoType operated on
5992 * It is only valid to call this function if @type is a MONO_TYPE_PTR.
5995 * Returns: the MonoType pointer that describes the type that @type
5996 * represents a pointer to.
5999 mono_type_get_ptr_type (MonoType
*type
)
6001 g_assert (type
->type
== MONO_TYPE_PTR
);
6002 return type
->data
.type
;
6006 mono_type_get_modifiers (MonoType
*type
, gboolean
*is_required
, gpointer
*iter
)
6008 /* FIXME: implement */
6013 * mono_type_is_struct:
6014 * @type: the MonoType operated on
6016 * Returns: #TRUE is @type is a struct, that is a ValueType but not en enum
6017 * or a basic type like System.Int32. #FALSE otherwise.
6020 mono_type_is_struct (MonoType
*type
)
6022 return (!type
->byref
&& ((type
->type
== MONO_TYPE_VALUETYPE
&&
6023 !type
->data
.klass
->enumtype
) || (type
->type
== MONO_TYPE_TYPEDBYREF
) ||
6024 ((type
->type
== MONO_TYPE_GENERICINST
) &&
6025 mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
) &&
6026 !type
->data
.generic_class
->container_class
->enumtype
)));
6030 * mono_type_is_void:
6031 * @type: the MonoType operated on
6033 * Returns: #TRUE is @type is System.Void. #FALSE otherwise.
6036 mono_type_is_void (MonoType
*type
)
6038 return (type
&& (type
->type
== MONO_TYPE_VOID
) && !type
->byref
);
6042 * mono_type_is_pointer:
6043 * @type: the MonoType operated on
6045 * Returns: #TRUE is @type is a managed or unmanaged pointer type. #FALSE otherwise.
6048 mono_type_is_pointer (MonoType
*type
)
6050 return (type
&& ((type
->byref
|| (type
->type
== MONO_TYPE_I
) || type
->type
== MONO_TYPE_STRING
)
6051 || (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
6052 (type
->type
== MONO_TYPE_U
) || (type
->type
== MONO_TYPE_OBJECT
) ||
6053 (type
->type
== MONO_TYPE_ARRAY
) || (type
->type
== MONO_TYPE_PTR
) ||
6054 (type
->type
== MONO_TYPE_FNPTR
)));
6058 * mono_type_is_reference:
6059 * @type: the MonoType operated on
6061 * Returns: #TRUE is @type represents an object reference . #FALSE otherwise.
6064 mono_type_is_reference (MonoType
*type
)
6066 return (type
&& (((type
->type
== MONO_TYPE_STRING
) ||
6067 (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
6068 (type
->type
== MONO_TYPE_OBJECT
) || (type
->type
== MONO_TYPE_ARRAY
)) ||
6069 ((type
->type
== MONO_TYPE_GENERICINST
) &&
6070 !mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
))));
6074 * mono_signature_get_return_type:
6075 * @sig: the method signature inspected
6077 * Returns: the return type of the method signature @sig
6080 mono_signature_get_return_type (MonoMethodSignature
*sig
)
6086 * mono_signature_get_params:
6087 * @sig: the method signature inspected
6088 * #iter: pointer to an iterator
6090 * Iterates over the parameters for the method signature @sig.
6091 * A void* pointer must be initualized to #NULL to start the iteration
6092 * and it's address is passed to this function repeteadly until it returns
6095 * Returns: the next parameter type of the method signature @sig,
6096 * #NULL when finished.
6099 mono_signature_get_params (MonoMethodSignature
*sig
, gpointer
*iter
)
6105 /* start from the first */
6106 if (sig
->param_count
) {
6107 *iter
= &sig
->params
[0];
6108 return sig
->params
[0];
6116 if (type
< &sig
->params
[sig
->param_count
]) {
6124 * mono_signature_get_param_count:
6125 * @sig: the method signature inspected
6127 * Returns: the number of parameters in the method signature @sig.
6130 mono_signature_get_param_count (MonoMethodSignature
*sig
)
6132 return sig
->param_count
;
6136 * mono_signature_get_call_conv:
6137 * @sig: the method signature inspected
6139 * Returns: the call convention of the method signature @sig.
6142 mono_signature_get_call_conv (MonoMethodSignature
*sig
)
6144 return sig
->call_convention
;
6148 * mono_signature_vararg_start:
6149 * @sig: the method signature inspected
6151 * Returns: the number of the first vararg parameter in the
6152 * method signature @sig. -1 if this is not a vararg signature.
6155 mono_signature_vararg_start (MonoMethodSignature
*sig
)
6157 return sig
->sentinelpos
;
6161 * mono_signature_is_instance:
6162 * @sig: the method signature inspected
6164 * Returns: #TRUE if this the method signature @sig has an implicit
6165 * first instance argument. #FALSE otherwise.
6168 mono_signature_is_instance (MonoMethodSignature
*sig
)
6170 return sig
->hasthis
;
6174 * mono_signature_explicit_this:
6175 * @sig: the method signature inspected
6177 * Returns: #TRUE if this the method signature @sig has an explicit
6178 * instance argument. #FALSE otherwise.
6181 mono_signature_explicit_this (MonoMethodSignature
*sig
)
6183 return sig
->explicit_this
;
6186 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
6188 mono_aligned_addr_hash (gconstpointer ptr
)
6190 return GPOINTER_TO_UINT (ptr
) >> 3;
6194 * If @field belongs to an inflated generic class, return the corresponding field of the
6195 * generic type definition class.
6198 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField
*field
)
6203 if (!field
->parent
->generic_class
)
6206 gtd
= field
->parent
->generic_class
->container_class
;
6207 offset
= field
- field
->parent
->fields
;
6208 return gtd
->fields
+ offset
;
6212 * If @event belongs to an inflated generic class, return the corresponding event of the
6213 * generic type definition class.
6216 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent
*event
)
6221 if (!event
->parent
->generic_class
)
6224 gtd
= event
->parent
->generic_class
->container_class
;
6225 offset
= event
- event
->parent
->ext
->events
;
6226 return gtd
->ext
->events
+ offset
;
6230 * If @property belongs to an inflated generic class, return the corresponding property of the
6231 * generic type definition class.
6234 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty
*property
)
6239 if (!property
->parent
->generic_class
)
6242 gtd
= property
->parent
->generic_class
->container_class
;
6243 offset
= property
- property
->parent
->ext
->properties
;
6244 return gtd
->ext
->properties
+ offset
;