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)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
19 #include "tabledefs.h"
20 #include "mono-endian.h"
22 #include "tokentype.h"
23 #include "class-internals.h"
24 #include "metadata-internals.h"
25 #include "verify-internals.h"
28 #include "debug-helpers.h"
29 #include "abi-details.h"
30 #include <mono/utils/mono-error-internals.h>
31 #include <mono/utils/bsearch.h>
32 #include <mono/utils/atomic.h>
34 /* Auxiliary structure used for caching inflated signatures */
36 MonoMethodSignature
*sig
;
37 MonoGenericContext context
;
38 } MonoInflatedMethodSignature
;
40 static gboolean
do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
, gboolean transient
,
41 const char *ptr
, const char **rptr
, MonoError
*error
);
43 static gboolean
do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
);
44 static gboolean
mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
);
45 static gboolean
mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
);
46 static gboolean
_mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
,
47 gboolean signature_only
);
48 static void free_generic_inst (MonoGenericInst
*ginst
);
49 static void free_generic_class (MonoGenericClass
*ginst
);
50 static void free_inflated_method (MonoMethodInflated
*method
);
51 static void free_inflated_signature (MonoInflatedMethodSignature
*sig
);
52 static void mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
, MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
);
55 * This enumeration is used to describe the data types in the metadata
66 /* Index into Blob heap */
69 /* Index into String heap */
75 /* Pointer into a table */
78 /* HasConstant:Parent pointer (Param, Field or Property) */
81 /* HasCustomAttribute index. Indexes any table except CustomAttribute */
84 /* CustomAttributeType encoded index */
87 /* HasDeclSecurity index: TypeDef Method or Assembly */
90 /* Implementation coded index: File, Export AssemblyRef */
93 /* HasFieldMarshal coded index: Field or Param table */
96 /* MemberForwardedIndex: Field or Method */
99 /* TypeDefOrRef coded index: typedef, typeref, typespec */
102 /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
105 /* MethodDefOrRef coded index: Method or Member Ref table */
108 /* HasSemantic coded index: Event or Property */
111 /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
114 /* CustomDebugInformation parent encoded index */
115 MONO_MT_HASCUSTDEBUG_IDX
118 const static unsigned char TableSchemas
[] = {
119 #define ASSEMBLY_SCHEMA_OFFSET 0
120 MONO_MT_UINT32
, /* "HashId" }, */
121 MONO_MT_UINT16
, /* "Major" }, */
122 MONO_MT_UINT16
, /* "Minor" }, */
123 MONO_MT_UINT16
, /* "BuildNumber" }, */
124 MONO_MT_UINT16
, /* "RevisionNumber" }, */
125 MONO_MT_UINT32
, /* "Flags" }, */
126 MONO_MT_BLOB_IDX
, /* "PublicKey" }, */
127 MONO_MT_STRING_IDX
, /* "Name" }, */
128 MONO_MT_STRING_IDX
, /* "Culture" }, */
131 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
132 MONO_MT_UINT32
, /* "OSPlatformID" }, */
133 MONO_MT_UINT32
, /* "OSMajor" }, */
134 MONO_MT_UINT32
, /* "OSMinor" }, */
137 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
138 MONO_MT_UINT32
, /* "Processor" }, */
141 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
142 MONO_MT_UINT16
, /* "Major" }, */
143 MONO_MT_UINT16
, /* "Minor" }, */
144 MONO_MT_UINT16
, /* "Build" }, */
145 MONO_MT_UINT16
, /* "Revision" }, */
146 MONO_MT_UINT32
, /* "Flags" }, */
147 MONO_MT_BLOB_IDX
, /* "PublicKeyOrToken" }, */
148 MONO_MT_STRING_IDX
, /* "Name" }, */
149 MONO_MT_STRING_IDX
, /* "Culture" }, */
150 MONO_MT_BLOB_IDX
, /* "HashValue" }, */
153 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
154 MONO_MT_UINT32
, /* "OSPlatformID" }, */
155 MONO_MT_UINT32
, /* "OSMajorVersion" }, */
156 MONO_MT_UINT32
, /* "OSMinorVersion" }, */
157 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
160 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
161 MONO_MT_UINT32
, /* "Processor" }, */
162 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
165 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
166 MONO_MT_UINT16
, /* "PackingSize" }, */
167 MONO_MT_UINT32
, /* "ClassSize" }, */
168 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
171 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
172 MONO_MT_UINT8
, /* "Type" }, */
173 MONO_MT_UINT8
, /* "PaddingZero" }, */
174 MONO_MT_CONST_IDX
, /* "Parent" }, */
175 MONO_MT_BLOB_IDX
, /* "Value" }, */
178 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
179 MONO_MT_HASCAT_IDX
, /* "Parent" }, */
180 MONO_MT_CAT_IDX
, /* "Type" }, */
181 MONO_MT_BLOB_IDX
, /* "Value" }, */
184 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
185 MONO_MT_UINT16
, /* "Action" }, */
186 MONO_MT_HASDEC_IDX
, /* "Parent" }, */
187 MONO_MT_BLOB_IDX
, /* "PermissionSet" }, */
190 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
191 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
192 MONO_MT_TABLE_IDX
, /* "EventList:Event" }, */
195 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
196 MONO_MT_UINT16
, /* "EventFlags#EventAttribute" }, */
197 MONO_MT_STRING_IDX
, /* "Name" }, */
198 MONO_MT_TDOR_IDX
, /* "EventType" }, TypeDef or TypeRef or TypeSpec */
201 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
202 MONO_MT_TABLE_IDX
, /* "Event" }, */
205 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
206 MONO_MT_UINT32
, /* "Flags" }, */
207 MONO_MT_TABLE_IDX
, /* "TypeDefId" }, */
208 MONO_MT_STRING_IDX
, /* "TypeName" }, */
209 MONO_MT_STRING_IDX
, /* "TypeNameSpace" }, */
210 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
213 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
214 MONO_MT_UINT16
, /* "Flags" }, */
215 MONO_MT_STRING_IDX
, /* "Name" }, */
216 MONO_MT_BLOB_IDX
, /* "Signature" }, */
219 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
220 MONO_MT_UINT32
, /* "Offset" }, */
221 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
224 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
225 MONO_MT_HFM_IDX
, /* "Parent" }, */
226 MONO_MT_BLOB_IDX
, /* "NativeType" }, */
229 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
230 MONO_MT_UINT32
, /* "RVA" }, */
231 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
234 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
235 MONO_MT_TABLE_IDX
, /* "Field" }, */
238 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
239 MONO_MT_UINT32
, /* "Flags" }, */
240 MONO_MT_STRING_IDX
, /* "Name" }, */
241 MONO_MT_BLOB_IDX
, /* "Value" }, */
244 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
245 MONO_MT_UINT16
, /* "MappingFlag" }, */
246 MONO_MT_MF_IDX
, /* "MemberForwarded" }, */
247 MONO_MT_STRING_IDX
, /* "ImportName" }, */
248 MONO_MT_TABLE_IDX
, /* "ImportScope:ModuleRef" }, */
251 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
252 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
253 MONO_MT_TDOR_IDX
, /* "Interface=TypeDefOrRef" }, */
256 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
257 MONO_MT_UINT32
, /* "Offset" }, */
258 MONO_MT_UINT32
, /* "Flags" }, */
259 MONO_MT_STRING_IDX
, /* "Name" }, */
260 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
263 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
264 MONO_MT_MRP_IDX
, /* "Class" }, */
265 MONO_MT_STRING_IDX
, /* "Name" }, */
266 MONO_MT_BLOB_IDX
, /* "Signature" }, */
269 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
270 MONO_MT_UINT32
, /* "RVA" }, */
271 MONO_MT_UINT16
, /* "ImplFlags#MethodImplAttributes" }, */
272 MONO_MT_UINT16
, /* "Flags#MethodAttribute" }, */
273 MONO_MT_STRING_IDX
, /* "Name" }, */
274 MONO_MT_BLOB_IDX
, /* "Signature" }, */
275 MONO_MT_TABLE_IDX
, /* "ParamList:Param" }, */
278 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
279 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
280 MONO_MT_MDOR_IDX
, /* "MethodBody" }, */
281 MONO_MT_MDOR_IDX
, /* "MethodDeclaration" }, */
284 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
285 MONO_MT_UINT16
, /* "MethodSemantic" }, */
286 MONO_MT_TABLE_IDX
, /* "Method:Method" }, */
287 MONO_MT_HS_IDX
, /* "Association" }, */
290 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
291 MONO_MT_TABLE_IDX
, /* "Method" }, */
294 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
295 MONO_MT_UINT16
, /* "Generation" }, */
296 MONO_MT_STRING_IDX
, /* "Name" }, */
297 MONO_MT_GUID_IDX
, /* "MVID" }, */
298 MONO_MT_GUID_IDX
, /* "EncID" }, */
299 MONO_MT_GUID_IDX
, /* "EncBaseID" }, */
302 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
303 MONO_MT_STRING_IDX
, /* "Name" }, */
306 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
307 MONO_MT_TABLE_IDX
, /* "NestedClass:TypeDef" }, */
308 MONO_MT_TABLE_IDX
, /* "EnclosingClass:TypeDef" }, */
311 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
312 MONO_MT_UINT16
, /* "Flags" }, */
313 MONO_MT_UINT16
, /* "Sequence" }, */
314 MONO_MT_STRING_IDX
, /* "Name" }, */
317 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
318 MONO_MT_TABLE_IDX
, /* "Param" }, */
321 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
322 MONO_MT_UINT16
, /* "Flags" }, */
323 MONO_MT_STRING_IDX
, /* "Name" }, */
324 MONO_MT_BLOB_IDX
, /* "Type" }, */
327 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
328 MONO_MT_TABLE_IDX
, /* "Property" }, */
331 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
332 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
333 MONO_MT_TABLE_IDX
, /* "PropertyList:Property" }, */
336 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
337 MONO_MT_BLOB_IDX
, /* "Signature" }, */
340 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
341 MONO_MT_UINT32
, /* "Flags" }, */
342 MONO_MT_STRING_IDX
, /* "Name" }, */
343 MONO_MT_STRING_IDX
, /* "Namespace" }, */
344 MONO_MT_TDOR_IDX
, /* "Extends" }, */
345 MONO_MT_TABLE_IDX
, /* "FieldList:Field" }, */
346 MONO_MT_TABLE_IDX
, /* "MethodList:Method" }, */
349 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
350 MONO_MT_RS_IDX
, /* "ResolutionScope=ResolutionScope" }, */
351 MONO_MT_STRING_IDX
, /* "Name" }, */
352 MONO_MT_STRING_IDX
, /* "Namespace" }, */
355 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
356 MONO_MT_BLOB_IDX
, /* "Signature" }, */
359 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
360 MONO_MT_UINT16
, /* "Number" }, */
361 MONO_MT_UINT16
, /* "Flags" }, */
362 MONO_MT_TABLE_IDX
, /* "Owner" }, TypeDef or MethodDef */
363 MONO_MT_STRING_IDX
, /* "Name" }, */
366 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
367 MONO_MT_MDOR_IDX
, /* "Method" }, */
368 MONO_MT_BLOB_IDX
, /* "Signature" }, */
371 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
372 MONO_MT_TABLE_IDX
, /* "GenericParam" }, */
373 MONO_MT_TDOR_IDX
, /* "Constraint" }, */
376 #define DOCUMENT_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
377 MONO_MT_BLOB_IDX
, /* Name */
378 MONO_MT_GUID_IDX
, /* HashAlgorithm */
379 MONO_MT_BLOB_IDX
, /* Hash */
380 MONO_MT_GUID_IDX
, /* Language */
383 #define METHODBODY_SCHEMA_OFFSET DOCUMENT_SCHEMA_OFFSET + 5
384 MONO_MT_TABLE_IDX
, /* Document */
385 MONO_MT_BLOB_IDX
, /* SequencePoints */
388 #define LOCALSCOPE_SCHEMA_OFFSET METHODBODY_SCHEMA_OFFSET + 3
389 MONO_MT_TABLE_IDX
, /* Method */
390 MONO_MT_TABLE_IDX
, /* ImportScope */
391 MONO_MT_TABLE_IDX
, /* VariableList */
392 MONO_MT_TABLE_IDX
, /* ConstantList */
393 MONO_MT_UINT32
, /* StartOffset */
394 MONO_MT_UINT32
, /* Length */
397 #define LOCALVARIABLE_SCHEMA_OFFSET LOCALSCOPE_SCHEMA_OFFSET + 7
398 MONO_MT_UINT16
, /* Attributes */
399 MONO_MT_UINT16
, /* Index */
400 MONO_MT_STRING_IDX
, /* Name */
403 #define LOCALCONSTANT_SCHEMA_OFFSET LOCALVARIABLE_SCHEMA_OFFSET + 4
404 MONO_MT_STRING_IDX
, /* Name (String heap index) */
405 MONO_MT_BLOB_IDX
, /* Signature (Blob heap index, LocalConstantSig blob) */
408 #define IMPORTSCOPE_SCHEMA_OFFSET LOCALCONSTANT_SCHEMA_OFFSET + 3
409 MONO_MT_TABLE_IDX
, /* Parent (ImportScope row id or nil) */
410 MONO_MT_BLOB_IDX
, /* Imports (Blob index, encoding: Imports blob) */
413 #define ASYNCMETHOD_SCHEMA_OFFSET IMPORTSCOPE_SCHEMA_OFFSET + 3
414 MONO_MT_TABLE_IDX
, /* MoveNextMethod (MethodDef row id) */
415 MONO_MT_TABLE_IDX
, /* KickoffMethod (MethodDef row id) */
418 #define CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET ASYNCMETHOD_SCHEMA_OFFSET + 3
419 MONO_MT_HASCUSTDEBUG_IDX
, /* Parent (HasCustomDebugInformation coded index) */
420 MONO_MT_GUID_IDX
, /* Kind (Guid heap index) */
421 MONO_MT_BLOB_IDX
, /* Value (Blob heap index) */
424 #define NULL_SCHEMA_OFFSET CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET + 4
428 /* Must be the same order as MONO_TABLE_* */
429 const static unsigned char
430 table_description
[] = {
431 MODULE_SCHEMA_OFFSET
,
432 TYPEREF_SCHEMA_OFFSET
,
433 TYPEDEF_SCHEMA_OFFSET
,
434 FIELD_POINTER_SCHEMA_OFFSET
,
436 METHOD_POINTER_SCHEMA_OFFSET
,
437 METHOD_SCHEMA_OFFSET
,
438 PARAM_POINTER_SCHEMA_OFFSET
,
440 IFACEMAP_SCHEMA_OFFSET
,
441 MEMBERREF_SCHEMA_OFFSET
, /* 0xa */
442 CONSTANT_SCHEMA_OFFSET
,
443 CUSTOM_ATTR_SCHEMA_OFFSET
,
444 FIELD_MARSHAL_SCHEMA_OFFSET
,
445 DECL_SEC_SCHEMA_OFFSET
,
446 CLASS_LAYOUT_SCHEMA_OFFSET
,
447 FIELD_LAYOUT_SCHEMA_OFFSET
, /* 0x10 */
448 STDALON_SIG_SCHEMA_OFFSET
,
449 EVENTMAP_SCHEMA_OFFSET
,
450 EVENT_POINTER_SCHEMA_OFFSET
,
452 PROPERTY_MAP_SCHEMA_OFFSET
,
453 PROPERTY_POINTER_SCHEMA_OFFSET
,
454 PROPERTY_SCHEMA_OFFSET
,
455 METHOD_SEMA_SCHEMA_OFFSET
,
456 METHOD_IMPL_SCHEMA_OFFSET
,
457 MODULEREF_SCHEMA_OFFSET
, /* 0x1a */
458 TYPESPEC_SCHEMA_OFFSET
,
459 IMPLMAP_SCHEMA_OFFSET
,
460 FIELD_RVA_SCHEMA_OFFSET
,
463 ASSEMBLY_SCHEMA_OFFSET
, /* 0x20 */
464 ASSEMBLYPROC_SCHEMA_OFFSET
,
465 ASSEMBLYOS_SCHEMA_OFFSET
,
466 ASSEMBLYREF_SCHEMA_OFFSET
,
467 ASSEMBLYREFPROC_SCHEMA_OFFSET
,
468 ASSEMBLYREFOS_SCHEMA_OFFSET
,
470 EXPORTED_TYPE_SCHEMA_OFFSET
,
471 MANIFEST_SCHEMA_OFFSET
,
472 NESTED_CLASS_SCHEMA_OFFSET
,
473 GENPARAM_SCHEMA_OFFSET
, /* 0x2a */
474 METHOD_SPEC_SCHEMA_OFFSET
,
475 GEN_CONSTRAINT_SCHEMA_OFFSET
,
479 DOCUMENT_SCHEMA_OFFSET
, /* 0x30 */
480 METHODBODY_SCHEMA_OFFSET
,
481 LOCALSCOPE_SCHEMA_OFFSET
,
482 LOCALVARIABLE_SCHEMA_OFFSET
,
483 LOCALCONSTANT_SCHEMA_OFFSET
,
484 IMPORTSCOPE_SCHEMA_OFFSET
,
485 ASYNCMETHOD_SCHEMA_OFFSET
,
486 CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET
489 #ifdef HAVE_ARRAY_ELEM_INIT
490 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
491 #define MSGSTRFIELD1(line) str##line
492 static const struct msgstr_t
{
493 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
494 #include "mono/cil/tables.def"
497 #define TABLEDEF(a,b) b,
498 #include "mono/cil/tables.def"
501 static const gint16 tableidx
[] = {
502 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
503 #include "mono/cil/tables.def"
508 #define TABLEDEF(a,b) b,
509 static const char* const
510 mono_tables_names
[] = {
511 #include "mono/cil/tables.def"
517 // Amount initially reserved in each imageset's mempool.
518 // FIXME: This number is arbitrary, a more practical number should be found
519 #define INITIAL_IMAGE_SET_SIZE 1024
522 * mono_meta_table_name:
523 * @table: table index
525 * Returns the name of the given ECMA metadata logical format table
526 * as described in ECMA 335, Partition II, Section 22.
528 * Returns: the name for the @table index
531 mono_meta_table_name (int table
)
533 if ((table
< 0) || (table
> MONO_TABLE_LAST
))
536 #ifdef HAVE_ARRAY_ELEM_INIT
537 return (const char*)&tablestr
+ tableidx
[table
];
539 return mono_tables_names
[table
];
543 /* The guy who wrote the spec for this should not be allowed near a
546 If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
547 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
548 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
549 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
550 inverse of this mapping.
553 #define rtsize(meta,s,b) (((s) < (1 << (b)) ? 2 : 4))
556 idx_size (MonoImage
*meta
, int tableidx
)
558 return meta
->tables
[tableidx
].rows
< 65536 ? 2 : 4;
562 get_nrows (MonoImage
*meta
, int tableidx
)
564 return meta
->tables
[tableidx
].rows
;
567 /* Reference: Partition II - 23.2.6 */
569 * mono_metadata_compute_size:
570 * @meta: metadata context
571 * @tableindex: metadata table number
572 * @result_bitfield: pointer to guint32 where to store additional info
574 * mono_metadata_compute_size() computes the lenght in bytes of a single
575 * row in a metadata table. The size of each column is encoded in the
576 * @result_bitfield return value along with the number of columns in the table.
577 * the resulting bitfield should be handed to the mono_metadata_table_size()
578 * and mono_metadata_table_count() macros.
579 * This is a Mono runtime internal only function.
582 mono_metadata_compute_size (MonoImage
*meta
, int tableindex
, guint32
*result_bitfield
)
584 guint32 bitfield
= 0;
585 int size
= 0, field_size
= 0;
588 const unsigned char *description
= TableSchemas
+ table_description
[tableindex
];
590 for (i
= 0; (code
= description
[i
]) != MONO_MT_END
; i
++){
593 field_size
= 4; break;
596 field_size
= 2; break;
599 field_size
= 1; break;
601 case MONO_MT_BLOB_IDX
:
602 field_size
= meta
->idx_blob_wide
? 4 : 2; break;
604 case MONO_MT_STRING_IDX
:
605 field_size
= meta
->idx_string_wide
? 4 : 2; break;
607 case MONO_MT_GUID_IDX
:
608 field_size
= meta
->idx_guid_wide
? 4 : 2; break;
610 case MONO_MT_TABLE_IDX
:
611 /* Uhm, a table index can point to other tables besides the current one
612 * so, it's not correct to use the rowcount of the current table to
613 * get the size for this column - lupus
615 switch (tableindex
) {
616 case MONO_TABLE_ASSEMBLYREFOS
:
618 field_size
= idx_size (meta
, MONO_TABLE_ASSEMBLYREF
); break;
619 case MONO_TABLE_ASSEMBLYREFPROCESSOR
:
621 field_size
= idx_size (meta
, MONO_TABLE_ASSEMBLYREF
); break;
622 case MONO_TABLE_CLASSLAYOUT
:
624 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
625 case MONO_TABLE_EVENTMAP
:
626 g_assert (i
== 0 || i
== 1);
627 field_size
= i
? idx_size (meta
, MONO_TABLE_EVENT
):
628 idx_size (meta
, MONO_TABLE_TYPEDEF
);
630 case MONO_TABLE_EVENT_POINTER
:
632 field_size
= idx_size (meta
, MONO_TABLE_EVENT
); break;
633 case MONO_TABLE_EXPORTEDTYPE
:
635 /* the index is in another metadata file, so it must be 4 */
636 field_size
= 4; break;
637 case MONO_TABLE_FIELDLAYOUT
:
639 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
640 case MONO_TABLE_FIELDRVA
:
642 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
643 case MONO_TABLE_FIELD_POINTER
:
645 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
646 case MONO_TABLE_IMPLMAP
:
648 field_size
= idx_size (meta
, MONO_TABLE_MODULEREF
); break;
649 case MONO_TABLE_INTERFACEIMPL
:
651 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
652 case MONO_TABLE_METHOD
:
654 field_size
= idx_size (meta
, MONO_TABLE_PARAM
); break;
655 case MONO_TABLE_METHODIMPL
:
657 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
658 case MONO_TABLE_METHODSEMANTICS
:
660 field_size
= idx_size (meta
, MONO_TABLE_METHOD
); break;
661 case MONO_TABLE_METHOD_POINTER
:
663 field_size
= idx_size (meta
, MONO_TABLE_METHOD
); break;
664 case MONO_TABLE_NESTEDCLASS
:
665 g_assert (i
== 0 || i
== 1);
666 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
667 case MONO_TABLE_PARAM_POINTER
:
669 field_size
= idx_size (meta
, MONO_TABLE_PARAM
); break;
670 case MONO_TABLE_PROPERTYMAP
:
671 g_assert (i
== 0 || i
== 1);
672 field_size
= i
? idx_size (meta
, MONO_TABLE_PROPERTY
):
673 idx_size (meta
, MONO_TABLE_TYPEDEF
);
675 case MONO_TABLE_PROPERTY_POINTER
:
677 field_size
= idx_size (meta
, MONO_TABLE_PROPERTY
); break;
678 case MONO_TABLE_TYPEDEF
:
679 g_assert (i
== 4 || i
== 5);
680 field_size
= i
== 4 ? idx_size (meta
, MONO_TABLE_FIELD
):
681 idx_size (meta
, MONO_TABLE_METHOD
);
683 case MONO_TABLE_GENERICPARAM
:
685 n
= MAX (get_nrows (meta
, MONO_TABLE_METHOD
), get_nrows (meta
, MONO_TABLE_TYPEDEF
));
686 /*This is a coded token for 2 tables, so takes 1 bit */
687 field_size
= rtsize (meta
, n
, 16 - MONO_TYPEORMETHOD_BITS
);
689 case MONO_TABLE_GENERICPARAMCONSTRAINT
:
691 field_size
= idx_size (meta
, MONO_TABLE_GENERICPARAM
);
693 case MONO_TABLE_LOCALSCOPE
:
696 // FIXME: This table is in another file
697 field_size
= idx_size (meta
, MONO_TABLE_METHOD
);
700 field_size
= idx_size (meta
, MONO_TABLE_IMPORTSCOPE
);
703 field_size
= idx_size (meta
, MONO_TABLE_LOCALVARIABLE
);
706 field_size
= idx_size (meta
, MONO_TABLE_LOCALCONSTANT
);
709 g_assert_not_reached ();
713 case MONO_TABLE_METHODBODY
:
715 field_size
= idx_size (meta
, MONO_TABLE_DOCUMENT
); break;
716 case MONO_TABLE_IMPORTSCOPE
:
718 field_size
= idx_size (meta
, MONO_TABLE_IMPORTSCOPE
); break;
719 case MONO_TABLE_STATEMACHINEMETHOD
:
720 g_assert(i
== 0 || i
== 1);
721 field_size
= idx_size(meta
, MONO_TABLE_METHOD
); break;
723 g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex
, i
);
728 * HasConstant: ParamDef, FieldDef, Property
730 case MONO_MT_CONST_IDX
:
731 n
= MAX (get_nrows (meta
, MONO_TABLE_PARAM
),
732 get_nrows (meta
, MONO_TABLE_FIELD
));
733 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_PROPERTY
));
735 /* 2 bits to encode tag */
736 field_size
= rtsize (meta
, n
, 16-2);
740 * HasCustomAttribute: points to any table but
743 case MONO_MT_HASCAT_IDX
:
745 * We believe that since the signature and
746 * permission are indexing the Blob heap,
747 * we should consider the blob size first
749 /* I'm not a believer - lupus
750 if (meta->idx_blob_wide){
755 n
= MAX (get_nrows (meta
, MONO_TABLE_METHOD
),
756 get_nrows (meta
, MONO_TABLE_FIELD
));
757 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPEREF
));
758 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPEDEF
));
759 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_PARAM
));
760 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_INTERFACEIMPL
));
761 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MEMBERREF
));
762 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MODULE
));
763 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_DECLSECURITY
));
764 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_PROPERTY
));
765 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_EVENT
));
766 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_STANDALONESIG
));
767 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MODULEREF
));
768 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
769 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLY
));
770 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
771 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_FILE
));
772 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_EXPORTEDTYPE
));
773 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MANIFESTRESOURCE
));
774 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_GENERICPARAM
));
775 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_GENERICPARAMCONSTRAINT
));
776 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_METHODSPEC
));
778 /* 5 bits to encode */
779 field_size
= rtsize (meta
, n
, 16-5);
783 * HasCustomAttribute: points to any table but
787 case MONO_MT_HASCUSTDEBUG_IDX
:
788 n
= MAX(get_nrows (meta
, MONO_TABLE_METHOD
),
789 get_nrows (meta
, MONO_TABLE_FIELD
));
790 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_TYPEREF
));
791 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_TYPEDEF
));
792 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_PARAM
));
793 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_INTERFACEIMPL
));
794 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MEMBERREF
));
795 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MODULE
));
796 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_DECLSECURITY
));
797 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_PROPERTY
));
798 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_EVENT
));
799 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_STANDALONESIG
));
800 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MODULEREF
));
801 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
802 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_ASSEMBLY
));
803 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
804 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_FILE
));
805 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_EXPORTEDTYPE
));
806 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MANIFESTRESOURCE
));
807 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_GENERICPARAM
));
808 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_GENERICPARAMCONSTRAINT
));
809 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_METHODSPEC
));
810 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_DOCUMENT
));
811 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_LOCALSCOPE
));
812 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_LOCALVARIABLE
));
813 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_LOCALCONSTANT
));
814 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_IMPORTSCOPE
));
816 /* 5 bits to encode */
817 field_size
= rtsize(meta
, n
, 16 - 5);
821 * CustomAttributeType: TypeDef, TypeRef, MethodDef,
822 * MemberRef and String.
824 case MONO_MT_CAT_IDX
:
825 /* String is a heap, if it is wide, we know the size */
827 if (meta->idx_string_wide){
832 n
= MAX (get_nrows (meta
, MONO_TABLE_TYPEREF
),
833 get_nrows (meta
, MONO_TABLE_TYPEDEF
));
834 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_METHOD
));
835 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MEMBERREF
));
837 /* 3 bits to encode */
838 field_size
= rtsize (meta
, n
, 16-3);
842 * HasDeclSecurity: Typedef, MethodDef, Assembly
844 case MONO_MT_HASDEC_IDX
:
845 n
= MAX (get_nrows (meta
, MONO_TABLE_TYPEDEF
),
846 get_nrows (meta
, MONO_TABLE_METHOD
));
847 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLY
));
849 /* 2 bits to encode */
850 field_size
= rtsize (meta
, n
, 16-2);
854 * Implementation: File, AssemblyRef, ExportedType
856 case MONO_MT_IMPL_IDX
:
857 n
= MAX (get_nrows (meta
, MONO_TABLE_FILE
),
858 get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
859 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_EXPORTEDTYPE
));
861 /* 2 bits to encode tag */
862 field_size
= rtsize (meta
, n
, 16-2);
866 * HasFieldMarshall: FieldDef, ParamDef
868 case MONO_MT_HFM_IDX
:
869 n
= MAX (get_nrows (meta
, MONO_TABLE_FIELD
),
870 get_nrows (meta
, MONO_TABLE_PARAM
));
872 /* 1 bit used to encode tag */
873 field_size
= rtsize (meta
, n
, 16-1);
877 * MemberForwarded: FieldDef, MethodDef
880 n
= MAX (get_nrows (meta
, MONO_TABLE_FIELD
),
881 get_nrows (meta
, MONO_TABLE_METHOD
));
883 /* 1 bit used to encode tag */
884 field_size
= rtsize (meta
, n
, 16-1);
888 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
890 * It is TypeDef, _TypeRef_, TypeSpec, instead.
892 case MONO_MT_TDOR_IDX
:
893 n
= MAX (get_nrows (meta
, MONO_TABLE_TYPEDEF
),
894 get_nrows (meta
, MONO_TABLE_TYPEREF
));
895 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
897 /* 2 bits to encode */
898 field_size
= rtsize (meta
, n
, 16-2);
902 * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
904 case MONO_MT_MRP_IDX
:
905 n
= MAX (get_nrows (meta
, MONO_TABLE_TYPEDEF
),
906 get_nrows (meta
, MONO_TABLE_TYPEREF
));
907 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_METHOD
));
908 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MODULEREF
));
909 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
911 /* 3 bits to encode */
912 field_size
= rtsize (meta
, n
, 16 - 3);
916 * MethodDefOrRef: MethodDef, MemberRef
918 case MONO_MT_MDOR_IDX
:
919 n
= MAX (get_nrows (meta
, MONO_TABLE_METHOD
),
920 get_nrows (meta
, MONO_TABLE_MEMBERREF
));
922 /* 1 bit used to encode tag */
923 field_size
= rtsize (meta
, n
, 16-1);
927 * HasSemantics: Property, Event
930 n
= MAX (get_nrows (meta
, MONO_TABLE_PROPERTY
),
931 get_nrows (meta
, MONO_TABLE_EVENT
));
933 /* 1 bit used to encode tag */
934 field_size
= rtsize (meta
, n
, 16-1);
938 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
941 n
= MAX (get_nrows (meta
, MONO_TABLE_MODULE
),
942 get_nrows (meta
, MONO_TABLE_MODULEREF
));
943 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
944 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPEREF
));
946 /* 2 bits used to encode tag (ECMA spec claims 3) */
947 field_size
= rtsize (meta
, n
, 16 - 2);
952 * encode field size as follows (we just need to
959 bitfield
|= (field_size
-1) << shift
;
962 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
965 *result_bitfield
= (i
<< 24) | bitfield
;
970 * mono_metadata_compute_table_bases:
971 * @meta: metadata context to compute table values
973 * Computes the table bases for the metadata structure.
974 * This is an internal function used by the image loader code.
977 mono_metadata_compute_table_bases (MonoImage
*meta
)
980 const char *base
= meta
->tables_base
;
982 for (i
= 0; i
< MONO_TABLE_NUM
; i
++) {
983 MonoTableInfo
*table
= &meta
->tables
[i
];
984 if (table
->rows
== 0)
987 table
->row_size
= mono_metadata_compute_size (meta
, i
, &table
->size_bitfield
);
989 base
+= table
->rows
* table
->row_size
;
994 * mono_metadata_locate:
995 * @meta: metadata context
996 * @table: table code.
997 * @idx: index of element to retrieve from @table.
999 * Returns: a pointer to the @idx element in the metadata table
1000 * whose code is @table.
1003 mono_metadata_locate (MonoImage
*meta
, int table
, int idx
)
1005 /* idx == 0 refers always to NULL */
1006 g_return_val_if_fail (idx
> 0 && idx
<= meta
->tables
[table
].rows
, ""); /*FIXME shouldn't we return NULL here?*/
1008 return meta
->tables
[table
].base
+ (meta
->tables
[table
].row_size
* (idx
- 1));
1012 * mono_metadata_locate_token:
1013 * @meta: metadata context
1014 * @token: metadata token
1016 * Returns: a pointer to the data in the metadata represented by the
1020 mono_metadata_locate_token (MonoImage
*meta
, guint32 token
)
1022 return mono_metadata_locate (meta
, token
>> 24, token
& 0xffffff);
1026 * mono_metadata_string_heap:
1027 * @meta: metadata context
1028 * @index: index into the string heap.
1030 * Returns: an in-memory pointer to the @index in the string heap.
1033 mono_metadata_string_heap (MonoImage
*meta
, guint32 index
)
1035 g_assert (index
< meta
->heap_strings
.size
);
1036 g_return_val_if_fail (index
< meta
->heap_strings
.size
, "");
1037 return meta
->heap_strings
.data
+ index
;
1041 * mono_metadata_user_string:
1042 * @meta: metadata context
1043 * @index: index into the user string heap.
1045 * Returns: an in-memory pointer to the @index in the user string heap ("#US").
1048 mono_metadata_user_string (MonoImage
*meta
, guint32 index
)
1050 g_assert (index
< meta
->heap_us
.size
);
1051 g_return_val_if_fail (index
< meta
->heap_us
.size
, "");
1052 return meta
->heap_us
.data
+ index
;
1056 * mono_metadata_blob_heap:
1057 * @meta: metadata context
1058 * @index: index into the blob.
1060 * Returns: an in-memory pointer to the @index in the Blob heap.
1063 mono_metadata_blob_heap (MonoImage
*meta
, guint32 index
)
1065 g_assert (index
< meta
->heap_blob
.size
);
1066 g_return_val_if_fail (index
< meta
->heap_blob
.size
, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
1067 return meta
->heap_blob
.data
+ index
;
1071 * mono_metadata_guid_heap:
1072 * @meta: metadata context
1073 * @index: index into the guid heap.
1075 * Returns: an in-memory pointer to the @index in the guid heap.
1078 mono_metadata_guid_heap (MonoImage
*meta
, guint32 index
)
1081 index
*= 16; /* adjust for guid size and 1-based index */
1082 g_return_val_if_fail (index
< meta
->heap_guid
.size
, "");
1083 return meta
->heap_guid
.data
+ index
;
1086 static const unsigned char *
1087 dword_align (const unsigned char *ptr
)
1089 #if SIZEOF_VOID_P == 8
1090 return (const unsigned char *) (((guint64
) (ptr
+ 3)) & ~3);
1092 return (const unsigned char *) (((guint32
) (ptr
+ 3)) & ~3);
1097 * mono_metadata_decode_row:
1098 * @t: table to extract information from.
1099 * @idx: index in table.
1100 * @res: array of @res_size cols to store the results in
1102 * This decompresses the metadata element @idx in table @t
1103 * into the guint32 @res array that has res_size elements
1106 mono_metadata_decode_row (const MonoTableInfo
*t
, int idx
, guint32
*res
, int res_size
)
1108 guint32 bitfield
= t
->size_bitfield
;
1109 int i
, count
= mono_metadata_table_count (bitfield
);
1112 g_assert (idx
< t
->rows
);
1113 g_assert (idx
>= 0);
1114 data
= t
->base
+ idx
* t
->row_size
;
1116 g_assert (res_size
== count
);
1118 for (i
= 0; i
< count
; i
++) {
1119 int n
= mono_metadata_table_size (bitfield
, i
);
1123 res
[i
] = *data
; break;
1125 res
[i
] = read16 (data
); break;
1127 res
[i
] = read32 (data
); break;
1129 g_assert_not_reached ();
1136 * mono_metadata_decode_row_col:
1137 * @t: table to extract information from.
1138 * @idx: index for row in table.
1139 * @col: column in the row.
1141 * This function returns the value of column @col from the @idx
1142 * row in the table @t.
1145 mono_metadata_decode_row_col (const MonoTableInfo
*t
, int idx
, guint col
)
1147 guint32 bitfield
= t
->size_bitfield
;
1149 register const char *data
;
1152 g_assert (idx
< t
->rows
);
1153 g_assert (col
< mono_metadata_table_count (bitfield
));
1154 data
= t
->base
+ idx
* t
->row_size
;
1156 n
= mono_metadata_table_size (bitfield
, 0);
1157 for (i
= 0; i
< col
; ++i
) {
1159 n
= mono_metadata_table_size (bitfield
, i
+ 1);
1165 return read16 (data
);
1167 return read32 (data
);
1169 g_assert_not_reached ();
1175 * mono_metadata_decode_blob_size:
1176 * @ptr: pointer to a blob object
1177 * @rptr: the new position of the pointer
1179 * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
1181 * Returns: the size of the blob object
1184 mono_metadata_decode_blob_size (const char *xptr
, const char **rptr
)
1186 const unsigned char *ptr
= (const unsigned char *)xptr
;
1189 if ((*ptr
& 0x80) == 0){
1190 size
= ptr
[0] & 0x7f;
1192 } else if ((*ptr
& 0x40) == 0){
1193 size
= ((ptr
[0] & 0x3f) << 8) + ptr
[1];
1196 size
= ((ptr
[0] & 0x1f) << 24) +
1208 * mono_metadata_decode_value:
1209 * @ptr: pointer to decode from
1210 * @rptr: the new position of the pointer
1212 * This routine decompresses 32-bit values as specified in the "Blob and
1213 * Signature" section (23.2)
1215 * Returns: the decoded value
1218 mono_metadata_decode_value (const char *_ptr
, const char **rptr
)
1220 const unsigned char *ptr
= (const unsigned char *) _ptr
;
1221 unsigned char b
= *ptr
;
1224 if ((b
& 0x80) == 0){
1227 } else if ((b
& 0x40) == 0){
1228 len
= ((b
& 0x3f) << 8 | ptr
[1]);
1231 len
= ((b
& 0x1f) << 24) |
1244 * mono_metadata_decode_signed_value:
1245 * @ptr: pointer to decode from
1246 * @rptr: the new position of the pointer
1248 * This routine decompresses 32-bit signed values
1249 * (not specified in the spec)
1251 * Returns: the decoded value
1254 mono_metadata_decode_signed_value (const char *ptr
, const char **rptr
)
1256 guint32 uval
= mono_metadata_decode_value (ptr
, rptr
);
1257 gint32 ival
= uval
>> 1;
1260 /* ival is a truncated 2's complement negative number. */
1262 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1265 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1266 return ival
- 0x2000;
1267 if (ival
< 0x10000000)
1268 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1269 return ival
- 0x10000000;
1270 g_assert (ival
< 0x20000000);
1271 g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival
, uval
);
1272 return ival
- 0x20000000;
1276 * Translates the given 1-based index into the Method, Field, Event, or Param tables
1277 * using the *Ptr tables in uncompressed metadata, if they are available.
1279 * FIXME: The caller is not forced to call this function, which is error-prone, since
1280 * forgetting to call it would only show up as a bug on uncompressed metadata.
1283 mono_metadata_translate_token_index (MonoImage
*image
, int table
, guint32 idx
)
1285 if (!image
->uncompressed_metadata
)
1289 case MONO_TABLE_METHOD
:
1290 if (image
->tables
[MONO_TABLE_METHOD_POINTER
].rows
)
1291 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_METHOD_POINTER
], idx
- 1, MONO_METHOD_POINTER_METHOD
);
1294 case MONO_TABLE_FIELD
:
1295 if (image
->tables
[MONO_TABLE_FIELD_POINTER
].rows
)
1296 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_FIELD_POINTER
], idx
- 1, MONO_FIELD_POINTER_FIELD
);
1299 case MONO_TABLE_EVENT
:
1300 if (image
->tables
[MONO_TABLE_EVENT_POINTER
].rows
)
1301 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_EVENT_POINTER
], idx
- 1, MONO_EVENT_POINTER_EVENT
);
1304 case MONO_TABLE_PROPERTY
:
1305 if (image
->tables
[MONO_TABLE_PROPERTY_POINTER
].rows
)
1306 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PROPERTY_POINTER
], idx
- 1, MONO_PROPERTY_POINTER_PROPERTY
);
1309 case MONO_TABLE_PARAM
:
1310 if (image
->tables
[MONO_TABLE_PARAM_POINTER
].rows
)
1311 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PARAM_POINTER
], idx
- 1, MONO_PARAM_POINTER_PARAM
);
1320 * mono_metadata_decode_table_row:
1322 * Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
1323 * uncompressed metadata into account, so it should be used to access the
1324 * Method, Field, Param and Event tables when the access is made from metadata, i.e.
1325 * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
1328 mono_metadata_decode_table_row (MonoImage
*image
, int table
, int idx
, guint32
*res
, int res_size
)
1330 if (image
->uncompressed_metadata
)
1331 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1333 mono_metadata_decode_row (&image
->tables
[table
], idx
, res
, res_size
);
1337 * mono_metadata_decode_table_row_col:
1339 * Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
1340 * uncompressed metadata into account, so it should be used to access the
1341 * Method, Field, Param and Event tables.
1343 guint32
mono_metadata_decode_table_row_col (MonoImage
*image
, int table
, int idx
, guint col
)
1345 if (image
->uncompressed_metadata
)
1346 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1348 return mono_metadata_decode_row_col (&image
->tables
[table
], idx
, col
);
1352 * mono_metadata_parse_typedef_or_ref:
1353 * @m: a metadata context.
1354 * @ptr: a pointer to an encoded TypedefOrRef in @m
1355 * @rptr: pointer updated to match the end of the decoded stream
1357 * Returns: a token valid in the @m metadata decoded from
1358 * the compressed representation.
1361 mono_metadata_parse_typedef_or_ref (MonoImage
*m
, const char *ptr
, const char **rptr
)
1364 token
= mono_metadata_decode_value (ptr
, &ptr
);
1367 return mono_metadata_token_from_dor (token
);
1371 * mono_metadata_parse_custom_mod:
1372 * @m: a metadata context.
1373 * @dest: storage where the info about the custom modifier is stored (may be NULL)
1374 * @ptr: a pointer to (possibly) the start of a custom modifier list
1375 * @rptr: pointer updated to match the end of the decoded stream
1377 * Checks if @ptr points to a type custom modifier compressed representation.
1379 * Returns: #TRUE if a custom modifier was found, #FALSE if not.
1382 mono_metadata_parse_custom_mod (MonoImage
*m
, MonoCustomMod
*dest
, const char *ptr
, const char **rptr
)
1384 MonoCustomMod local
;
1385 if ((*ptr
== MONO_TYPE_CMOD_OPT
) || (*ptr
== MONO_TYPE_CMOD_REQD
)) {
1388 dest
->required
= *ptr
== MONO_TYPE_CMOD_REQD
? 1 : 0;
1389 dest
->token
= mono_metadata_parse_typedef_or_ref (m
, ptr
+ 1, rptr
);
1396 * mono_metadata_parse_array_internal:
1397 * @m: a metadata context.
1398 * @transient: whenever to allocate data from the heap
1399 * @ptr: a pointer to an encoded array description.
1400 * @rptr: pointer updated to match the end of the decoded stream
1402 * Decodes the compressed array description found in the metadata @m at @ptr.
1404 * Returns: a #MonoArrayType structure describing the array type
1405 * and dimensions. Memory is allocated from the heap or from the image mempool, depending
1406 * on the value of @transient.
1408 * LOCKING: Acquires the loader lock
1410 static MonoArrayType
*
1411 mono_metadata_parse_array_internal (MonoImage
*m
, MonoGenericContainer
*container
,
1412 gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1415 MonoArrayType
*array
;
1418 etype
= mono_metadata_parse_type_checked (m
, container
, 0, FALSE
, ptr
, &ptr
, error
); //FIXME this doesn't respect @transient
1422 array
= transient
? (MonoArrayType
*)g_malloc0 (sizeof (MonoArrayType
)) : (MonoArrayType
*)mono_image_alloc0 (m
, sizeof (MonoArrayType
));
1423 array
->eklass
= mono_class_from_mono_type (etype
);
1424 array
->rank
= mono_metadata_decode_value (ptr
, &ptr
);
1426 array
->numsizes
= mono_metadata_decode_value (ptr
, &ptr
);
1427 if (array
->numsizes
)
1428 array
->sizes
= transient
? (int *)g_malloc0 (sizeof (int) * array
->numsizes
) : (int *)mono_image_alloc0 (m
, sizeof (int) * array
->numsizes
);
1429 for (i
= 0; i
< array
->numsizes
; ++i
)
1430 array
->sizes
[i
] = mono_metadata_decode_value (ptr
, &ptr
);
1432 array
->numlobounds
= mono_metadata_decode_value (ptr
, &ptr
);
1433 if (array
->numlobounds
)
1434 array
->lobounds
= transient
? (int *)g_malloc0 (sizeof (int) * array
->numlobounds
) : (int *)mono_image_alloc0 (m
, sizeof (int) * array
->numlobounds
);
1435 for (i
= 0; i
< array
->numlobounds
; ++i
)
1436 array
->lobounds
[i
] = mono_metadata_decode_signed_value (ptr
, &ptr
);
1444 mono_metadata_parse_array (MonoImage
*m
, const char *ptr
, const char **rptr
)
1447 MonoArrayType
*ret
= mono_metadata_parse_array_internal (m
, NULL
, FALSE
, ptr
, rptr
, &error
);
1448 mono_error_cleanup (&error
);
1454 * mono_metadata_free_array:
1455 * @array: array description
1457 * Frees the array description returned from mono_metadata_parse_array().
1460 mono_metadata_free_array (MonoArrayType
*array
)
1462 g_free (array
->sizes
);
1463 g_free (array
->lobounds
);
1468 * need to add common field and param attributes combinations:
1471 * public static literal
1474 * private static literal
1476 static const MonoType
1478 /* data, attrs, type, nmods, byref, pinned */
1479 {{NULL
}, 0, MONO_TYPE_VOID
, 0, 0, 0},
1480 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 0, 0},
1481 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 1, 0},
1482 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 0, 0},
1483 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 1, 0},
1484 {{NULL
}, 0, MONO_TYPE_I1
, 0, 0, 0},
1485 {{NULL
}, 0, MONO_TYPE_I1
, 0, 1, 0},
1486 {{NULL
}, 0, MONO_TYPE_U1
, 0, 0, 0},
1487 {{NULL
}, 0, MONO_TYPE_U1
, 0, 1, 0},
1488 {{NULL
}, 0, MONO_TYPE_I2
, 0, 0, 0},
1489 {{NULL
}, 0, MONO_TYPE_I2
, 0, 1, 0},
1490 {{NULL
}, 0, MONO_TYPE_U2
, 0, 0, 0},
1491 {{NULL
}, 0, MONO_TYPE_U2
, 0, 1, 0},
1492 {{NULL
}, 0, MONO_TYPE_I4
, 0, 0, 0},
1493 {{NULL
}, 0, MONO_TYPE_I4
, 0, 1, 0},
1494 {{NULL
}, 0, MONO_TYPE_U4
, 0, 0, 0},
1495 {{NULL
}, 0, MONO_TYPE_U4
, 0, 1, 0},
1496 {{NULL
}, 0, MONO_TYPE_I8
, 0, 0, 0},
1497 {{NULL
}, 0, MONO_TYPE_I8
, 0, 1, 0},
1498 {{NULL
}, 0, MONO_TYPE_U8
, 0, 0, 0},
1499 {{NULL
}, 0, MONO_TYPE_U8
, 0, 1, 0},
1500 {{NULL
}, 0, MONO_TYPE_R4
, 0, 0, 0},
1501 {{NULL
}, 0, MONO_TYPE_R4
, 0, 1, 0},
1502 {{NULL
}, 0, MONO_TYPE_R8
, 0, 0, 0},
1503 {{NULL
}, 0, MONO_TYPE_R8
, 0, 1, 0},
1504 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 0, 0},
1505 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 1, 0},
1506 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 0, 0},
1507 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 1, 0},
1508 {{NULL
}, 0, MONO_TYPE_TYPEDBYREF
, 0, 0, 0},
1509 {{NULL
}, 0, MONO_TYPE_I
, 0, 0, 0},
1510 {{NULL
}, 0, MONO_TYPE_I
, 0, 1, 0},
1511 {{NULL
}, 0, MONO_TYPE_U
, 0, 0, 0},
1512 {{NULL
}, 0, MONO_TYPE_U
, 0, 1, 0},
1515 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1517 static GHashTable
*type_cache
= NULL
;
1518 static int next_generic_inst_id
= 0;
1520 /* Protected by image_sets_mutex */
1521 static MonoImageSet
*mscorlib_image_set
;
1522 /* Protected by image_sets_mutex */
1523 static GPtrArray
*image_sets
;
1524 static mono_mutex_t image_sets_mutex
;
1526 static guint
mono_generic_class_hash (gconstpointer data
);
1529 * MonoTypes with modifies are never cached, so we never check or use that field.
1532 mono_type_hash (gconstpointer data
)
1534 const MonoType
*type
= (const MonoType
*) data
;
1535 if (type
->type
== MONO_TYPE_GENERICINST
)
1536 return mono_generic_class_hash (type
->data
.generic_class
);
1538 return type
->type
| (type
->byref
<< 8) | (type
->attrs
<< 9);
1542 mono_type_equal (gconstpointer ka
, gconstpointer kb
)
1544 const MonoType
*a
= (const MonoType
*) ka
;
1545 const MonoType
*b
= (const MonoType
*) kb
;
1547 if (a
->type
!= b
->type
|| a
->byref
!= b
->byref
|| a
->attrs
!= b
->attrs
|| a
->pinned
!= b
->pinned
)
1549 /* need other checks */
1554 mono_metadata_generic_inst_hash (gconstpointer data
)
1556 const MonoGenericInst
*ginst
= (const MonoGenericInst
*) data
;
1560 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
1562 hash
+= mono_metadata_type_hash (ginst
->type_argv
[i
]);
1565 return hash
^ (ginst
->is_open
<< 8);
1569 mono_generic_inst_equal_full (const MonoGenericInst
*a
, const MonoGenericInst
*b
, gboolean signature_only
)
1573 // An optimization: if the ids of two insts are the same, we know they are the same inst and don't check contents.
1574 // Furthermore, because we perform early de-duping, if the ids differ, we know the contents differ.
1575 #ifndef MONO_SMALL_CONFIG // Optimization does not work in MONO_SMALL_CONFIG: There are no IDs
1576 if (a
->id
&& b
->id
) { // "id 0" means "object has no id"-- de-duping hasn't been performed yet, must check contents.
1579 // In signature-comparison mode id equality implies object equality, but this is not true for inequality.
1580 // Two separate objects could have signature-equavalent contents.
1581 if (!signature_only
)
1586 if (a
->is_open
!= b
->is_open
|| a
->type_argc
!= b
->type_argc
)
1588 for (i
= 0; i
< a
->type_argc
; ++i
) {
1589 if (!do_mono_metadata_type_equal (a
->type_argv
[i
], b
->type_argv
[i
], signature_only
))
1596 mono_metadata_generic_inst_equal (gconstpointer ka
, gconstpointer kb
)
1598 const MonoGenericInst
*a
= (const MonoGenericInst
*) ka
;
1599 const MonoGenericInst
*b
= (const MonoGenericInst
*) kb
;
1601 return mono_generic_inst_equal_full (a
, b
, FALSE
);
1605 mono_generic_class_hash (gconstpointer data
)
1607 const MonoGenericClass
*gclass
= (const MonoGenericClass
*) data
;
1608 guint hash
= mono_metadata_type_hash (&gclass
->container_class
->byval_arg
);
1611 hash
+= gclass
->is_tb_open
;
1612 hash
+= mono_metadata_generic_context_hash (&gclass
->context
);
1618 mono_generic_class_equal (gconstpointer ka
, gconstpointer kb
)
1620 const MonoGenericClass
*a
= (const MonoGenericClass
*) ka
;
1621 const MonoGenericClass
*b
= (const MonoGenericClass
*) kb
;
1623 return _mono_metadata_generic_class_equal (a
, b
, FALSE
);
1627 * mono_metadata_init:
1629 * Initialize the global variables of this module.
1630 * This is a Mono runtime internal function.
1633 mono_metadata_init (void)
1637 type_cache
= g_hash_table_new (mono_type_hash
, mono_type_equal
);
1639 for (i
= 0; i
< NBUILTIN_TYPES (); ++i
)
1640 g_hash_table_insert (type_cache
, (gpointer
) &builtin_types
[i
], (gpointer
) &builtin_types
[i
]);
1642 mono_os_mutex_init_recursive (&image_sets_mutex
);
1646 * mono_metadata_cleanup:
1648 * Free all resources used by this module.
1649 * This is a Mono runtime internal function.
1652 mono_metadata_cleanup (void)
1654 g_hash_table_destroy (type_cache
);
1656 g_ptr_array_free (image_sets
, TRUE
);
1658 mono_os_mutex_destroy (&image_sets_mutex
);
1662 * mono_metadata_parse_type:
1663 * @m: metadata context
1664 * @mode: king of type that may be found at @ptr
1665 * @opt_attrs: optional attributes to store in the returned type
1666 * @ptr: pointer to the type representation
1667 * @rptr: pointer updated to match the end of the decoded stream
1668 * @transient: whenever to allocate the result from the heap or from a mempool
1670 * Decode a compressed type description found at @ptr in @m.
1671 * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
1672 * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
1673 * This function can be used to decode type descriptions in method signatures,
1674 * field signatures, locals signatures etc.
1676 * To parse a generic type, `generic_container' points to the current class'es
1677 * (the `generic_container' field in the MonoClass) or the current generic method's
1678 * (stored in image->property_hash) generic container.
1679 * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
1680 * this MonoGenericContainer.
1682 * LOCKING: Acquires the loader lock.
1684 * Returns: a #MonoType structure representing the decoded type.
1687 mono_metadata_parse_type_internal (MonoImage
*m
, MonoGenericContainer
*container
,
1688 short opt_attrs
, gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1690 MonoType
*type
, *cached
;
1692 gboolean byref
= FALSE
;
1693 gboolean pinned
= FALSE
;
1694 const char *tmp_ptr
;
1695 int count
= 0; // Number of mod arguments
1698 mono_error_init (error
);
1701 * According to the spec, custom modifiers should come before the byref
1702 * flag, but the IL produced by ilasm from the following signature:
1703 * object modopt(...) &
1704 * starts with a byref flag, followed by the modifiers. (bug #49802)
1705 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1706 * it would be better to treat byref as real type constructor instead of
1708 * Also, pinned should come before anything else, but some MSV++ produced
1709 * assemblies violate this (#bug 61990).
1712 /* Count the modifiers first */
1717 case MONO_TYPE_PINNED
:
1718 case MONO_TYPE_BYREF
:
1721 case MONO_TYPE_CMOD_REQD
:
1722 case MONO_TYPE_CMOD_OPT
:
1724 mono_metadata_parse_custom_mod (m
, NULL
, tmp_ptr
, &tmp_ptr
);
1731 if (count
) { // There are mods, so the MonoType will be of nonstandard size.
1734 size
= MONO_SIZEOF_TYPE
+ ((gint32
)count
) * sizeof (MonoCustomMod
);
1735 type
= transient
? (MonoType
*)g_malloc0 (size
) : (MonoType
*)mono_image_alloc0 (m
, size
);
1736 type
->num_mods
= count
;
1738 mono_error_set_bad_image (error
, m
, "Invalid type with more than 64 modifiers");
1741 } else { // The type is of standard size, so we can allocate it on the stack.
1743 memset (type
, 0, MONO_SIZEOF_TYPE
);
1746 /* Iterate again, but now parse pinned, byref and custom modifiers */
1751 case MONO_TYPE_PINNED
:
1755 case MONO_TYPE_BYREF
:
1759 case MONO_TYPE_CMOD_REQD
:
1760 case MONO_TYPE_CMOD_OPT
:
1761 mono_metadata_parse_custom_mod (m
, &(type
->modifiers
[count
]), ptr
, &ptr
);
1769 type
->attrs
= opt_attrs
;
1770 type
->byref
= byref
;
1771 type
->pinned
= pinned
? 1 : 0;
1773 if (!do_mono_metadata_parse_type (type
, m
, container
, transient
, ptr
, &ptr
, error
))
1779 // Possibly we can return an already-allocated type instead of the one we decoded
1780 if (!type
->num_mods
&& !transient
) {
1781 /* no need to free type here, because it is on the stack */
1782 if ((type
->type
== MONO_TYPE_CLASS
|| type
->type
== MONO_TYPE_VALUETYPE
) && !type
->pinned
&& !type
->attrs
) {
1783 MonoType
*ret
= type
->byref
? &type
->data
.klass
->this_arg
: &type
->data
.klass
->byval_arg
;
1785 /* Consider the case:
1787 class Foo<T> { class Bar {} }
1788 class Test : Foo<Test>.Bar {}
1790 When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
1791 a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1793 We ensure that the MonoClass is in a state that we can canonicalize to:
1795 klass->byval_arg.data.klass == klass
1796 klass->this_arg.data.klass == klass
1798 If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1800 LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1801 of a MonoClass which currently holds the loader lock. 'type' is local.
1803 if (ret
->data
.klass
== type
->data
.klass
) {
1807 /* No need to use locking since nobody is modifying the hash table */
1808 if ((cached
= (MonoType
*)g_hash_table_lookup (type_cache
, type
))) {
1813 /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1815 if (type
== &stype
) { // Type was allocated on the stack, so we need to copy it to safety
1816 type
= transient
? (MonoType
*)g_malloc (MONO_SIZEOF_TYPE
) : (MonoType
*)mono_image_alloc (m
, MONO_SIZEOF_TYPE
);
1817 memcpy (type
, &stype
, MONO_SIZEOF_TYPE
);
1824 mono_metadata_parse_type_checked (MonoImage
*m
, MonoGenericContainer
*container
,
1825 short opt_attrs
, gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1827 return mono_metadata_parse_type_internal (m
, container
, opt_attrs
, transient
, ptr
, rptr
, error
);
1831 * LOCKING: Acquires the loader lock.
1834 mono_metadata_parse_type (MonoImage
*m
, MonoParseTypeMode mode
, short opt_attrs
,
1835 const char *ptr
, const char **rptr
)
1838 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, opt_attrs
, FALSE
, ptr
, rptr
, &error
);
1839 mono_error_cleanup (&error
);
1844 mono_metadata_method_has_param_attrs (MonoImage
*m
, int def
)
1846 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1847 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1848 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1850 if (def
< methodt
->rows
)
1851 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1853 lastp
= m
->tables
[MONO_TABLE_PARAM
].rows
+ 1;
1855 for (i
= param_index
; i
< lastp
; ++i
) {
1856 guint32 flags
= mono_metadata_decode_row_col (paramt
, i
- 1, MONO_PARAM_FLAGS
);
1865 * mono_metadata_get_param_attrs:
1867 * @m The image to loader parameter attributes from
1868 * @def method def token (one based)
1869 * @param_count number of params to decode including the return value
1871 * Return the parameter attributes for the method whose MethodDef index is DEF. The
1872 * returned memory needs to be freed by the caller. If all the param attributes are
1873 * 0, then NULL is returned.
1876 mono_metadata_get_param_attrs (MonoImage
*m
, int def
, int param_count
)
1878 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1879 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1880 guint32 cols
[MONO_PARAM_SIZE
];
1881 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1884 if (def
< methodt
->rows
)
1885 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1887 lastp
= paramt
->rows
+ 1;
1889 for (i
= param_index
; i
< lastp
; ++i
) {
1890 mono_metadata_decode_row (paramt
, i
- 1, cols
, MONO_PARAM_SIZE
);
1891 if (cols
[MONO_PARAM_FLAGS
]) {
1893 pattrs
= g_new0 (int, param_count
);
1894 /* at runtime we just ignore this kind of malformed file:
1895 * the verifier can signal the error to the user
1897 if (cols
[MONO_PARAM_SEQUENCE
] >= param_count
)
1899 pattrs
[cols
[MONO_PARAM_SEQUENCE
]] = cols
[MONO_PARAM_FLAGS
];
1908 * mono_metadata_parse_signature:
1909 * @image: metadata context
1910 * @token: metadata token
1912 * Decode a method signature stored in the STANDALONESIG table
1914 * Returns: a MonoMethodSignature describing the signature.
1916 MonoMethodSignature
*
1917 mono_metadata_parse_signature (MonoImage
*image
, guint32 token
)
1920 MonoMethodSignature
*ret
;
1921 ret
= mono_metadata_parse_signature_checked (image
, token
, &error
);
1922 mono_error_cleanup (&error
);
1927 * mono_metadata_parse_signature_checked:
1928 * @image: metadata context
1929 * @token: metadata token
1930 * @error: set on error
1932 * Decode a method signature stored in the STANDALONESIG table
1934 * Returns: a MonoMethodSignature describing the signature. On failure
1935 * returns NULL and sets @error.
1937 MonoMethodSignature
*
1938 mono_metadata_parse_signature_checked (MonoImage
*image
, guint32 token
, MonoError
*error
)
1941 mono_error_init (error
);
1942 MonoTableInfo
*tables
= image
->tables
;
1943 guint32 idx
= mono_metadata_token_index (token
);
1947 if (image_is_dynamic (image
)) {
1948 return (MonoMethodSignature
*)mono_lookup_dynamic_token (image
, token
, NULL
, error
);
1951 g_assert (mono_metadata_token_table(token
) == MONO_TABLE_STANDALONESIG
);
1953 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
1955 ptr
= mono_metadata_blob_heap (image
, sig
);
1956 mono_metadata_decode_blob_size (ptr
, &ptr
);
1958 return mono_metadata_parse_method_signature_full (image
, NULL
, 0, ptr
, NULL
, error
);
1962 * mono_metadata_signature_alloc:
1963 * @image: metadata context
1964 * @nparmas: number of parameters in the signature
1966 * Allocate a MonoMethodSignature structure with the specified number of params.
1967 * The return type and the params types need to be filled later.
1968 * This is a Mono runtime internal function.
1970 * LOCKING: Assumes the loader lock is held.
1972 * Returns: the new MonoMethodSignature structure.
1974 MonoMethodSignature
*
1975 mono_metadata_signature_alloc (MonoImage
*m
, guint32 nparams
)
1977 MonoMethodSignature
*sig
;
1979 sig
= (MonoMethodSignature
*)mono_image_alloc0 (m
, MONO_SIZEOF_METHOD_SIGNATURE
+ ((gint32
)nparams
) * sizeof (MonoType
*));
1980 sig
->param_count
= nparams
;
1981 sig
->sentinelpos
= -1;
1986 static MonoMethodSignature
*
1987 mono_metadata_signature_dup_internal_with_padding (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
, size_t padding
)
1989 int sigsize
, sig_header_size
;
1990 MonoMethodSignature
*ret
;
1991 sigsize
= sig_header_size
= MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*) + padding
;
1993 sigsize
+= MONO_SIZEOF_TYPE
;
1996 ret
= (MonoMethodSignature
*)mono_image_alloc (image
, sigsize
);
1998 ret
= (MonoMethodSignature
*)mono_mempool_alloc (mp
, sigsize
);
2000 ret
= (MonoMethodSignature
*)g_malloc (sigsize
);
2003 memcpy (ret
, sig
, sig_header_size
- padding
);
2005 // Copy return value because of ownership semantics.
2007 // Danger! Do not alter padding use without changing the dup_add_this below
2008 intptr_t end_of_header
= (intptr_t)( (char*)(ret
) + sig_header_size
);
2009 ret
->ret
= (MonoType
*)end_of_header
;
2010 memcpy (ret
->ret
, sig
->ret
, MONO_SIZEOF_TYPE
);
2016 static MonoMethodSignature
*
2017 mono_metadata_signature_dup_internal (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
)
2019 return mono_metadata_signature_dup_internal_with_padding (image
, mp
, sig
, 0);
2022 * signature_dup_add_this:
2024 * Make a copy of @sig, adding an explicit this argument.
2026 MonoMethodSignature
*
2027 mono_metadata_signature_dup_add_this (MonoImage
*image
, MonoMethodSignature
*sig
, MonoClass
*klass
)
2029 MonoMethodSignature
*ret
;
2030 ret
= mono_metadata_signature_dup_internal_with_padding (image
, NULL
, sig
, sizeof (MonoType
*));
2032 ret
->param_count
= sig
->param_count
+ 1;
2033 ret
->hasthis
= FALSE
;
2035 for (int i
= sig
->param_count
- 1; i
>= 0; i
--)
2036 ret
->params
[i
+ 1] = sig
->params
[i
];
2037 ret
->params
[0] = klass
->valuetype
? &klass
->this_arg
: &klass
->byval_arg
;
2039 for (int i
= sig
->param_count
- 1; i
>= 0; i
--)
2040 g_assert(ret
->params
[i
+ 1]->type
== sig
->params
[i
]->type
&& ret
->params
[i
+1]->type
!= MONO_TYPE_END
);
2041 g_assert (ret
->ret
->type
== sig
->ret
->type
&& ret
->ret
->type
!= MONO_TYPE_END
);
2048 MonoMethodSignature
*
2049 mono_metadata_signature_dup_full (MonoImage
*image
, MonoMethodSignature
*sig
)
2051 MonoMethodSignature
*ret
= mono_metadata_signature_dup_internal (image
, NULL
, sig
);
2053 for (int i
= 0 ; i
< sig
->param_count
; i
++)
2054 g_assert(ret
->params
[i
]->type
== sig
->params
[i
]->type
);
2055 g_assert (ret
->ret
->type
== sig
->ret
->type
);
2060 /*The mempool is accessed without synchronization*/
2061 MonoMethodSignature
*
2062 mono_metadata_signature_dup_mempool (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
2064 return mono_metadata_signature_dup_internal (NULL
, mp
, sig
);
2068 * mono_metadata_signature_dup:
2069 * @sig: method signature
2071 * Duplicate an existing MonoMethodSignature so it can be modified.
2072 * This is a Mono runtime internal function.
2074 * Returns: the new MonoMethodSignature structure.
2076 MonoMethodSignature
*
2077 mono_metadata_signature_dup (MonoMethodSignature
*sig
)
2079 return mono_metadata_signature_dup_full (NULL
, sig
);
2083 * mono_metadata_signature_size:
2085 * Return the amount of memory allocated to SIG.
2088 mono_metadata_signature_size (MonoMethodSignature
*sig
)
2090 return MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*);
2094 * mono_metadata_parse_method_signature:
2095 * @m: metadata context
2096 * @generic_container: generics container
2097 * @def: the MethodDef index or 0 for Ref signatures.
2098 * @ptr: pointer to the signature metadata representation
2099 * @rptr: pointer updated to match the end of the decoded stream
2101 * Decode a method signature stored at @ptr.
2102 * This is a Mono runtime internal function.
2104 * LOCKING: Assumes the loader lock is held.
2106 * Returns: a MonoMethodSignature describing the signature.
2108 MonoMethodSignature
*
2109 mono_metadata_parse_method_signature_full (MonoImage
*m
, MonoGenericContainer
*container
,
2110 int def
, const char *ptr
, const char **rptr
, MonoError
*error
)
2112 MonoMethodSignature
*method
;
2113 int i
, *pattrs
= NULL
;
2114 guint32 hasthis
= 0, explicit_this
= 0, call_convention
, param_count
;
2115 guint32 gen_param_count
= 0;
2116 gboolean is_open
= FALSE
;
2118 mono_error_init (error
);
2121 gen_param_count
= 1;
2126 call_convention
= *ptr
& 0x0F;
2128 if (gen_param_count
)
2129 gen_param_count
= mono_metadata_decode_value (ptr
, &ptr
);
2130 param_count
= mono_metadata_decode_value (ptr
, &ptr
);
2133 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 */
2135 method
= mono_metadata_signature_alloc (m
, param_count
);
2136 method
->hasthis
= hasthis
;
2137 method
->explicit_this
= explicit_this
;
2138 method
->call_convention
= call_convention
;
2139 method
->generic_param_count
= gen_param_count
;
2141 if (call_convention
!= 0xa) {
2142 method
->ret
= mono_metadata_parse_type_checked (m
, container
, pattrs
? pattrs
[0] : 0, FALSE
, ptr
, &ptr
, error
);
2144 mono_metadata_free_method_signature (method
);
2148 is_open
= mono_class_is_open_constructed_type (method
->ret
);
2151 for (i
= 0; i
< method
->param_count
; ++i
) {
2152 if (*ptr
== MONO_TYPE_SENTINEL
) {
2153 if (method
->call_convention
!= MONO_CALL_VARARG
|| def
) {
2154 mono_error_set_bad_image (error
, m
, "Found sentinel for methoddef or no vararg");
2158 if (method
->sentinelpos
>= 0) {
2159 mono_error_set_bad_image (error
, m
, "Found sentinel twice in the same signature.");
2163 method
->sentinelpos
= i
;
2166 method
->params
[i
] = mono_metadata_parse_type_checked (m
, container
, pattrs
? pattrs
[i
+1] : 0, FALSE
, ptr
, &ptr
, error
);
2167 if (!method
->params
[i
]) {
2168 mono_metadata_free_method_signature (method
);
2173 is_open
= mono_class_is_open_constructed_type (method
->params
[i
]);
2176 /* The sentinel could be missing if the caller does not pass any additional arguments */
2177 if (!def
&& method
->call_convention
== MONO_CALL_VARARG
&& method
->sentinelpos
< 0)
2178 method
->sentinelpos
= method
->param_count
;
2180 method
->has_type_parameters
= is_open
;
2182 if (def
&& (method
->call_convention
== MONO_CALL_VARARG
))
2183 method
->sentinelpos
= method
->param_count
;
2190 * Add signature to a cache and increase ref count...
2197 * mono_metadata_parse_method_signature:
2198 * @m: metadata context
2199 * @def: the MethodDef index or 0 for Ref signatures.
2200 * @ptr: pointer to the signature metadata representation
2201 * @rptr: pointer updated to match the end of the decoded stream
2203 * Decode a method signature stored at @ptr.
2204 * This is a Mono runtime internal function.
2206 * LOCKING: Assumes the loader lock is held.
2208 * Returns: a MonoMethodSignature describing the signature.
2210 MonoMethodSignature
*
2211 mono_metadata_parse_method_signature (MonoImage
*m
, int def
, const char *ptr
, const char **rptr
)
2214 * This function MUST NOT be called by runtime code as it does error handling incorrectly.
2215 * Use mono_metadata_parse_method_signature_full instead.
2216 * It's ok to asser on failure as we no longer use it.
2219 MonoMethodSignature
*ret
;
2220 ret
= mono_metadata_parse_method_signature_full (m
, NULL
, def
, ptr
, rptr
, &error
);
2221 g_assert (mono_error_ok (&error
));
2227 * mono_metadata_free_method_signature:
2228 * @sig: signature to destroy
2230 * Free the memory allocated in the signature @sig.
2231 * This method needs to be robust and work also on partially-built
2232 * signatures, so it does extra checks.
2235 mono_metadata_free_method_signature (MonoMethodSignature
*sig
)
2237 /* Everything is allocated from mempools */
2241 mono_metadata_free_type (sig->ret);
2242 for (i = 0; i < sig->param_count; ++i) {
2243 if (sig->params [i])
2244 mono_metadata_free_type (sig->params [i]);
2250 mono_metadata_free_inflated_signature (MonoMethodSignature
*sig
)
2254 /* Allocated in inflate_generic_signature () */
2256 mono_metadata_free_type (sig
->ret
);
2257 for (i
= 0; i
< sig
->param_count
; ++i
) {
2258 if (sig
->params
[i
])
2259 mono_metadata_free_type (sig
->params
[i
]);
2265 inflated_method_equal (gconstpointer a
, gconstpointer b
)
2267 const MonoMethodInflated
*ma
= (const MonoMethodInflated
*)a
;
2268 const MonoMethodInflated
*mb
= (const MonoMethodInflated
*)b
;
2269 if (ma
->declaring
!= mb
->declaring
)
2271 return mono_metadata_generic_context_equal (&ma
->context
, &mb
->context
);
2275 inflated_method_hash (gconstpointer a
)
2277 const MonoMethodInflated
*ma
= (const MonoMethodInflated
*)a
;
2278 return (mono_metadata_generic_context_hash (&ma
->context
) ^ mono_aligned_addr_hash (ma
->declaring
));
2282 inflated_signature_equal (gconstpointer a
, gconstpointer b
)
2284 const MonoInflatedMethodSignature
*sig1
= (const MonoInflatedMethodSignature
*)a
;
2285 const MonoInflatedMethodSignature
*sig2
= (const MonoInflatedMethodSignature
*)b
;
2287 /* sig->sig is assumed to be canonized */
2288 if (sig1
->sig
!= sig2
->sig
)
2290 /* The generic instances are canonized */
2291 return mono_metadata_generic_context_equal (&sig1
->context
, &sig2
->context
);
2295 inflated_signature_hash (gconstpointer a
)
2297 const MonoInflatedMethodSignature
*sig
= (const MonoInflatedMethodSignature
*)a
;
2299 /* sig->sig is assumed to be canonized */
2300 return mono_metadata_generic_context_hash (&sig
->context
) ^ mono_aligned_addr_hash (sig
->sig
);
2304 dump_ginst (MonoGenericInst *ginst)
2309 g_print ("Ginst: <");
2310 for (i = 0; i < ginst->type_argc; ++i) {
2313 name = mono_type_get_name (ginst->type_argv [i]);
2314 g_print ("%s", name);
2320 static gboolean
type_in_image (MonoType
*type
, MonoImage
*image
);
2323 signature_in_image (MonoMethodSignature
*sig
, MonoImage
*image
)
2325 gpointer iter
= NULL
;
2328 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2329 if (type_in_image (p
, image
))
2332 return type_in_image (mono_signature_get_return_type (sig
), image
);
2336 ginst_in_image (MonoGenericInst
*ginst
, MonoImage
*image
)
2340 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2341 if (type_in_image (ginst
->type_argv
[i
], image
))
2349 gclass_in_image (MonoGenericClass
*gclass
, MonoImage
*image
)
2351 return gclass
->container_class
->image
== image
||
2352 ginst_in_image (gclass
->context
.class_inst
, image
);
2356 type_in_image (MonoType
*type
, MonoImage
*image
)
2359 switch (type
->type
) {
2360 case MONO_TYPE_GENERICINST
:
2361 return gclass_in_image (type
->data
.generic_class
, image
);
2363 type
= type
->data
.type
;
2365 case MONO_TYPE_SZARRAY
:
2366 type
= &type
->data
.klass
->byval_arg
;
2368 case MONO_TYPE_ARRAY
:
2369 type
= &type
->data
.array
->eklass
->byval_arg
;
2371 case MONO_TYPE_FNPTR
:
2372 return signature_in_image (type
->data
.method
, image
);
2374 case MONO_TYPE_MVAR
:
2375 return image
== get_image_for_generic_param (type
->data
.generic_param
);
2377 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2378 return image
== mono_class_from_mono_type (type
)->image
;
2383 image_sets_lock (void)
2385 mono_os_mutex_lock (&image_sets_mutex
);
2389 image_sets_unlock (void)
2391 mono_os_mutex_unlock (&image_sets_mutex
);
2397 * Return a MonoImageSet representing the set of images in IMAGES.
2399 static MonoImageSet
*
2400 get_image_set (MonoImage
**images
, int nimages
)
2406 /* Common case: Image set contains corlib only. If we've seen that case before, we cached the set. */
2407 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
&& mscorlib_image_set
)
2408 return mscorlib_image_set
;
2410 /* Happens with empty generic instances */
2411 // FIXME: Is corlib the correct thing to return here? If so, why? This may be an artifact of generic instances previously defaulting to allocating from corlib.
2413 return mscorlib_image_set
;
2418 image_sets
= g_ptr_array_new ();
2420 // Before we go on, we should check to see whether a MonoImageSet with these images already exists.
2421 // We can search the referred-by imagesets of any one of our images to do this. Arbitrarily pick one here:
2422 if (images
[0] == mono_defaults
.corlib
&& nimages
> 1)
2423 l
= images
[1]->image_sets
; // Prefer not to search the imagesets of corlib-- that will be a long list.
2425 l
= images
[0]->image_sets
;
2428 while (l
) // Iterate over selected list, looking for an imageset with members equal to our target one
2430 set
= (MonoImageSet
*)l
->data
;
2432 if (set
->nimages
== nimages
) { // Member count differs, this can't be it
2433 // Compare all members to all members-- order might be different
2434 for (j
= 0; j
< nimages
; ++j
) {
2435 for (k
= 0; k
< nimages
; ++k
)
2436 if (set
->images
[k
] == images
[j
])
2437 break; // Break on match
2439 // If we iterated all the way through set->images, images[j] was *not* found.
2441 break; // Break on "image not found"
2444 // If we iterated all the way through images without breaking, all items in images were found in set->images
2446 break; // Break on "found a set with equal members"
2452 // If we iterated all the way through l without breaking, the imageset does not already exist and we shuold create it
2454 set
= g_new0 (MonoImageSet
, 1);
2455 set
->nimages
= nimages
;
2456 set
->images
= g_new0 (MonoImage
*, nimages
);
2457 mono_os_mutex_init_recursive (&set
->lock
);
2458 for (i
= 0; i
< nimages
; ++i
)
2459 set
->images
[i
] = images
[i
];
2460 set
->gclass_cache
= g_hash_table_new_full (mono_generic_class_hash
, mono_generic_class_equal
, NULL
, (GDestroyNotify
)free_generic_class
);
2461 set
->ginst_cache
= g_hash_table_new_full (mono_metadata_generic_inst_hash
, mono_metadata_generic_inst_equal
, NULL
, (GDestroyNotify
)free_generic_inst
);
2462 set
->gmethod_cache
= g_hash_table_new_full (inflated_method_hash
, inflated_method_equal
, NULL
, (GDestroyNotify
)free_inflated_method
);
2463 set
->gsignature_cache
= g_hash_table_new_full (inflated_signature_hash
, inflated_signature_equal
, NULL
, (GDestroyNotify
)free_inflated_signature
);
2465 for (i
= 0; i
< nimages
; ++i
)
2466 set
->images
[i
]->image_sets
= g_slist_prepend (set
->images
[i
]->image_sets
, set
);
2468 g_ptr_array_add (image_sets
, set
);
2471 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
) {
2472 mono_memory_barrier ();
2473 mscorlib_image_set
= set
;
2476 image_sets_unlock ();
2482 delete_image_set (MonoImageSet
*set
)
2486 g_hash_table_destroy (set
->gclass_cache
);
2487 g_hash_table_destroy (set
->ginst_cache
);
2488 g_hash_table_destroy (set
->gmethod_cache
);
2489 g_hash_table_destroy (set
->gsignature_cache
);
2491 mono_wrapper_caches_free (&set
->wrapper_caches
);
2495 for (i
= 0; i
< set
->nimages
; ++i
)
2496 set
->images
[i
]->image_sets
= g_slist_remove (set
->images
[i
]->image_sets
, set
);
2498 g_ptr_array_remove (image_sets
, set
);
2500 image_sets_unlock ();
2503 mono_mempool_destroy (set
->mempool
);
2504 g_free (set
->images
);
2505 mono_os_mutex_destroy (&set
->lock
);
2510 mono_image_set_lock (MonoImageSet
*set
)
2512 mono_os_mutex_lock (&set
->lock
);
2516 mono_image_set_unlock (MonoImageSet
*set
)
2518 mono_os_mutex_unlock (&set
->lock
);
2522 mono_image_set_alloc (MonoImageSet
*set
, guint size
)
2526 mono_image_set_lock (set
);
2528 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2529 res
= mono_mempool_alloc (set
->mempool
, size
);
2530 mono_image_set_unlock (set
);
2536 mono_image_set_alloc0 (MonoImageSet
*set
, guint size
)
2540 mono_image_set_lock (set
);
2542 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2543 res
= mono_mempool_alloc0 (set
->mempool
, size
);
2544 mono_image_set_unlock (set
);
2550 mono_image_set_strdup (MonoImageSet
*set
, const char *s
)
2554 mono_image_set_lock (set
);
2556 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2557 res
= mono_mempool_strdup (set
->mempool
, s
);
2558 mono_image_set_unlock (set
);
2563 // Get a descriptive string for a MonoImageSet
2564 // Callers are obligated to free buffer with g_free after use
2566 mono_image_set_description (MonoImageSet
*set
)
2568 GString
*result
= g_string_new (NULL
);
2570 g_string_append (result
, "[");
2571 for (img
= 0; img
< set
->nimages
; img
++)
2574 g_string_append (result
, ", ");
2575 g_string_append (result
, set
->images
[img
]->name
);
2577 g_string_append (result
, "]");
2578 return g_string_free (result
, FALSE
);
2582 * Structure used by the collect_..._images functions to store the image list.
2585 MonoImage
*image_buf
[64];
2587 int nimages
, images_len
;
2591 collect_data_init (CollectData
*data
)
2593 data
->images
= data
->image_buf
;
2594 data
->images_len
= 64;
2599 collect_data_free (CollectData
*data
)
2601 if (data
->images
!= data
->image_buf
)
2602 g_free (data
->images
);
2606 enlarge_data (CollectData
*data
)
2608 int new_len
= data
->images_len
< 16 ? 16 : data
->images_len
* 2;
2609 MonoImage
**d
= g_new (MonoImage
*, new_len
);
2612 g_assert_not_reached ();
2613 memcpy (d
, data
->images
, data
->images_len
);
2614 if (data
->images
!= data
->image_buf
)
2615 g_free (data
->images
);
2617 data
->images_len
= new_len
;
2621 add_image (MonoImage
*image
, CollectData
*data
)
2625 /* The arrays are small, so use a linear search instead of a hash table */
2626 for (i
= 0; i
< data
->nimages
; ++i
)
2627 if (data
->images
[i
] == image
)
2630 if (data
->nimages
== data
->images_len
)
2631 enlarge_data (data
);
2633 data
->images
[data
->nimages
++] = image
;
2637 collect_type_images (MonoType
*type
, CollectData
*data
);
2640 collect_ginst_images (MonoGenericInst
*ginst
, CollectData
*data
)
2644 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2645 collect_type_images (ginst
->type_argv
[i
], data
);
2650 collect_gclass_images (MonoGenericClass
*gclass
, CollectData
*data
)
2652 add_image (gclass
->container_class
->image
, data
);
2653 if (gclass
->context
.class_inst
)
2654 collect_ginst_images (gclass
->context
.class_inst
, data
);
2658 collect_signature_images (MonoMethodSignature
*sig
, CollectData
*data
)
2660 gpointer iter
= NULL
;
2663 collect_type_images (mono_signature_get_return_type (sig
), data
);
2664 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2665 collect_type_images (p
, data
);
2669 collect_inflated_signature_images (MonoInflatedMethodSignature
*sig
, CollectData
*data
)
2671 collect_signature_images (sig
->sig
, data
);
2672 if (sig
->context
.class_inst
)
2673 collect_ginst_images (sig
->context
.class_inst
, data
);
2674 if (sig
->context
.method_inst
)
2675 collect_ginst_images (sig
->context
.method_inst
, data
);
2679 collect_method_images (MonoMethodInflated
*method
, CollectData
*data
)
2681 MonoMethod
*m
= method
->declaring
;
2683 add_image (method
->declaring
->klass
->image
, data
);
2684 if (method
->context
.class_inst
)
2685 collect_ginst_images (method
->context
.class_inst
, data
);
2686 if (method
->context
.method_inst
)
2687 collect_ginst_images (method
->context
.method_inst
, data
);
2689 * Dynamic assemblies have no references, so the images they depend on can be unloaded before them.
2691 if (image_is_dynamic (m
->klass
->image
))
2692 collect_signature_images (mono_method_signature (m
), data
);
2696 collect_type_images (MonoType
*type
, CollectData
*data
)
2699 switch (type
->type
) {
2700 case MONO_TYPE_GENERICINST
:
2701 collect_gclass_images (type
->data
.generic_class
, data
);
2704 type
= type
->data
.type
;
2706 case MONO_TYPE_SZARRAY
:
2707 type
= &type
->data
.klass
->byval_arg
;
2709 case MONO_TYPE_ARRAY
:
2710 type
= &type
->data
.array
->eklass
->byval_arg
;
2712 case MONO_TYPE_FNPTR
:
2713 //return signature_in_image (type->data.method, image);
2714 g_assert_not_reached ();
2716 case MONO_TYPE_MVAR
:
2718 MonoImage
*image
= get_image_for_generic_param (type
->data
.generic_param
);
2719 add_image (image
, data
);
2722 case MONO_TYPE_CLASS
:
2723 case MONO_TYPE_VALUETYPE
:
2724 add_image (mono_class_from_mono_type (type
)->image
, data
);
2727 add_image (mono_defaults
.corlib
, data
);
2734 } CleanForImageUserData
;
2737 steal_gclass_in_image (gpointer key
, gpointer value
, gpointer data
)
2739 MonoGenericClass
*gclass
= (MonoGenericClass
*)key
;
2740 CleanForImageUserData
*user_data
= (CleanForImageUserData
*)data
;
2742 g_assert (gclass_in_image (gclass
, user_data
->image
));
2744 user_data
->list
= g_slist_prepend (user_data
->list
, gclass
);
2749 steal_ginst_in_image (gpointer key
, gpointer value
, gpointer data
)
2751 MonoGenericInst
*ginst
= (MonoGenericInst
*)key
;
2752 CleanForImageUserData
*user_data
= (CleanForImageUserData
*)data
;
2754 // This doesn't work during corlib compilation
2755 //g_assert (ginst_in_image (ginst, user_data->image));
2757 user_data
->list
= g_slist_prepend (user_data
->list
, ginst
);
2762 inflated_method_in_image (gpointer key
, gpointer value
, gpointer data
)
2764 MonoImage
*image
= (MonoImage
*)data
;
2765 MonoMethodInflated
*method
= (MonoMethodInflated
*)key
;
2768 // https://bugzilla.novell.com/show_bug.cgi?id=458168
2769 g_assert (method
->declaring
->klass
->image
== image
||
2770 (method
->context
.class_inst
&& ginst_in_image (method
->context
.class_inst
, image
)) ||
2771 (method
->context
.method_inst
&& ginst_in_image (method
->context
.method_inst
, image
)) || (((MonoMethod
*)method
)->signature
&& signature_in_image (mono_method_signature ((MonoMethod
*)method
), image
)));
2777 inflated_signature_in_image (gpointer key
, gpointer value
, gpointer data
)
2779 MonoImage
*image
= (MonoImage
*)data
;
2780 MonoInflatedMethodSignature
*sig
= (MonoInflatedMethodSignature
*)key
;
2782 return signature_in_image (sig
->sig
, image
) ||
2783 (sig
->context
.class_inst
&& ginst_in_image (sig
->context
.class_inst
, image
)) ||
2784 (sig
->context
.method_inst
&& ginst_in_image (sig
->context
.method_inst
, image
));
2788 check_gmethod (gpointer key
, gpointer value
, gpointer data
)
2790 MonoMethodInflated
*method
= (MonoMethodInflated
*)key
;
2791 MonoImage
*image
= (MonoImage
*)data
;
2793 if (method
->context
.class_inst
)
2794 g_assert (!ginst_in_image (method
->context
.class_inst
, image
));
2795 if (method
->context
.method_inst
)
2796 g_assert (!ginst_in_image (method
->context
.method_inst
, image
));
2797 if (((MonoMethod
*)method
)->signature
)
2798 g_assert (!signature_in_image (mono_method_signature ((MonoMethod
*)method
), image
));
2804 * Run a consistency check on the image set data structures.
2806 static G_GNUC_UNUSED
void
2807 check_image_sets (MonoImage
*image
)
2810 GSList
*l
= image
->image_sets
;
2815 for (i
= 0; i
< image_sets
->len
; ++i
) {
2816 MonoImageSet
*set
= (MonoImageSet
*)g_ptr_array_index (image_sets
, i
);
2818 if (!g_slist_find (l
, set
)) {
2819 g_hash_table_foreach (set
->gmethod_cache
, check_gmethod
, image
);
2825 mono_metadata_clean_for_image (MonoImage
*image
)
2827 CleanForImageUserData ginst_data
, gclass_data
;
2828 GSList
*l
, *set_list
;
2830 //check_image_sets (image);
2833 * The data structures could reference each other so we delete them in two phases.
2834 * This is required because of the hashing functions in gclass/ginst_cache.
2836 ginst_data
.image
= gclass_data
.image
= image
;
2837 ginst_data
.list
= gclass_data
.list
= NULL
;
2839 /* Collect the items to delete */
2840 /* delete_image_set () modifies the lists so make a copy */
2841 for (l
= image
->image_sets
; l
; l
= l
->next
) {
2842 MonoImageSet
*set
= (MonoImageSet
*)l
->data
;
2844 mono_image_set_lock (set
);
2845 g_hash_table_foreach_steal (set
->gclass_cache
, steal_gclass_in_image
, &gclass_data
);
2846 g_hash_table_foreach_steal (set
->ginst_cache
, steal_ginst_in_image
, &ginst_data
);
2847 g_hash_table_foreach_remove (set
->gmethod_cache
, inflated_method_in_image
, image
);
2848 g_hash_table_foreach_remove (set
->gsignature_cache
, inflated_signature_in_image
, image
);
2849 mono_image_set_unlock (set
);
2852 /* Delete the removed items */
2853 for (l
= ginst_data
.list
; l
; l
= l
->next
)
2854 free_generic_inst ((MonoGenericInst
*)l
->data
);
2855 for (l
= gclass_data
.list
; l
; l
= l
->next
)
2856 free_generic_class ((MonoGenericClass
*)l
->data
);
2857 g_slist_free (ginst_data
.list
);
2858 g_slist_free (gclass_data
.list
);
2859 /* delete_image_set () modifies the lists so make a copy */
2860 set_list
= g_slist_copy (image
->image_sets
);
2861 for (l
= set_list
; l
; l
= l
->next
) {
2862 MonoImageSet
*set
= (MonoImageSet
*)l
->data
;
2864 delete_image_set (set
);
2866 g_slist_free (set_list
);
2870 free_inflated_method (MonoMethodInflated
*imethod
)
2872 MonoMethod
*method
= (MonoMethod
*)imethod
;
2874 if (method
->signature
)
2875 mono_metadata_free_inflated_signature (method
->signature
);
2877 if (method
->wrapper_type
)
2878 g_free (((MonoMethodWrapper
*)method
)->method_data
);
2884 free_generic_inst (MonoGenericInst
*ginst
)
2888 /* The ginst itself is allocated from the image set mempool */
2889 for (i
= 0; i
< ginst
->type_argc
; ++i
)
2890 mono_metadata_free_type (ginst
->type_argv
[i
]);
2894 free_generic_class (MonoGenericClass
*gclass
)
2896 /* The gclass itself is allocated from the image set mempool */
2897 if (gclass
->cached_class
&& gclass
->cached_class
->interface_id
)
2898 mono_unload_interface_id (gclass
->cached_class
);
2902 free_inflated_signature (MonoInflatedMethodSignature
*sig
)
2904 mono_metadata_free_inflated_signature (sig
->sig
);
2909 * mono_metadata_get_inflated_signature:
2911 * Given an inflated signature and a generic context, return a canonical copy of the
2912 * signature. The returned signature might be equal to SIG or it might be a cached copy.
2914 MonoMethodSignature
*
2915 mono_metadata_get_inflated_signature (MonoMethodSignature
*sig
, MonoGenericContext
*context
)
2917 MonoInflatedMethodSignature helper
;
2918 MonoInflatedMethodSignature
*res
;
2923 helper
.context
.class_inst
= context
->class_inst
;
2924 helper
.context
.method_inst
= context
->method_inst
;
2926 collect_data_init (&data
);
2928 collect_inflated_signature_images (&helper
, &data
);
2930 set
= get_image_set (data
.images
, data
.nimages
);
2932 collect_data_free (&data
);
2934 mono_image_set_lock (set
);
2936 res
= (MonoInflatedMethodSignature
*)g_hash_table_lookup (set
->gsignature_cache
, &helper
);
2938 res
= g_new0 (MonoInflatedMethodSignature
, 1);
2940 res
->context
.class_inst
= context
->class_inst
;
2941 res
->context
.method_inst
= context
->method_inst
;
2942 g_hash_table_insert (set
->gsignature_cache
, res
, res
);
2945 mono_image_set_unlock (set
);
2951 mono_metadata_get_image_set_for_method (MonoMethodInflated
*method
)
2954 CollectData image_set_data
;
2956 collect_data_init (&image_set_data
);
2957 collect_method_images (method
, &image_set_data
);
2958 set
= get_image_set (image_set_data
.images
, image_set_data
.nimages
);
2959 collect_data_free (&image_set_data
);
2965 * mono_metadata_get_generic_inst:
2967 * Given a list of types, return a MonoGenericInst that represents that list.
2968 * The returned MonoGenericInst has its own copy of the list of types. The list
2969 * passed in the argument can be freed, modified or disposed of.
2973 mono_metadata_get_generic_inst (int type_argc
, MonoType
**type_argv
)
2975 MonoGenericInst
*ginst
;
2978 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
2980 for (i
= 0; i
< type_argc
; ++i
)
2981 if (mono_class_is_open_constructed_type (type_argv
[i
]))
2983 is_open
= (i
< type_argc
);
2985 ginst
= (MonoGenericInst
*)g_alloca (size
);
2986 memset (ginst
, 0, sizeof (MonoGenericInst
));
2987 ginst
->is_open
= is_open
;
2988 ginst
->type_argc
= type_argc
;
2989 memcpy (ginst
->type_argv
, type_argv
, type_argc
* sizeof (MonoType
*));
2991 return mono_metadata_get_canonical_generic_inst (ginst
);
2996 * mono_metadata_get_canonical_generic_inst:
2997 * @candidate: an arbitrary generic instantiation
2999 * Returns the canonical generic instantiation that represents the given
3000 * candidate by identifying the image set for the candidate instantiation and
3001 * finding the instance in the image set or adding a copy of the given instance
3004 * The returned MonoGenericInst has its own copy of the list of types. The list
3005 * passed in the argument can be freed, modified or disposed of.
3009 mono_metadata_get_canonical_generic_inst (MonoGenericInst
*candidate
)
3012 int type_argc
= candidate
->type_argc
;
3013 gboolean is_open
= candidate
->is_open
;
3016 collect_data_init (&data
);
3018 collect_ginst_images (candidate
, &data
);
3020 set
= get_image_set (data
.images
, data
.nimages
);
3022 collect_data_free (&data
);
3024 mono_image_set_lock (set
);
3026 MonoGenericInst
*ginst
= (MonoGenericInst
*)g_hash_table_lookup (set
->ginst_cache
, candidate
);
3028 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
3029 ginst
= (MonoGenericInst
*)mono_image_set_alloc0 (set
, size
);
3030 #ifndef MONO_SMALL_CONFIG
3031 ginst
->id
= ++next_generic_inst_id
;
3033 ginst
->is_open
= is_open
;
3034 ginst
->type_argc
= type_argc
;
3036 for (int i
= 0; i
< type_argc
; ++i
)
3037 ginst
->type_argv
[i
] = mono_metadata_type_dup (NULL
, candidate
->type_argv
[i
]);
3039 g_hash_table_insert (set
->ginst_cache
, ginst
, ginst
);
3042 mono_image_set_unlock (set
);
3047 mono_metadata_is_type_builder_generic_type_definition (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
3049 MonoGenericContainer
*container
= mono_class_get_generic_container (container_class
);
3051 if (!is_dynamic
|| container_class
->wastypebuilder
|| container
->type_argc
!= inst
->type_argc
)
3053 return inst
== container
->context
.class_inst
;
3057 * mono_metadata_lookup_generic_class:
3059 * Returns a MonoGenericClass with the given properties.
3063 mono_metadata_lookup_generic_class (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
3065 MonoGenericClass
*gclass
;
3066 MonoGenericClass helper
;
3067 gboolean is_tb_open
= mono_metadata_is_type_builder_generic_type_definition (container_class
, inst
, is_dynamic
);
3071 g_assert (mono_class_get_generic_container (container_class
)->type_argc
== inst
->type_argc
);
3073 memset (&helper
, 0, sizeof(helper
)); // act like g_new0
3074 helper
.container_class
= container_class
;
3075 helper
.context
.class_inst
= inst
;
3076 helper
.is_dynamic
= is_dynamic
; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
3077 helper
.is_tb_open
= is_tb_open
;
3079 collect_data_init (&data
);
3081 collect_gclass_images (&helper
, &data
);
3083 set
= get_image_set (data
.images
, data
.nimages
);
3085 collect_data_free (&data
);
3087 mono_image_set_lock (set
);
3089 gclass
= (MonoGenericClass
*)g_hash_table_lookup (set
->gclass_cache
, &helper
);
3091 /* A tripwire just to keep us honest */
3092 g_assert (!helper
.cached_class
);
3095 mono_image_set_unlock (set
);
3099 gclass
= mono_image_set_new0 (set
, MonoGenericClass
, 1);
3101 gclass
->is_dynamic
= 1;
3103 gclass
->is_tb_open
= is_tb_open
;
3104 gclass
->container_class
= container_class
;
3105 gclass
->context
.class_inst
= inst
;
3106 gclass
->context
.method_inst
= NULL
;
3107 gclass
->owner
= set
;
3108 if (inst
== mono_class_get_generic_container (container_class
)->context
.class_inst
&& !is_tb_open
)
3109 gclass
->cached_class
= container_class
;
3111 g_hash_table_insert (set
->gclass_cache
, gclass
, gclass
);
3113 mono_image_set_unlock (set
);
3119 * mono_metadata_inflate_generic_inst:
3121 * Instantiate the generic instance @ginst with the context @context.
3122 * Check @error for success.
3126 mono_metadata_inflate_generic_inst (MonoGenericInst
*ginst
, MonoGenericContext
*context
, MonoError
*error
)
3128 MonoType
**type_argv
;
3129 MonoGenericInst
*nginst
= NULL
;
3132 mono_error_init (error
);
3134 if (!ginst
->is_open
)
3137 type_argv
= g_new0 (MonoType
*, ginst
->type_argc
);
3139 for (i
= 0; i
< ginst
->type_argc
; i
++) {
3140 type_argv
[i
] = mono_class_inflate_generic_type_checked (ginst
->type_argv
[i
], context
, error
);
3141 if (!mono_error_ok (error
))
3146 nginst
= mono_metadata_get_generic_inst (ginst
->type_argc
, type_argv
);
3149 for (i
= 0; i
< count
; i
++)
3150 mono_metadata_free_type (type_argv
[i
]);
3157 mono_metadata_parse_generic_inst (MonoImage
*m
, MonoGenericContainer
*container
,
3158 int count
, const char *ptr
, const char **rptr
, MonoError
*error
)
3160 MonoType
**type_argv
;
3161 MonoGenericInst
*ginst
;
3164 mono_error_init (error
);
3165 type_argv
= g_new0 (MonoType
*, count
);
3167 for (i
= 0; i
< count
; i
++) {
3168 MonoType
*t
= mono_metadata_parse_type_checked (m
, container
, 0, FALSE
, ptr
, &ptr
, error
);
3179 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
3187 do_mono_metadata_parse_generic_class (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
3188 const char *ptr
, const char **rptr
, MonoError
*error
)
3190 MonoGenericInst
*inst
;
3195 mono_error_init (error
);
3197 // XXX how about transient?
3198 gtype
= mono_metadata_parse_type_checked (m
, NULL
, 0, FALSE
, ptr
, &ptr
, error
);
3202 gklass
= mono_class_from_mono_type (gtype
);
3203 if (!mono_class_is_gtd (gklass
)) {
3204 mono_error_set_bad_image (error
, m
, "Generic instance with non-generic definition");
3208 count
= mono_metadata_decode_value (ptr
, &ptr
);
3209 inst
= mono_metadata_parse_generic_inst (m
, container
, count
, ptr
, &ptr
, error
);
3216 type
->data
.generic_class
= mono_metadata_lookup_generic_class (gklass
, inst
, FALSE
);
3222 * @gc: The generic container to normalize
3223 * @type: The kind of generic parameters the resulting generic-container should contain
3226 static MonoGenericContainer
*
3227 select_container (MonoGenericContainer
*gc
, MonoTypeEnum type
)
3229 gboolean is_var
= (type
== MONO_TYPE_VAR
);
3233 g_assert (is_var
|| type
== MONO_TYPE_MVAR
);
3236 if (gc
->is_method
|| gc
->parent
)
3238 * The current MonoGenericContainer is a generic method -> its `parent'
3239 * points to the containing class'es container.
3247 MonoGenericContainer
*
3248 get_anonymous_container_for_image (MonoImage
*image
, gboolean is_mvar
)
3250 MonoGenericContainer
**container_pointer
;
3252 container_pointer
= &image
->anonymous_generic_method_container
;
3254 container_pointer
= &image
->anonymous_generic_class_container
;
3255 MonoGenericContainer
*result
= *container_pointer
;
3257 // This container has never been created; make it now.
3260 // Note this is never deallocated anywhere-- it exists for the lifetime of the image it's allocated from
3261 result
= (MonoGenericContainer
*)mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
3262 result
->owner
.image
= image
;
3263 result
->is_anonymous
= TRUE
;
3264 result
->is_small_param
= TRUE
;
3265 result
->is_method
= is_mvar
;
3267 // If another thread already made a container, use that and leak this new one.
3268 // (Technically it would currently be safe to just assign instead of CASing.)
3269 MonoGenericContainer
*exchange
= (MonoGenericContainer
*)InterlockedCompareExchangePointer ((volatile gpointer
*)container_pointer
, result
, NULL
);
3277 * mono_metadata_parse_generic_param:
3278 * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3279 * see mono_metadata_parse_type_checked() for details.
3280 * Internal routine to parse a generic type parameter.
3281 * LOCKING: Acquires the loader lock
3283 static MonoGenericParam
*
3284 mono_metadata_parse_generic_param (MonoImage
*m
, MonoGenericContainer
*generic_container
,
3285 MonoTypeEnum type
, const char *ptr
, const char **rptr
, MonoError
*error
)
3287 int index
= mono_metadata_decode_value (ptr
, &ptr
);
3291 mono_error_init (error
);
3293 generic_container
= select_container (generic_container
, type
);
3294 if (!generic_container
) {
3295 gboolean is_mvar
= FALSE
;
3300 case MONO_TYPE_MVAR
:
3304 g_error ("Cerating generic param object with invalid MonoType"); // This is not a generic param
3307 /* Create dummy MonoGenericParam */
3308 MonoGenericParam
*param
;
3310 param
= (MonoGenericParam
*)mono_image_alloc0 (m
, sizeof (MonoGenericParam
));
3312 param
->owner
= get_anonymous_container_for_image (m
, is_mvar
);
3317 if (index
>= generic_container
->type_argc
) {
3318 mono_error_set_bad_image (error
, m
, "Invalid generic %s parameter index %d, max index is %d",
3319 generic_container
->is_method
? "method" : "type",
3320 index
, generic_container
->type_argc
);
3324 //This can't return NULL
3325 return mono_generic_container_get_param (generic_container
, index
);
3329 * mono_metadata_get_shared_type:
3331 * Return a shared instance of TYPE, if available, NULL otherwise.
3332 * Shared MonoType instances help save memory. Their contents should not be modified
3333 * by the caller. They do not need to be freed as their lifetime is bound by either
3334 * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3335 * instance they are embedded in. If they are freed, they should be freed using
3336 * mono_metadata_free_type () instead of g_free ().
3339 mono_metadata_get_shared_type (MonoType
*type
)
3343 /* No need to use locking since nobody is modifying the hash table */
3344 if ((cached
= (MonoType
*)g_hash_table_lookup (type_cache
, type
)))
3347 switch (type
->type
){
3348 case MONO_TYPE_CLASS
:
3349 case MONO_TYPE_VALUETYPE
:
3350 if (type
== &type
->data
.klass
->byval_arg
)
3352 if (type
== &type
->data
.klass
->this_arg
)
3363 compare_type_literals (MonoImage
*image
, int class_type
, int type_type
, MonoError
*error
)
3365 mono_error_init (error
);
3367 /* byval_arg.type can be zero if we're decoding a type that references a class been loading.
3368 * See mcs/test/gtest-440. and #650936.
3369 * FIXME This better be moved to the metadata verifier as it can catch more cases.
3373 /* NET 1.1 assemblies might encode string and object in a denormalized way.
3376 if (class_type
== type_type
)
3379 if (type_type
== MONO_TYPE_CLASS
) {
3380 if (class_type
== MONO_TYPE_STRING
|| class_type
== MONO_TYPE_OBJECT
)
3382 //XXX stringify this argument
3383 mono_error_set_bad_image (error
, image
, "Expected reference type but got type kind %d", class_type
);
3387 g_assert (type_type
== MONO_TYPE_VALUETYPE
);
3388 switch (class_type
) {
3389 case MONO_TYPE_BOOLEAN
:
3390 case MONO_TYPE_CHAR
:
3403 case MONO_TYPE_CLASS
:
3406 //XXX stringify this argument
3407 mono_error_set_bad_image (error
, image
, "Expected value type but got type kind %d", class_type
);
3413 verify_var_type_and_container (MonoImage
*image
, int var_type
, MonoGenericContainer
*container
, MonoError
*error
)
3415 mono_error_init (error
);
3416 if (var_type
== MONO_TYPE_MVAR
) {
3417 if (!container
->is_method
) { //MVAR and a method container
3418 mono_error_set_bad_image (error
, image
, "MVAR parsed in a context without a method container");
3422 if (!(!container
->is_method
|| //VAR and class container
3423 (container
->is_method
&& container
->parent
))) { //VAR and method container with parent
3424 mono_error_set_bad_image (error
, image
, "VAR parsed in a context without a class container");
3432 * do_mono_metadata_parse_type:
3433 * @type: MonoType to be filled in with the return value
3435 * @generic_context: generics_context
3436 * @transient: whenever to allocate data from the heap
3437 * @ptr: pointer to the encoded type
3438 * @rptr: pointer where the end of the encoded type is saved
3440 * Internal routine used to "fill" the contents of @type from an
3441 * allocated pointer. This is done this way to avoid doing too
3442 * many mini-allocations (particularly for the MonoFieldType which
3443 * most of the time is just a MonoType, but sometimes might be augmented).
3445 * This routine is used by mono_metadata_parse_type and
3446 * mono_metadata_parse_field_type
3448 * This extracts a Type as specified in Partition II (22.2.12)
3450 * Returns: FALSE if the type could not be loaded
3453 do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
3454 gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
3456 mono_error_init (error
);
3458 type
->type
= (MonoTypeEnum
)mono_metadata_decode_value (ptr
, &ptr
);
3460 switch (type
->type
){
3461 case MONO_TYPE_VOID
:
3462 case MONO_TYPE_BOOLEAN
:
3463 case MONO_TYPE_CHAR
:
3476 case MONO_TYPE_STRING
:
3477 case MONO_TYPE_OBJECT
:
3478 case MONO_TYPE_TYPEDBYREF
:
3480 case MONO_TYPE_VALUETYPE
:
3481 case MONO_TYPE_CLASS
: {
3484 token
= mono_metadata_parse_typedef_or_ref (m
, ptr
, &ptr
);
3485 klass
= mono_class_get_checked (m
, token
, error
);
3486 type
->data
.klass
= klass
;
3490 if (!compare_type_literals (m
, klass
->byval_arg
.type
, type
->type
, error
))
3495 case MONO_TYPE_SZARRAY
: {
3496 MonoType
*etype
= mono_metadata_parse_type_checked (m
, container
, 0, transient
, ptr
, &ptr
, error
);
3500 type
->data
.klass
= mono_class_from_mono_type (etype
);
3503 mono_metadata_free_type (etype
);
3505 g_assert (type
->data
.klass
); //This was previously a check for NULL, but mcfmt should never fail. It can return a borken MonoClass, but should return at least something.
3508 case MONO_TYPE_PTR
: {
3509 type
->data
.type
= mono_metadata_parse_type_checked (m
, container
, 0, transient
, ptr
, &ptr
, error
);
3510 if (!type
->data
.type
)
3514 case MONO_TYPE_FNPTR
: {
3515 type
->data
.method
= mono_metadata_parse_method_signature_full (m
, container
, 0, ptr
, &ptr
, error
);
3516 if (!type
->data
.method
)
3520 case MONO_TYPE_ARRAY
: {
3521 type
->data
.array
= mono_metadata_parse_array_internal (m
, container
, transient
, ptr
, &ptr
, error
);
3522 if (!type
->data
.array
)
3526 case MONO_TYPE_MVAR
:
3527 case MONO_TYPE_VAR
: {
3528 if (container
&& !verify_var_type_and_container (m
, type
->type
, container
, error
))
3531 type
->data
.generic_param
= mono_metadata_parse_generic_param (m
, container
, type
->type
, ptr
, &ptr
, error
);
3532 if (!type
->data
.generic_param
)
3537 case MONO_TYPE_GENERICINST
: {
3538 if (!do_mono_metadata_parse_generic_class (type
, m
, container
, ptr
, &ptr
, error
))
3543 mono_error_set_bad_image (error
, m
, "type 0x%02x not handled in do_mono_metadata_parse_type on image %s", type
->type
, m
->name
);
3553 * mono_metadata_free_type:
3554 * @type: type to free
3556 * Free the memory allocated for type @type which is allocated on the heap.
3559 mono_metadata_free_type (MonoType
*type
)
3561 if (type
>= builtin_types
&& type
< builtin_types
+ NBUILTIN_TYPES ())
3564 switch (type
->type
){
3565 case MONO_TYPE_OBJECT
:
3566 case MONO_TYPE_STRING
:
3567 if (!type
->data
.klass
)
3570 case MONO_TYPE_CLASS
:
3571 case MONO_TYPE_VALUETYPE
:
3572 if (type
== &type
->data
.klass
->byval_arg
|| type
== &type
->data
.klass
->this_arg
)
3576 mono_metadata_free_type (type
->data
.type
);
3578 case MONO_TYPE_FNPTR
:
3579 mono_metadata_free_method_signature (type
->data
.method
);
3581 case MONO_TYPE_ARRAY
:
3582 mono_metadata_free_array (type
->data
.array
);
3593 hex_dump (const char *buffer
, int base
, int count
)
3595 int show_header
= 1;
3603 for (i
= 0; i
< count
; i
++){
3606 printf ("\n0x%08x: ", (unsigned char) base
+ i
);
3608 printf ("%02x ", (unsigned char) (buffer
[i
]));
3615 * @ptr: Points to the beginning of the Section Data (25.3)
3617 static MonoExceptionClause
*
3618 parse_section_data (MonoImage
*m
, int *num_clauses
, const unsigned char *ptr
, MonoError
*error
)
3620 unsigned char sect_data_flags
;
3622 guint32 sect_data_len
;
3623 MonoExceptionClause
* clauses
= NULL
;
3625 mono_error_init (error
);
3628 /* align on 32-bit boundary */
3629 ptr
= dword_align (ptr
);
3630 sect_data_flags
= *ptr
;
3633 is_fat
= sect_data_flags
& METHOD_HEADER_SECTION_FAT_FORMAT
;
3635 sect_data_len
= (ptr
[2] << 16) | (ptr
[1] << 8) | ptr
[0];
3638 sect_data_len
= ptr
[0];
3642 if (sect_data_flags
& METHOD_HEADER_SECTION_EHTABLE
) {
3643 const unsigned char *p
= dword_align (ptr
);
3645 *num_clauses
= is_fat
? sect_data_len
/ 24: sect_data_len
/ 12;
3646 /* we could just store a pointer if we don't need to byteswap */
3647 clauses
= (MonoExceptionClause
*)g_malloc0 (sizeof (MonoExceptionClause
) * (*num_clauses
));
3648 for (i
= 0; i
< *num_clauses
; ++i
) {
3649 MonoExceptionClause
*ec
= &clauses
[i
];
3652 ec
->flags
= read32 (p
);
3653 ec
->try_offset
= read32 (p
+ 4);
3654 ec
->try_len
= read32 (p
+ 8);
3655 ec
->handler_offset
= read32 (p
+ 12);
3656 ec
->handler_len
= read32 (p
+ 16);
3657 tof_value
= read32 (p
+ 20);
3660 ec
->flags
= read16 (p
);
3661 ec
->try_offset
= read16 (p
+ 2);
3662 ec
->try_len
= *(p
+ 4);
3663 ec
->handler_offset
= read16 (p
+ 5);
3664 ec
->handler_len
= *(p
+ 7);
3665 tof_value
= read32 (p
+ 8);
3668 if (ec
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
) {
3669 ec
->data
.filter_offset
= tof_value
;
3670 } else if (ec
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) {
3671 ec
->data
.catch_class
= NULL
;
3673 ec
->data
.catch_class
= mono_class_get_checked (m
, tof_value
, error
);
3674 if (!is_ok (error
)) {
3680 ec
->data
.catch_class
= NULL
;
3682 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
3686 if (sect_data_flags
& METHOD_HEADER_SECTION_MORE_SECTS
)
3687 ptr
+= sect_data_len
- 4; /* LAMESPEC: it seems the size includes the header */
3694 * mono_method_get_header_summary:
3695 * @method: The method to get the header.
3696 * @summary: Where to store the header
3699 * Returns: TRUE if the header was properly decoded.
3702 mono_method_get_header_summary (MonoMethod
*method
, MonoMethodHeaderSummary
*summary
)
3708 unsigned char flags
, format
;
3711 /*Only the GMD has a pointer to the metadata.*/
3712 while (method
->is_inflated
)
3713 method
= ((MonoMethodInflated
*)method
)->declaring
;
3715 summary
->code_size
= 0;
3716 summary
->has_clauses
= FALSE
;
3718 /*FIXME extract this into a MACRO and share it with mono_method_get_header*/
3719 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
))
3722 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| method
->sre_method
) {
3723 MonoMethodHeader
*header
= ((MonoMethodWrapper
*)method
)->header
;
3726 summary
->code_size
= header
->code_size
;
3727 summary
->has_clauses
= header
->num_clauses
> 0;
3732 idx
= mono_metadata_token_index (method
->token
);
3733 img
= method
->klass
->image
;
3734 rva
= mono_metadata_decode_row_col (&img
->tables
[MONO_TABLE_METHOD
], idx
- 1, MONO_METHOD_RVA
);
3736 /*We must run the verifier since we'll be decoding it.*/
3737 if (!mono_verifier_verify_method_header (img
, rva
, NULL
))
3740 ptr
= mono_image_rva_map (img
, rva
);
3744 flags
= *(const unsigned char *)ptr
;
3745 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
3748 case METHOD_HEADER_TINY_FORMAT
:
3750 summary
->code_size
= flags
>> 2;
3752 case METHOD_HEADER_FAT_FORMAT
:
3753 fat_flags
= read16 (ptr
);
3755 summary
->code_size
= read32 (ptr
);
3756 if (fat_flags
& METHOD_HEADER_MORE_SECTS
)
3757 summary
->has_clauses
= TRUE
;
3766 * mono_metadata_parse_mh_full:
3767 * @m: metadata context
3768 * @generic_context: generics context
3769 * @ptr: pointer to the method header.
3771 * Decode the method header at @ptr, including pointer to the IL code,
3772 * info about local variables and optional exception tables.
3773 * This is a Mono runtime internal function.
3775 * LOCKING: Acquires the loader lock.
3777 * Returns: a transient MonoMethodHeader allocated from the heap.
3780 mono_metadata_parse_mh_full (MonoImage
*m
, MonoGenericContainer
*container
, const char *ptr
, MonoError
*error
)
3782 MonoMethodHeader
*mh
= NULL
;
3783 unsigned char flags
= *(const unsigned char *) ptr
;
3784 unsigned char format
= flags
& METHOD_HEADER_FORMAT_MASK
;
3786 guint32 local_var_sig_tok
, max_stack
, code_size
, init_locals
;
3787 const unsigned char *code
;
3788 MonoExceptionClause
* clauses
= NULL
;
3789 int num_clauses
= 0;
3790 MonoTableInfo
*t
= &m
->tables
[MONO_TABLE_STANDALONESIG
];
3791 guint32 cols
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
3793 mono_error_init (error
);
3796 mono_error_set_bad_image (error
, m
, "Method header with null pointer");
3801 case METHOD_HEADER_TINY_FORMAT
:
3802 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
);
3805 mh
->is_transient
= TRUE
;
3806 local_var_sig_tok
= 0;
3807 mh
->code_size
= flags
>> 2;
3808 mh
->code
= (unsigned char*)ptr
;
3810 case METHOD_HEADER_FAT_FORMAT
:
3811 fat_flags
= read16 (ptr
);
3813 max_stack
= read16 (ptr
);
3815 code_size
= read32 (ptr
);
3817 local_var_sig_tok
= read32 (ptr
);
3820 if (fat_flags
& METHOD_HEADER_INIT_LOCALS
)
3825 code
= (unsigned char*)ptr
;
3827 if (!(fat_flags
& METHOD_HEADER_MORE_SECTS
))
3831 * There are more sections
3833 ptr
= (char*)code
+ code_size
;
3836 mono_error_set_bad_image (error
, m
, "Invalid method header format %d", format
);
3840 if (local_var_sig_tok
) {
3841 int idx
= (local_var_sig_tok
& 0xffffff)-1;
3842 if (idx
>= t
->rows
|| idx
< 0) {
3843 mono_error_set_bad_image (error
, m
, "Invalid method header local vars signature token 0x%8x", idx
);
3846 mono_metadata_decode_row (t
, idx
, cols
, 1);
3848 if (!mono_verifier_verify_standalone_signature (m
, cols
[MONO_STAND_ALONE_SIGNATURE
], NULL
)) {
3849 mono_error_set_bad_image (error
, m
, "Method header locals signature 0x%8x verification failed", idx
);
3853 if (fat_flags
& METHOD_HEADER_MORE_SECTS
) {
3854 clauses
= parse_section_data (m
, &num_clauses
, (const unsigned char*)ptr
, error
);
3858 if (local_var_sig_tok
) {
3859 const char *locals_ptr
;
3862 locals_ptr
= mono_metadata_blob_heap (m
, cols
[MONO_STAND_ALONE_SIGNATURE
]);
3863 mono_metadata_decode_blob_size (locals_ptr
, &locals_ptr
);
3864 if (*locals_ptr
!= 0x07)
3865 g_warning ("wrong signature for locals blob");
3867 len
= mono_metadata_decode_value (locals_ptr
, &locals_ptr
);
3868 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ len
* sizeof (MonoType
*) + num_clauses
* sizeof (MonoExceptionClause
));
3869 mh
->num_locals
= len
;
3870 for (i
= 0; i
< len
; ++i
) {
3871 mh
->locals
[i
] = mono_metadata_parse_type_internal (m
, container
, 0, TRUE
, locals_ptr
, &locals_ptr
, error
);
3876 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ num_clauses
* sizeof (MonoExceptionClause
));
3879 mh
->code_size
= code_size
;
3880 mh
->max_stack
= max_stack
;
3881 mh
->is_transient
= TRUE
;
3882 mh
->init_locals
= init_locals
;
3884 MonoExceptionClause
* clausesp
= (MonoExceptionClause
*)&mh
->locals
[mh
->num_locals
];
3885 memcpy (clausesp
, clauses
, num_clauses
* sizeof (MonoExceptionClause
));
3887 mh
->clauses
= clausesp
;
3888 mh
->num_clauses
= num_clauses
;
3899 * mono_metadata_parse_mh:
3900 * @generic_context: generics context
3901 * @ptr: pointer to the method header.
3903 * Decode the method header at @ptr, including pointer to the IL code,
3904 * info about local variables and optional exception tables.
3906 * Returns: a transient MonoMethodHeader allocated from the heap.
3909 mono_metadata_parse_mh (MonoImage
*m
, const char *ptr
)
3912 MonoMethodHeader
*header
= mono_metadata_parse_mh_full (m
, NULL
, ptr
, &error
);
3913 mono_error_cleanup (&error
);
3918 * mono_metadata_free_mh:
3919 * @mh: a method header
3921 * Free the memory allocated for the method header.
3924 mono_metadata_free_mh (MonoMethodHeader
*mh
)
3928 /* If it is not transient it means it's part of a wrapper method,
3929 * or a SRE-generated method, so the lifetime in that case is
3930 * dictated by the method's own lifetime
3932 if (mh
->is_transient
) {
3933 for (i
= 0; i
< mh
->num_locals
; ++i
)
3934 mono_metadata_free_type (mh
->locals
[i
]);
3940 * mono_method_header_get_code:
3941 * @header: a MonoMethodHeader pointer
3942 * @code_size: memory location for returning the code size
3943 * @max_stack: memory location for returning the max stack
3945 * Method header accessor to retreive info about the IL code properties:
3946 * a pointer to the IL code itself, the size of the code and the max number
3947 * of stack slots used by the code.
3949 * Returns: pointer to the IL code represented by the method header.
3951 const unsigned char*
3952 mono_method_header_get_code (MonoMethodHeader
*header
, guint32
* code_size
, guint32
* max_stack
)
3955 *code_size
= header
->code_size
;
3957 *max_stack
= header
->max_stack
;
3958 return header
->code
;
3962 * mono_method_header_get_locals:
3963 * @header: a MonoMethodHeader pointer
3964 * @num_locals: memory location for returning the number of local variables
3965 * @init_locals: memory location for returning the init_locals flag
3967 * Method header accessor to retreive info about the local variables:
3968 * an array of local types, the number of locals and whether the locals
3969 * are supposed to be initialized to 0 on method entry
3971 * Returns: pointer to an array of types of the local variables
3974 mono_method_header_get_locals (MonoMethodHeader
*header
, guint32
* num_locals
, gboolean
*init_locals
)
3977 *num_locals
= header
->num_locals
;
3979 *init_locals
= header
->init_locals
;
3980 return header
->locals
;
3984 * mono_method_header_get_num_clauses:
3985 * @header: a MonoMethodHeader pointer
3987 * Method header accessor to retreive the number of exception clauses.
3989 * Returns: the number of exception clauses present
3992 mono_method_header_get_num_clauses (MonoMethodHeader
*header
)
3994 return header
->num_clauses
;
3998 * mono_method_header_get_clauses:
3999 * @header: a MonoMethodHeader pointer
4000 * @method: MonoMethod the header belongs to
4001 * @iter: pointer to a iterator
4002 * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
4004 * Get the info about the exception clauses in the method. Set *iter to NULL to
4005 * initiate the iteration, then call the method repeatedly until it returns FALSE.
4006 * At each iteration, the structure pointed to by clause if filled with the
4007 * exception clause information.
4009 * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
4013 mono_method_header_get_clauses (MonoMethodHeader
*header
, MonoMethod
*method
, gpointer
*iter
, MonoExceptionClause
*clause
)
4015 MonoExceptionClause
*sc
;
4016 /* later we'll be able to use this interface to parse the clause info on demand,
4017 * without allocating anything.
4019 if (!iter
|| !header
->num_clauses
)
4022 *iter
= sc
= header
->clauses
;
4026 sc
= (MonoExceptionClause
*)*iter
;
4028 if (sc
< header
->clauses
+ header
->num_clauses
) {
4037 * mono_metadata_parse_field_type:
4038 * @m: metadata context to extract information from
4039 * @ptr: pointer to the field signature
4040 * @rptr: pointer updated to match the end of the decoded stream
4042 * Parses the field signature, and returns the type information for it.
4044 * Returns: The MonoType that was extracted from @ptr.
4047 mono_metadata_parse_field_type (MonoImage
*m
, short field_flags
, const char *ptr
, const char **rptr
)
4050 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, field_flags
, FALSE
, ptr
, rptr
, &error
);
4051 mono_error_cleanup (&error
);
4056 * mono_metadata_parse_param:
4057 * @m: metadata context to extract information from
4058 * @ptr: pointer to the param signature
4059 * @rptr: pointer updated to match the end of the decoded stream
4061 * Parses the param signature, and returns the type information for it.
4063 * Returns: The MonoType that was extracted from @ptr.
4066 mono_metadata_parse_param (MonoImage
*m
, const char *ptr
, const char **rptr
)
4069 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, 0, FALSE
, ptr
, rptr
, &error
);
4070 mono_error_cleanup (&error
);
4075 * mono_metadata_token_from_dor:
4076 * @dor_token: A TypeDefOrRef coded index
4078 * dor_token is a TypeDefOrRef coded index: it contains either
4079 * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
4080 * bits contain an index into the table.
4082 * Returns: an expanded token
4085 mono_metadata_token_from_dor (guint32 dor_index
)
4089 table
= dor_index
& 0x03;
4090 idx
= dor_index
>> 2;
4093 case 0: /* TypeDef */
4094 return MONO_TOKEN_TYPE_DEF
| idx
;
4095 case 1: /* TypeRef */
4096 return MONO_TOKEN_TYPE_REF
| idx
;
4097 case 2: /* TypeSpec */
4098 return MONO_TOKEN_TYPE_SPEC
| idx
;
4100 g_assert_not_reached ();
4107 * We use this to pass context information to the row locator
4110 int idx
; /* The index that we are trying to locate */
4111 int col_idx
; /* The index in the row where idx may be stored */
4112 MonoTableInfo
*t
; /* pointer to the table */
4117 * How the row locator works.
4122 * ___|___------> _______
4125 * A column in the rows of table A references an index in table B.
4126 * For example A may be the TYPEDEF table and B the METHODDEF table.
4128 * Given an index in table B we want to get the row in table A
4129 * where the column n references our index in B.
4131 * In the locator_t structure:
4133 * col_idx is the column number
4134 * index is the index in table B
4135 * result will be the index in table A
4138 * Table A Table B column (in table A)
4139 * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
4140 * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
4141 * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
4142 * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
4143 * METHODSEM PROPERTY ASSOCIATION (encoded index)
4145 * Note that we still don't support encoded indexes.
4149 typedef_locator (const void *a
, const void *b
)
4151 locator_t
*loc
= (locator_t
*) a
;
4152 const char *bb
= (const char *) b
;
4153 int typedef_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4154 guint32 col
, col_next
;
4156 col
= mono_metadata_decode_row_col (loc
->t
, typedef_index
, loc
->col_idx
);
4162 * Need to check that the next row is valid.
4164 if (typedef_index
+ 1 < loc
->t
->rows
) {
4165 col_next
= mono_metadata_decode_row_col (loc
->t
, typedef_index
+ 1, loc
->col_idx
);
4166 if (loc
->idx
>= col_next
)
4169 if (col
== col_next
)
4173 loc
->result
= typedef_index
;
4179 table_locator (const void *a
, const void *b
)
4181 locator_t
*loc
= (locator_t
*) a
;
4182 const char *bb
= (const char *) b
;
4183 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4186 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
4188 if (loc
->idx
== col
) {
4189 loc
->result
= table_index
;
4199 declsec_locator (const void *a
, const void *b
)
4201 locator_t
*loc
= (locator_t
*) a
;
4202 const char *bb
= (const char *) b
;
4203 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4206 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
4208 if (loc
->idx
== col
) {
4209 loc
->result
= table_index
;
4221 * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
4222 * which contains IDX.
4225 search_ptr_table (MonoImage
*image
, int table
, int idx
)
4227 MonoTableInfo
*ptrdef
= &image
->tables
[table
];
4230 /* Use a linear search to find our index in the table */
4231 for (i
= 0; i
< ptrdef
->rows
; i
++)
4232 /* All the Ptr tables have the same structure */
4233 if (mono_metadata_decode_row_col (ptrdef
, i
, 0) == idx
)
4236 if (i
< ptrdef
->rows
)
4243 * mono_metadata_typedef_from_field:
4244 * @meta: metadata context
4245 * @index: FieldDef token
4247 * Returns: the 1-based index into the TypeDef table of the type that
4248 * declared the field described by @index, or 0 if not found.
4251 mono_metadata_typedef_from_field (MonoImage
*meta
, guint32 index
)
4253 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
4259 loc
.idx
= mono_metadata_token_index (index
);
4260 loc
.col_idx
= MONO_TYPEDEF_FIELD_LIST
;
4263 if (meta
->uncompressed_metadata
)
4264 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
4266 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
4269 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4270 return loc
.result
+ 1;
4274 * mono_metadata_typedef_from_method:
4275 * @meta: metadata context
4276 * @index: MethodDef token
4278 * Returns: the 1-based index into the TypeDef table of the type that
4279 * declared the method described by @index. 0 if not found.
4282 mono_metadata_typedef_from_method (MonoImage
*meta
, guint32 index
)
4284 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
4290 loc
.idx
= mono_metadata_token_index (index
);
4291 loc
.col_idx
= MONO_TYPEDEF_METHOD_LIST
;
4294 if (meta
->uncompressed_metadata
)
4295 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_METHOD_POINTER
, loc
.idx
);
4297 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
4300 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4301 return loc
.result
+ 1;
4305 * mono_metadata_interfaces_from_typedef_full:
4306 * @meta: metadata context
4307 * @index: typedef token
4308 * @interfaces: Out parameter used to store the interface array
4309 * @count: Out parameter used to store the number of interfaces
4310 * @heap_alloc_result: if TRUE the result array will be g_malloc'd
4311 * @context: The generic context
4313 * The array of interfaces that the @index typedef token implements is returned in
4314 * @interfaces. The number of elements in the array is returned in @count.
4317 * Returns: TRUE on success, FALSE on failure.
4320 mono_metadata_interfaces_from_typedef_full (MonoImage
*meta
, guint32 index
, MonoClass
***interfaces
, guint
*count
, gboolean heap_alloc_result
, MonoGenericContext
*context
, MonoError
*error
)
4322 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_INTERFACEIMPL
];
4325 guint32 cols
[MONO_INTERFACEIMPL_SIZE
];
4331 mono_error_init (error
);
4336 loc
.idx
= mono_metadata_token_index (index
);
4337 loc
.col_idx
= MONO_INTERFACEIMPL_CLASS
;
4340 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4345 * We may end up in the middle of the rows...
4348 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_INTERFACEIMPL_CLASS
))
4354 while (pos
< tdef
->rows
) {
4355 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
4356 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
4361 if (heap_alloc_result
)
4362 result
= g_new0 (MonoClass
*, pos
- start
);
4364 result
= (MonoClass
**)mono_image_alloc0 (meta
, sizeof (MonoClass
*) * (pos
- start
));
4367 while (pos
< tdef
->rows
) {
4370 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
4371 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
4373 iface
= mono_class_get_and_inflate_typespec_checked (
4374 meta
, mono_metadata_token_from_dor (cols
[MONO_INTERFACEIMPL_INTERFACE
]), context
, error
);
4377 result
[pos
- start
] = iface
;
4380 *count
= pos
- start
;
4381 *interfaces
= result
;
4386 * @meta: metadata context
4387 * @index: typedef token
4388 * @count: Out parameter used to store the number of interfaces
4390 * The array of interfaces that the @index typedef token implements is returned in
4391 * @interfaces. The number of elements in the array is returned in @count. The returned
4392 * array is g_malloc'd and the caller must free it.
4394 * LOCKING: Acquires the loader lock .
4396 * Returns: the interface array on success, NULL on failure.
4400 mono_metadata_interfaces_from_typedef (MonoImage
*meta
, guint32 index
, guint
*count
)
4403 MonoClass
**interfaces
= NULL
;
4406 rv
= mono_metadata_interfaces_from_typedef_full (meta
, index
, &interfaces
, count
, TRUE
, NULL
, &error
);
4407 g_assert (mono_error_ok (&error
)); /* FIXME dont swallow the error */
4415 * mono_metadata_nested_in_typedef:
4416 * @meta: metadata context
4417 * @index: typedef token
4419 * Returns: the 1-based index into the TypeDef table of the type
4420 * where the type described by @index is nested.
4421 * Returns 0 if @index describes a non-nested type.
4424 mono_metadata_nested_in_typedef (MonoImage
*meta
, guint32 index
)
4426 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4432 loc
.idx
= mono_metadata_token_index (index
);
4433 loc
.col_idx
= MONO_NESTED_CLASS_NESTED
;
4436 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4439 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4440 return mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_NESTED_CLASS_ENCLOSING
) | MONO_TOKEN_TYPE_DEF
;
4444 * mono_metadata_nesting_typedef:
4445 * @meta: metadata context
4446 * @index: typedef token
4448 * Returns: the 1-based index into the TypeDef table of the first type
4449 * that is nested inside the type described by @index. The search starts at
4450 * @start_index. returns 0 if no such type is found.
4453 mono_metadata_nesting_typedef (MonoImage
*meta
, guint32 index
, guint32 start_index
)
4455 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4457 guint32 class_index
= mono_metadata_token_index (index
);
4462 start
= start_index
;
4464 while (start
<= tdef
->rows
) {
4465 if (class_index
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_NESTED_CLASS_ENCLOSING
))
4471 if (start
> tdef
->rows
)
4478 * mono_metadata_packing_from_typedef:
4479 * @meta: metadata context
4480 * @index: token representing a type
4482 * Returns: the info stored in the ClassLAyout table for the given typedef token
4483 * into the @packing and @size pointers.
4484 * Returns 0 if the info is not found.
4487 mono_metadata_packing_from_typedef (MonoImage
*meta
, guint32 index
, guint32
*packing
, guint32
*size
)
4489 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CLASSLAYOUT
];
4491 guint32 cols
[MONO_CLASS_LAYOUT_SIZE
];
4496 loc
.idx
= mono_metadata_token_index (index
);
4497 loc
.col_idx
= MONO_CLASS_LAYOUT_PARENT
;
4500 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4503 mono_metadata_decode_row (tdef
, loc
.result
, cols
, MONO_CLASS_LAYOUT_SIZE
);
4505 *packing
= cols
[MONO_CLASS_LAYOUT_PACKING_SIZE
];
4507 *size
= cols
[MONO_CLASS_LAYOUT_CLASS_SIZE
];
4509 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4510 return loc
.result
+ 1;
4514 * mono_metadata_custom_attrs_from_index:
4515 * @meta: metadata context
4516 * @index: token representing the parent
4518 * Returns: the 1-based index into the CustomAttribute table of the first
4519 * attribute which belongs to the metadata object described by @index.
4520 * Returns 0 if no such attribute is found.
4523 mono_metadata_custom_attrs_from_index (MonoImage
*meta
, guint32 index
)
4525 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4532 loc
.col_idx
= MONO_CUSTOM_ATTR_PARENT
;
4535 /* FIXME: Index translation */
4537 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4540 /* Find the first entry by searching backwards */
4541 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_CUSTOM_ATTR_PARENT
) == index
))
4544 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4545 return loc
.result
+ 1;
4549 * mono_metadata_declsec_from_index:
4550 * @meta: metadata context
4551 * @index: token representing the parent
4553 * Returns: the 0-based index into the DeclarativeSecurity table of the first
4554 * attribute which belongs to the metadata object described by @index.
4555 * Returns -1 if no such attribute is found.
4558 mono_metadata_declsec_from_index (MonoImage
*meta
, guint32 index
)
4560 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_DECLSECURITY
];
4567 loc
.col_idx
= MONO_DECL_SECURITY_PARENT
;
4570 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, declsec_locator
))
4573 /* Find the first entry by searching backwards */
4574 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_DECL_SECURITY_PARENT
) == index
))
4581 * mono_metadata_localscope_from_methoddef:
4582 * @meta: metadata context
4583 * @index: methoddef index
4585 * Returns: the 1-based index into the LocalScope table of the first
4586 * scope which belongs to the method described by @index.
4587 * Returns 0 if no such row is found.
4590 mono_metadata_localscope_from_methoddef (MonoImage
*meta
, guint32 index
)
4592 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_LOCALSCOPE
];
4599 loc
.col_idx
= MONO_LOCALSCOPE_METHOD
;
4602 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4605 /* Find the first entry by searching backwards */
4606 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_LOCALSCOPE_METHOD
) == index
))
4609 return loc
.result
+ 1;
4614 mono_backtrace (int limit
)
4619 backtrace (array
, limit
);
4620 names
= backtrace_symbols (array
, limit
);
4621 for (i
=0; i
< limit
; ++i
) {
4622 g_print ("\t%s\n", names
[i
]);
4628 static int i8_align
;
4631 * mono_type_set_alignment:
4633 * Set the alignment used by runtime to layout fields etc. of type TYPE to ALIGN.
4634 * This should only be used in AOT mode since the resulting layout will not match the
4638 mono_type_set_alignment (MonoTypeEnum type
, int align
)
4640 /* Support only a few types whose alignment is abi dependent */
4646 g_assert_not_reached ();
4653 * @t: the type to return the size of
4655 * Returns: the number of bytes required to hold an instance of this
4659 mono_type_size (MonoType
*t
, int *align
)
4661 MonoTypeEnum simple_type
;
4668 *align
= MONO_ABI_ALIGNOF (gpointer
);
4669 return MONO_ABI_SIZEOF (gpointer
);
4672 simple_type
= t
->type
;
4674 switch (simple_type
) {
4675 case MONO_TYPE_VOID
:
4678 case MONO_TYPE_BOOLEAN
:
4679 *align
= MONO_ABI_ALIGNOF (gint8
);
4683 *align
= MONO_ABI_ALIGNOF (gint8
);
4685 case MONO_TYPE_CHAR
:
4688 *align
= MONO_ABI_ALIGNOF (gint16
);
4692 *align
= MONO_ABI_ALIGNOF (gint32
);
4695 *align
= MONO_ABI_ALIGNOF (float);
4699 *align
= MONO_ABI_ALIGNOF (gint64
);
4702 *align
= MONO_ABI_ALIGNOF (double);
4706 *align
= MONO_ABI_ALIGNOF (gpointer
);
4707 return MONO_ABI_SIZEOF (gpointer
);
4708 case MONO_TYPE_VALUETYPE
: {
4709 if (t
->data
.klass
->enumtype
)
4710 return mono_type_size (mono_class_enum_basetype (t
->data
.klass
), align
);
4712 return mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
4714 case MONO_TYPE_STRING
:
4715 case MONO_TYPE_OBJECT
:
4716 case MONO_TYPE_CLASS
:
4717 case MONO_TYPE_SZARRAY
:
4719 case MONO_TYPE_FNPTR
:
4720 case MONO_TYPE_ARRAY
:
4721 *align
= MONO_ABI_ALIGNOF (gpointer
);
4722 return MONO_ABI_SIZEOF (gpointer
);
4723 case MONO_TYPE_TYPEDBYREF
:
4724 return mono_class_value_size (mono_defaults
.typed_reference_class
, (guint32
*)align
);
4725 case MONO_TYPE_GENERICINST
: {
4726 MonoGenericClass
*gclass
= t
->data
.generic_class
;
4727 MonoClass
*container_class
= gclass
->container_class
;
4729 // g_assert (!gclass->inst->is_open);
4731 if (container_class
->valuetype
) {
4732 if (container_class
->enumtype
)
4733 return mono_type_size (mono_class_enum_basetype (container_class
), align
);
4735 return mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
4737 *align
= MONO_ABI_ALIGNOF (gpointer
);
4738 return MONO_ABI_SIZEOF (gpointer
);
4742 case MONO_TYPE_MVAR
:
4743 if (!t
->data
.generic_param
->gshared_constraint
|| t
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_VALUETYPE
) {
4744 *align
= MONO_ABI_ALIGNOF (gpointer
);
4745 return MONO_ABI_SIZEOF (gpointer
);
4747 /* The gparam can only match types given by gshared_constraint */
4748 return mono_type_size (t
->data
.generic_param
->gshared_constraint
, align
);
4752 g_error ("mono_type_size: type 0x%02x unknown", t
->type
);
4758 * mono_type_stack_size:
4759 * @t: the type to return the size it uses on the stack
4761 * Returns: the number of bytes required to hold an instance of this
4762 * type on the runtime stack
4765 mono_type_stack_size (MonoType
*t
, int *align
)
4767 return mono_type_stack_size_internal (t
, align
, FALSE
);
4771 mono_type_stack_size_internal (MonoType
*t
, int *align
, gboolean allow_open
)
4774 MonoTypeEnum simple_type
;
4775 #if SIZEOF_VOID_P == SIZEOF_REGISTER
4776 int stack_slot_size
= MONO_ABI_SIZEOF (gpointer
);
4777 int stack_slot_align
= MONO_ABI_ALIGNOF (gpointer
);
4778 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
4779 int stack_slot_size
= SIZEOF_REGISTER
;
4780 int stack_slot_align
= SIZEOF_REGISTER
;
4783 g_assert (t
!= NULL
);
4789 *align
= stack_slot_align
;
4790 return stack_slot_size
;
4793 simple_type
= t
->type
;
4794 switch (simple_type
) {
4795 case MONO_TYPE_BOOLEAN
:
4796 case MONO_TYPE_CHAR
:
4805 case MONO_TYPE_STRING
:
4806 case MONO_TYPE_OBJECT
:
4807 case MONO_TYPE_CLASS
:
4808 case MONO_TYPE_SZARRAY
:
4810 case MONO_TYPE_FNPTR
:
4811 case MONO_TYPE_ARRAY
:
4812 *align
= stack_slot_align
;
4813 return stack_slot_size
;
4815 case MONO_TYPE_MVAR
:
4816 g_assert (allow_open
);
4817 if (!t
->data
.generic_param
->gshared_constraint
|| t
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_VALUETYPE
) {
4818 *align
= stack_slot_align
;
4819 return stack_slot_size
;
4821 /* The gparam can only match types given by gshared_constraint */
4822 return mono_type_stack_size_internal (t
->data
.generic_param
->gshared_constraint
, align
, allow_open
);
4824 case MONO_TYPE_TYPEDBYREF
:
4825 *align
= stack_slot_align
;
4826 return stack_slot_size
* 3;
4828 *align
= MONO_ABI_ALIGNOF (float);
4829 return sizeof (float);
4832 *align
= MONO_ABI_ALIGNOF (gint64
);
4833 return sizeof (gint64
);
4835 *align
= MONO_ABI_ALIGNOF (double);
4836 return sizeof (double);
4837 case MONO_TYPE_VALUETYPE
: {
4840 if (t
->data
.klass
->enumtype
)
4841 return mono_type_stack_size_internal (mono_class_enum_basetype (t
->data
.klass
), align
, allow_open
);
4843 size
= mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
4845 *align
= *align
+ stack_slot_align
- 1;
4846 *align
&= ~(stack_slot_align
- 1);
4848 size
+= stack_slot_size
- 1;
4849 size
&= ~(stack_slot_size
- 1);
4854 case MONO_TYPE_GENERICINST
: {
4855 MonoGenericClass
*gclass
= t
->data
.generic_class
;
4856 MonoClass
*container_class
= gclass
->container_class
;
4859 g_assert (!gclass
->context
.class_inst
->is_open
);
4861 if (container_class
->valuetype
) {
4862 if (container_class
->enumtype
)
4863 return mono_type_stack_size_internal (mono_class_enum_basetype (container_class
), align
, allow_open
);
4865 guint32 size
= mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
4867 *align
= *align
+ stack_slot_align
- 1;
4868 *align
&= ~(stack_slot_align
- 1);
4870 size
+= stack_slot_size
- 1;
4871 size
&= ~(stack_slot_size
- 1);
4876 *align
= stack_slot_align
;
4877 return stack_slot_size
;
4881 g_error ("type 0x%02x unknown", t
->type
);
4887 mono_type_generic_inst_is_valuetype (MonoType
*type
)
4889 g_assert (type
->type
== MONO_TYPE_GENERICINST
);
4890 return type
->data
.generic_class
->container_class
->valuetype
;
4894 mono_metadata_generic_class_is_valuetype (MonoGenericClass
*gclass
)
4896 return gclass
->container_class
->valuetype
;
4900 _mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
, gboolean signature_only
)
4902 MonoGenericInst
*i1
= g1
->context
.class_inst
;
4903 MonoGenericInst
*i2
= g2
->context
.class_inst
;
4905 if (g1
->is_dynamic
!= g2
->is_dynamic
)
4907 if (!mono_metadata_class_equal (g1
->container_class
, g2
->container_class
, signature_only
))
4909 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
4911 return g1
->is_tb_open
== g2
->is_tb_open
;
4915 _mono_metadata_generic_class_container_equal (const MonoGenericClass
*g1
, MonoClass
*c2
, gboolean signature_only
)
4917 MonoGenericInst
*i1
= g1
->context
.class_inst
;
4918 MonoGenericInst
*i2
= mono_class_get_generic_container (c2
)->context
.class_inst
;
4920 if (!mono_metadata_class_equal (g1
->container_class
, c2
, signature_only
))
4922 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
4924 return !g1
->is_tb_open
;
4928 mono_metadata_generic_context_hash (const MonoGenericContext
*context
)
4930 /* FIXME: check if this seed is good enough */
4931 guint hash
= 0xc01dfee7;
4932 if (context
->class_inst
)
4933 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->class_inst
);
4934 if (context
->method_inst
)
4935 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->method_inst
);
4940 mono_metadata_generic_context_equal (const MonoGenericContext
*g1
, const MonoGenericContext
*g2
)
4942 return g1
->class_inst
== g2
->class_inst
&& g1
->method_inst
== g2
->method_inst
;
4946 * mono_metadata_str_hash:
4948 * This should be used instead of g_str_hash for computing hash codes visible
4949 * outside this module, since g_str_hash () is not guaranteed to be stable
4950 * (its not the same in eglib for example).
4953 mono_metadata_str_hash (gconstpointer v1
)
4955 /* Same as g_str_hash () in glib */
4956 char *p
= (char *) v1
;
4961 hash
= (hash
<< 5) - hash
+ *p
;
4968 * mono_metadata_type_hash:
4971 * Computes an hash value for @t1 to be used in GHashTable.
4972 * The returned hash is guaranteed to be the same across executions.
4975 mono_metadata_type_hash (MonoType
*t1
)
4977 guint hash
= t1
->type
;
4979 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
4981 case MONO_TYPE_VALUETYPE
:
4982 case MONO_TYPE_CLASS
:
4983 case MONO_TYPE_SZARRAY
: {
4984 MonoClass
*klass
= t1
->data
.klass
;
4986 * Dynamic classes must not be hashed on their type since it can change
4987 * during runtime. For example, if we hash a reference type that is
4988 * later made into a valuetype.
4990 * This is specially problematic with generic instances since they are
4991 * inserted in a bunch of hash tables before been finished.
4993 if (image_is_dynamic (klass
->image
))
4994 return (t1
->byref
<< 6) | mono_metadata_str_hash (klass
->name
);
4995 return ((hash
<< 5) - hash
) ^ mono_metadata_str_hash (klass
->name
);
4998 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (t1
->data
.type
);
4999 case MONO_TYPE_ARRAY
:
5000 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (&t1
->data
.array
->eklass
->byval_arg
);
5001 case MONO_TYPE_GENERICINST
:
5002 return ((hash
<< 5) - hash
) ^ mono_generic_class_hash (t1
->data
.generic_class
);
5004 case MONO_TYPE_MVAR
:
5005 return ((hash
<< 5) - hash
) ^ mono_metadata_generic_param_hash (t1
->data
.generic_param
);
5012 mono_metadata_generic_param_hash (MonoGenericParam
*p
)
5015 MonoGenericParamInfo
*info
;
5017 hash
= (mono_generic_param_num (p
) << 2);
5018 if (p
->gshared_constraint
)
5019 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (p
->gshared_constraint
);
5020 info
= mono_generic_param_info (p
);
5021 /* Can't hash on the owner klass/method, since those might not be set when this is called */
5023 hash
= ((hash
<< 5) - hash
) ^ info
->token
;
5028 mono_metadata_generic_param_equal_internal (MonoGenericParam
*p1
, MonoGenericParam
*p2
, gboolean signature_only
)
5032 if (mono_generic_param_num (p1
) != mono_generic_param_num (p2
))
5034 if (p1
->gshared_constraint
&& p2
->gshared_constraint
) {
5035 if (!mono_metadata_type_equal (p1
->gshared_constraint
, p2
->gshared_constraint
))
5038 if (p1
->gshared_constraint
!= p2
->gshared_constraint
)
5043 * We have to compare the image as well because if we didn't,
5044 * the generic_inst_cache lookup wouldn't care about the image
5045 * of generic params, so what could happen is that a generic
5046 * inst with params from image A is put into the cache, then
5047 * image B gets that generic inst from the cache, image A is
5048 * unloaded, so the inst is deleted, but image B still retains
5051 if (mono_generic_param_owner (p1
) == mono_generic_param_owner (p2
))
5055 * If `signature_only' is true, we're comparing two (method) signatures.
5056 * In this case, the owner of two type parameters doesn't need to match.
5059 return signature_only
;
5063 mono_metadata_generic_param_equal (MonoGenericParam
*p1
, MonoGenericParam
*p2
)
5065 return mono_metadata_generic_param_equal_internal (p1
, p2
, TRUE
);
5069 mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
)
5073 if (mono_class_is_ginst (c1
) && mono_class_is_ginst (c2
))
5074 return _mono_metadata_generic_class_equal (mono_class_get_generic_class (c1
), mono_class_get_generic_class (c2
), signature_only
);
5075 if (mono_class_is_ginst (c1
) && mono_class_is_gtd (c2
))
5076 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c1
), c2
, signature_only
);
5077 if (mono_class_is_gtd (c1
) && mono_class_is_ginst (c2
))
5078 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c2
), c1
, signature_only
);
5079 if ((c1
->byval_arg
.type
== MONO_TYPE_VAR
) && (c2
->byval_arg
.type
== MONO_TYPE_VAR
))
5080 return mono_metadata_generic_param_equal_internal (
5081 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
5082 if ((c1
->byval_arg
.type
== MONO_TYPE_MVAR
) && (c2
->byval_arg
.type
== MONO_TYPE_MVAR
))
5083 return mono_metadata_generic_param_equal_internal (
5084 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
5085 if (signature_only
&&
5086 (c1
->byval_arg
.type
== MONO_TYPE_SZARRAY
) && (c2
->byval_arg
.type
== MONO_TYPE_SZARRAY
))
5087 return mono_metadata_class_equal (c1
->byval_arg
.data
.klass
, c2
->byval_arg
.data
.klass
, signature_only
);
5088 if (signature_only
&&
5089 (c1
->byval_arg
.type
== MONO_TYPE_ARRAY
) && (c2
->byval_arg
.type
== MONO_TYPE_ARRAY
))
5090 return do_mono_metadata_type_equal (&c1
->byval_arg
, &c2
->byval_arg
, signature_only
);
5095 mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
)
5097 gpointer iter1
= 0, iter2
= 0;
5101 if (s1
->call_convention
!= s2
->call_convention
)
5103 if (s1
->sentinelpos
!= s2
->sentinelpos
)
5105 if (s1
->hasthis
!= s2
->hasthis
)
5107 if (s1
->explicit_this
!= s2
->explicit_this
)
5109 if (! do_mono_metadata_type_equal (s1
->ret
, s2
->ret
, signature_only
))
5111 if (s1
->param_count
!= s2
->param_count
)
5115 MonoType
*t1
= mono_signature_get_params (s1
, &iter1
);
5116 MonoType
*t2
= mono_signature_get_params (s2
, &iter2
);
5118 if (t1
== NULL
|| t2
== NULL
)
5120 if (! do_mono_metadata_type_equal (t1
, t2
, signature_only
))
5126 * mono_metadata_type_equal:
5129 * @signature_only: If true, treat ginsts as equal which are instantiated separately but have equal positional value
5131 * Determine if @t1 and @t2 represent the same type.
5132 * Returns: #TRUE if @t1 and @t2 are equal.
5135 do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
5137 if (t1
->type
!= t2
->type
|| t1
->byref
!= t2
->byref
)
5141 case MONO_TYPE_VOID
:
5142 case MONO_TYPE_BOOLEAN
:
5143 case MONO_TYPE_CHAR
:
5154 case MONO_TYPE_STRING
:
5157 case MONO_TYPE_OBJECT
:
5158 case MONO_TYPE_TYPEDBYREF
:
5160 case MONO_TYPE_VALUETYPE
:
5161 case MONO_TYPE_CLASS
:
5162 case MONO_TYPE_SZARRAY
:
5163 return mono_metadata_class_equal (t1
->data
.klass
, t2
->data
.klass
, signature_only
);
5165 return do_mono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
, signature_only
);
5166 case MONO_TYPE_ARRAY
:
5167 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
5169 return mono_metadata_class_equal (t1
->data
.array
->eklass
, t2
->data
.array
->eklass
, signature_only
);
5170 case MONO_TYPE_GENERICINST
:
5171 return _mono_metadata_generic_class_equal (
5172 t1
->data
.generic_class
, t2
->data
.generic_class
, signature_only
);
5174 return mono_metadata_generic_param_equal_internal (
5175 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
5176 case MONO_TYPE_MVAR
:
5177 return mono_metadata_generic_param_equal_internal (
5178 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
5179 case MONO_TYPE_FNPTR
:
5180 return mono_metadata_fnptr_equal (t1
->data
.method
, t2
->data
.method
, signature_only
);
5182 g_error ("implement type compare for %0x!", t1
->type
);
5190 mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
5192 return do_mono_metadata_type_equal (t1
, t2
, FALSE
);
5196 * mono_metadata_type_equal_full:
5199 * @signature_only: if signature only comparison should be made
5201 * Determine if @t1 and @t2 are signature compatible if @signature_only is #TRUE, otherwise
5202 * behaves the same way as mono_metadata_type_equal.
5203 * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
5204 * Returns: #TRUE if @t1 and @t2 are equal taking @signature_only into account.
5207 mono_metadata_type_equal_full (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
5209 return do_mono_metadata_type_equal (t1
, t2
, signature_only
);
5213 * mono_metadata_signature_equal:
5214 * @sig1: a signature
5215 * @sig2: another signature
5217 * Determine if @sig1 and @sig2 represent the same signature, with the
5218 * same number of arguments and the same types.
5219 * Returns: #TRUE if @sig1 and @sig2 are equal.
5222 mono_metadata_signature_equal (MonoMethodSignature
*sig1
, MonoMethodSignature
*sig2
)
5226 if (sig1
->hasthis
!= sig2
->hasthis
|| sig1
->param_count
!= sig2
->param_count
)
5229 if (sig1
->generic_param_count
!= sig2
->generic_param_count
)
5233 * We're just comparing the signatures of two methods here:
5235 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
5236 * U and V are equal here.
5238 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
5241 for (i
= 0; i
< sig1
->param_count
; i
++) {
5242 MonoType
*p1
= sig1
->params
[i
];
5243 MonoType
*p2
= sig2
->params
[i
];
5245 /* if (p1->attrs != p2->attrs)
5248 if (!do_mono_metadata_type_equal (p1
, p2
, TRUE
))
5252 if (!do_mono_metadata_type_equal (sig1
->ret
, sig2
->ret
, TRUE
))
5258 * mono_metadata_type_dup:
5259 * @image: image to alloc memory from
5260 * @original: type to duplicate
5262 * Returns: copy of type allocated from the image's mempool (or from the heap, if @image is null).
5265 mono_metadata_type_dup (MonoImage
*image
, const MonoType
*o
)
5268 int sizeof_o
= MONO_SIZEOF_TYPE
;
5270 sizeof_o
+= o
->num_mods
* sizeof (MonoCustomMod
);
5272 r
= image
? (MonoType
*)mono_image_alloc0 (image
, sizeof_o
) : (MonoType
*)g_malloc (sizeof_o
);
5274 memcpy (r
, o
, sizeof_o
);
5276 if (o
->type
== MONO_TYPE_PTR
) {
5277 r
->data
.type
= mono_metadata_type_dup (image
, o
->data
.type
);
5278 } else if (o
->type
== MONO_TYPE_ARRAY
) {
5279 r
->data
.array
= mono_dup_array_type (image
, o
->data
.array
);
5280 } else if (o
->type
== MONO_TYPE_FNPTR
) {
5281 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
5282 r
->data
.method
= mono_metadata_signature_deep_dup (image
, o
->data
.method
);
5288 mono_signature_hash (MonoMethodSignature
*sig
)
5290 guint i
, res
= sig
->ret
->type
;
5292 for (i
= 0; i
< sig
->param_count
; i
++)
5293 res
= (res
<< 5) - res
+ mono_type_hash (sig
->params
[i
]);
5299 * mono_metadata_encode_value:
5300 * @value: value to encode
5301 * @buf: buffer where to write the compressed representation
5302 * @endbuf: pointer updated to point at the end of the encoded output
5304 * Encodes the value @value in the compressed representation used
5305 * in metadata and stores the result in @buf. @buf needs to be big
5306 * enough to hold the data (4 bytes).
5309 mono_metadata_encode_value (guint32 value
, char *buf
, char **endbuf
)
5315 else if (value
< 0x4000) {
5316 p
[0] = 0x80 | (value
>> 8);
5317 p
[1] = value
& 0xff;
5320 p
[0] = (value
>> 24) | 0xc0;
5321 p
[1] = (value
>> 16) & 0xff;
5322 p
[2] = (value
>> 8) & 0xff;
5323 p
[3] = value
& 0xff;
5331 * mono_metadata_field_info:
5332 * @meta: the Image the field is defined in
5333 * @index: the index in the field table representing the field
5334 * @offset: a pointer to an integer where to store the offset that
5335 * may have been specified for the field in a FieldLayout table
5336 * @rva: a pointer to the RVA of the field data in the image that
5337 * may have been defined in a FieldRVA table
5338 * @marshal_spec: a pointer to the marshal spec that may have been
5339 * defined for the field in a FieldMarshal table.
5341 * Gather info for field @index that may have been defined in the FieldLayout,
5342 * FieldRVA and FieldMarshal tables.
5343 * Either of offset, rva and marshal_spec can be NULL if you're not interested
5347 mono_metadata_field_info (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5348 MonoMarshalSpec
**marshal_spec
)
5350 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, FALSE
);
5354 mono_metadata_field_info_with_mempool (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5355 MonoMarshalSpec
**marshal_spec
)
5357 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, TRUE
);
5361 mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5362 MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
)
5364 MonoTableInfo
*tdef
;
5367 loc
.idx
= index
+ 1;
5368 if (meta
->uncompressed_metadata
)
5369 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
5372 tdef
= &meta
->tables
[MONO_TABLE_FIELDLAYOUT
];
5374 loc
.col_idx
= MONO_FIELD_LAYOUT_FIELD
;
5377 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5378 *offset
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_LAYOUT_OFFSET
);
5380 *offset
= (guint32
)-1;
5384 tdef
= &meta
->tables
[MONO_TABLE_FIELDRVA
];
5386 loc
.col_idx
= MONO_FIELD_RVA_FIELD
;
5389 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5391 * LAMESPEC: There is no signature, no nothing, just the raw data.
5393 *rva
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_RVA_RVA
);
5401 if ((p
= mono_metadata_get_marshal_info (meta
, index
, TRUE
))) {
5402 *marshal_spec
= mono_metadata_parse_marshal_spec_full (alloc_from_image
? meta
: NULL
, meta
, p
);
5409 * mono_metadata_get_constant_index:
5410 * @meta: the Image the field is defined in
5411 * @index: the token that may have a row defined in the constants table
5412 * @hint: possible position for the row
5414 * @token must be a FieldDef, ParamDef or PropertyDef token.
5416 * Returns: the index into the Constants table or 0 if not found.
5419 mono_metadata_get_constant_index (MonoImage
*meta
, guint32 token
, guint32 hint
)
5421 MonoTableInfo
*tdef
;
5423 guint32 index
= mono_metadata_token_index (token
);
5425 tdef
= &meta
->tables
[MONO_TABLE_CONSTANT
];
5426 index
<<= MONO_HASCONSTANT_BITS
;
5427 switch (mono_metadata_token_table (token
)) {
5428 case MONO_TABLE_FIELD
:
5429 index
|= MONO_HASCONSTANT_FIEDDEF
;
5431 case MONO_TABLE_PARAM
:
5432 index
|= MONO_HASCONSTANT_PARAM
;
5434 case MONO_TABLE_PROPERTY
:
5435 index
|= MONO_HASCONSTANT_PROPERTY
;
5438 g_warning ("Not a valid token for the constant table: 0x%08x", token
);
5442 loc
.col_idx
= MONO_CONSTANT_PARENT
;
5445 /* FIXME: Index translation */
5447 if ((hint
> 0) && (hint
< tdef
->rows
) && (mono_metadata_decode_row_col (tdef
, hint
- 1, MONO_CONSTANT_PARENT
) == index
))
5450 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5451 return loc
.result
+ 1;
5457 * mono_metadata_events_from_typedef:
5458 * @meta: metadata context
5459 * @index: 0-based index (in the TypeDef table) describing a type
5461 * Returns: the 0-based index in the Event table for the events in the
5462 * type. The last event that belongs to the type (plus 1) is stored
5463 * in the @end_idx pointer.
5466 mono_metadata_events_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5470 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_EVENTMAP
];
5478 loc
.col_idx
= MONO_EVENT_MAP_PARENT
;
5479 loc
.idx
= index
+ 1;
5481 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5484 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_EVENT_MAP_EVENTLIST
);
5485 if (loc
.result
+ 1 < tdef
->rows
) {
5486 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_EVENT_MAP_EVENTLIST
) - 1;
5488 end
= meta
->tables
[MONO_TABLE_EVENT
].rows
;
5496 * mono_metadata_methods_from_event:
5497 * @meta: metadata context
5498 * @index: 0-based index (in the Event table) describing a event
5500 * Returns: the 0-based index in the MethodDef table for the methods in the
5501 * event. The last method that belongs to the event (plus 1) is stored
5502 * in the @end_idx pointer.
5505 mono_metadata_methods_from_event (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5509 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
5510 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
5516 if (meta
->uncompressed_metadata
)
5517 index
= search_ptr_table (meta
, MONO_TABLE_EVENT_POINTER
, index
+ 1) - 1;
5520 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
5521 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
; /* Method association coded index */
5523 if (!mono_binary_search (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
5528 * We may end up in the middle of the rows...
5531 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
5537 while (end
< msemt
->rows
) {
5538 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
5539 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
5548 * mono_metadata_properties_from_typedef:
5549 * @meta: metadata context
5550 * @index: 0-based index (in the TypeDef table) describing a type
5552 * Returns: the 0-based index in the Property table for the properties in the
5553 * type. The last property that belongs to the type (plus 1) is stored
5554 * in the @end_idx pointer.
5557 mono_metadata_properties_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5561 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_PROPERTYMAP
];
5569 loc
.col_idx
= MONO_PROPERTY_MAP_PARENT
;
5570 loc
.idx
= index
+ 1;
5572 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5575 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_PROPERTY_MAP_PROPERTY_LIST
);
5576 if (loc
.result
+ 1 < tdef
->rows
) {
5577 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_PROPERTY_MAP_PROPERTY_LIST
) - 1;
5579 end
= meta
->tables
[MONO_TABLE_PROPERTY
].rows
;
5587 * mono_metadata_methods_from_property:
5588 * @meta: metadata context
5589 * @index: 0-based index (in the PropertyDef table) describing a property
5591 * Returns: the 0-based index in the MethodDef table for the methods in the
5592 * property. The last method that belongs to the property (plus 1) is stored
5593 * in the @end_idx pointer.
5596 mono_metadata_methods_from_property (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5600 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
5601 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
5607 if (meta
->uncompressed_metadata
)
5608 index
= search_ptr_table (meta
, MONO_TABLE_PROPERTY_POINTER
, index
+ 1) - 1;
5611 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
5612 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
; /* Method association coded index */
5614 if (!mono_binary_search (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
5619 * We may end up in the middle of the rows...
5622 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
5628 while (end
< msemt
->rows
) {
5629 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
5630 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
5639 mono_metadata_implmap_from_method (MonoImage
*meta
, guint32 method_idx
)
5642 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_IMPLMAP
];
5647 /* No index translation seems to be needed */
5650 loc
.col_idx
= MONO_IMPLMAP_MEMBER
;
5651 loc
.idx
= ((method_idx
+ 1) << MONO_MEMBERFORWD_BITS
) | MONO_MEMBERFORWD_METHODDEF
;
5653 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5656 return loc
.result
+ 1;
5660 * @image: context where the image is created
5661 * @type_spec: typespec token
5662 * @deprecated use mono_type_create_from_typespec_checked that has proper error handling
5664 * Creates a MonoType representing the TypeSpec indexed by the @type_spec
5668 mono_type_create_from_typespec (MonoImage
*image
, guint32 type_spec
)
5671 MonoType
*type
= mono_type_create_from_typespec_checked (image
, type_spec
, &error
);
5673 g_error ("Could not create typespec %x due to %s", type_spec
, mono_error_get_message (&error
));
5678 mono_type_create_from_typespec_checked (MonoImage
*image
, guint32 type_spec
, MonoError
*error
)
5681 guint32 idx
= mono_metadata_token_index (type_spec
);
5683 guint32 cols
[MONO_TYPESPEC_SIZE
];
5685 MonoType
*type
, *type2
;
5687 mono_error_init (error
);
5689 mono_image_lock (image
);
5690 type
= (MonoType
*)g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
5691 mono_image_unlock (image
);
5695 t
= &image
->tables
[MONO_TABLE_TYPESPEC
];
5697 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPESPEC_SIZE
);
5698 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_TYPESPEC_SIGNATURE
]);
5700 if (!mono_verifier_verify_typespec_signature (image
, cols
[MONO_TYPESPEC_SIGNATURE
], type_spec
, NULL
)) {
5701 mono_error_set_bad_image (error
, image
, "Could not verify type spec %08x.", type_spec
);
5705 mono_metadata_decode_value (ptr
, &ptr
);
5707 type
= mono_metadata_parse_type_checked (image
, NULL
, 0, TRUE
, ptr
, &ptr
, error
);
5711 type2
= mono_metadata_type_dup (image
, type
);
5712 mono_metadata_free_type (type
);
5714 mono_image_lock (image
);
5715 type
= (MonoType
*)g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
5716 /* We might leak some data in the image mempool if found */
5718 g_hash_table_insert (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
), type2
);
5721 mono_image_unlock (image
);
5728 mono_image_strndup (MonoImage
*image
, const char *data
, guint len
)
5732 return g_strndup (data
, len
);
5733 res
= (char *)mono_image_alloc (image
, len
+ 1);
5734 memcpy (res
, data
, len
);
5740 mono_metadata_parse_marshal_spec (MonoImage
*image
, const char *ptr
)
5742 return mono_metadata_parse_marshal_spec_full (NULL
, image
, ptr
);
5746 * If IMAGE is non-null, memory will be allocated from its mempool, otherwise it will be allocated using malloc.
5747 * PARENT_IMAGE is the image containing the marshal spec.
5750 mono_metadata_parse_marshal_spec_full (MonoImage
*image
, MonoImage
*parent_image
, const char *ptr
)
5752 MonoMarshalSpec
*res
;
5754 const char *start
= ptr
;
5756 /* fixme: this is incomplete, but I cant find more infos in the specs */
5759 res
= (MonoMarshalSpec
*)mono_image_alloc0 (image
, sizeof (MonoMarshalSpec
));
5761 res
= g_new0 (MonoMarshalSpec
, 1);
5763 len
= mono_metadata_decode_value (ptr
, &ptr
);
5764 res
->native
= (MonoMarshalNative
)*ptr
++;
5766 if (res
->native
== MONO_NATIVE_LPARRAY
) {
5767 res
->data
.array_data
.param_num
= -1;
5768 res
->data
.array_data
.num_elem
= -1;
5769 res
->data
.array_data
.elem_mult
= -1;
5771 if (ptr
- start
<= len
)
5772 res
->data
.array_data
.elem_type
= (MonoMarshalNative
)*ptr
++;
5773 if (ptr
- start
<= len
)
5774 res
->data
.array_data
.param_num
= mono_metadata_decode_value (ptr
, &ptr
);
5775 if (ptr
- start
<= len
)
5776 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5777 if (ptr
- start
<= len
) {
5779 * LAMESPEC: Older spec versions say this parameter comes before
5780 * num_elem. Never spec versions don't talk about elem_mult at
5781 * all, but csc still emits it, and it is used to distinguish
5782 * between param_num being 0, and param_num being omitted.
5783 * So if (param_num == 0) && (num_elem > 0), then
5784 * elem_mult == 0 -> the array size is num_elem
5785 * elem_mult == 1 -> the array size is @param_num + num_elem
5787 res
->data
.array_data
.elem_mult
= mono_metadata_decode_value (ptr
, &ptr
);
5791 if (res
->native
== MONO_NATIVE_BYVALTSTR
) {
5792 if (ptr
- start
<= len
)
5793 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5796 if (res
->native
== MONO_NATIVE_BYVALARRAY
) {
5797 if (ptr
- start
<= len
)
5798 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5801 if (res
->native
== MONO_NATIVE_CUSTOM
) {
5802 /* skip unused type guid */
5803 len
= mono_metadata_decode_value (ptr
, &ptr
);
5805 /* skip unused native type name */
5806 len
= mono_metadata_decode_value (ptr
, &ptr
);
5808 /* read custom marshaler type name */
5809 len
= mono_metadata_decode_value (ptr
, &ptr
);
5810 res
->data
.custom_data
.custom_name
= mono_image_strndup (image
, ptr
, len
);
5812 /* read cookie string */
5813 len
= mono_metadata_decode_value (ptr
, &ptr
);
5814 res
->data
.custom_data
.cookie
= mono_image_strndup (image
, ptr
, len
);
5815 res
->data
.custom_data
.image
= parent_image
;
5818 if (res
->native
== MONO_NATIVE_SAFEARRAY
) {
5819 res
->data
.safearray_data
.elem_type
= (MonoMarshalVariant
)0;
5820 res
->data
.safearray_data
.num_elem
= 0;
5821 if (ptr
- start
<= len
)
5822 res
->data
.safearray_data
.elem_type
= (MonoMarshalVariant
)*ptr
++;
5823 if (ptr
- start
<= len
)
5824 res
->data
.safearray_data
.num_elem
= *ptr
++;
5830 mono_metadata_free_marshal_spec (MonoMarshalSpec
*spec
)
5832 if (spec
->native
== MONO_NATIVE_CUSTOM
) {
5833 g_free (spec
->data
.custom_data
.custom_name
);
5834 g_free (spec
->data
.custom_data
.cookie
);
5840 * mono_type_to_unmanaged:
5842 * Returns: A MonoMarshalNative enumeration value (MONO_NATIVE_) value
5843 * describing the underlying native reprensetation of the type.
5845 * In addition the value pointed by
5846 * "conv" will contain the kind of marshalling required for this
5847 * particular type one of the MONO_MARSHAL_CONV_ enumeration values.
5850 mono_type_to_unmanaged (MonoType
*type
, MonoMarshalSpec
*mspec
, gboolean as_field
,
5851 gboolean unicode
, MonoMarshalConv
*conv
)
5853 MonoMarshalConv dummy_conv
;
5859 *conv
= MONO_MARSHAL_CONV_NONE
;
5862 return MONO_NATIVE_UINT
;
5866 case MONO_TYPE_BOOLEAN
:
5868 switch (mspec
->native
) {
5869 case MONO_NATIVE_VARIANTBOOL
:
5870 *conv
= MONO_MARSHAL_CONV_BOOL_VARIANTBOOL
;
5871 return MONO_NATIVE_VARIANTBOOL
;
5872 case MONO_NATIVE_BOOLEAN
:
5873 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
5874 return MONO_NATIVE_BOOLEAN
;
5875 case MONO_NATIVE_I1
:
5876 case MONO_NATIVE_U1
:
5877 return mspec
->native
;
5879 g_error ("cant marshal bool to native type %02x", mspec
->native
);
5882 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
5883 return MONO_NATIVE_BOOLEAN
;
5884 case MONO_TYPE_CHAR
:
5886 switch (mspec
->native
) {
5887 case MONO_NATIVE_U2
:
5888 case MONO_NATIVE_U1
:
5889 return mspec
->native
;
5891 g_error ("cant marshal char to native type %02x", mspec
->native
);
5894 return unicode
? MONO_NATIVE_U2
: MONO_NATIVE_U1
;
5895 case MONO_TYPE_I1
: return MONO_NATIVE_I1
;
5896 case MONO_TYPE_U1
: return MONO_NATIVE_U1
;
5897 case MONO_TYPE_I2
: return MONO_NATIVE_I2
;
5898 case MONO_TYPE_U2
: return MONO_NATIVE_U2
;
5899 case MONO_TYPE_I4
: return MONO_NATIVE_I4
;
5900 case MONO_TYPE_U4
: return MONO_NATIVE_U4
;
5901 case MONO_TYPE_I8
: return MONO_NATIVE_I8
;
5902 case MONO_TYPE_U8
: return MONO_NATIVE_U8
;
5903 case MONO_TYPE_R4
: return MONO_NATIVE_R4
;
5904 case MONO_TYPE_R8
: return MONO_NATIVE_R8
;
5905 case MONO_TYPE_STRING
:
5907 switch (mspec
->native
) {
5908 case MONO_NATIVE_BSTR
:
5909 *conv
= MONO_MARSHAL_CONV_STR_BSTR
;
5910 return MONO_NATIVE_BSTR
;
5911 case MONO_NATIVE_LPSTR
:
5912 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
5913 return MONO_NATIVE_LPSTR
;
5914 case MONO_NATIVE_LPWSTR
:
5915 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
5916 return MONO_NATIVE_LPWSTR
;
5917 case MONO_NATIVE_LPTSTR
:
5918 *conv
= MONO_MARSHAL_CONV_STR_LPTSTR
;
5919 return MONO_NATIVE_LPTSTR
;
5920 case MONO_NATIVE_ANSIBSTR
:
5921 *conv
= MONO_MARSHAL_CONV_STR_ANSIBSTR
;
5922 return MONO_NATIVE_ANSIBSTR
;
5923 case MONO_NATIVE_TBSTR
:
5924 *conv
= MONO_MARSHAL_CONV_STR_TBSTR
;
5925 return MONO_NATIVE_TBSTR
;
5926 case MONO_NATIVE_UTF8STR
:
5927 *conv
= MONO_MARSHAL_CONV_STR_UTF8STR
;
5928 return MONO_NATIVE_UTF8STR
;
5929 case MONO_NATIVE_BYVALTSTR
:
5931 *conv
= MONO_MARSHAL_CONV_STR_BYVALWSTR
;
5933 *conv
= MONO_MARSHAL_CONV_STR_BYVALSTR
;
5934 return MONO_NATIVE_BYVALTSTR
;
5936 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
);
5940 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
5941 return MONO_NATIVE_LPWSTR
;
5944 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
5945 return MONO_NATIVE_LPSTR
;
5947 case MONO_TYPE_PTR
: return MONO_NATIVE_UINT
;
5948 case MONO_TYPE_VALUETYPE
: /*FIXME*/
5949 if (type
->data
.klass
->enumtype
) {
5950 t
= mono_class_enum_basetype (type
->data
.klass
)->type
;
5953 if (type
->data
.klass
== mono_defaults
.handleref_class
){
5954 *conv
= MONO_MARSHAL_CONV_HANDLEREF
;
5955 return MONO_NATIVE_INT
;
5957 return MONO_NATIVE_STRUCT
;
5958 case MONO_TYPE_SZARRAY
:
5959 case MONO_TYPE_ARRAY
:
5961 switch (mspec
->native
) {
5962 case MONO_NATIVE_BYVALARRAY
:
5963 if ((type
->data
.klass
->element_class
== mono_defaults
.char_class
) && !unicode
)
5964 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY
;
5966 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALARRAY
;
5967 return MONO_NATIVE_BYVALARRAY
;
5968 case MONO_NATIVE_SAFEARRAY
:
5969 *conv
= MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
;
5970 return MONO_NATIVE_SAFEARRAY
;
5971 case MONO_NATIVE_LPARRAY
:
5972 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
5973 return MONO_NATIVE_LPARRAY
;
5975 g_error ("cant marshal array as native type %02x", mspec
->native
);
5979 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
5980 return MONO_NATIVE_LPARRAY
;
5981 case MONO_TYPE_I
: return MONO_NATIVE_INT
;
5982 case MONO_TYPE_U
: return MONO_NATIVE_UINT
;
5983 case MONO_TYPE_CLASS
:
5984 case MONO_TYPE_OBJECT
: {
5985 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
5987 switch (mspec
->native
) {
5988 case MONO_NATIVE_STRUCT
:
5989 return MONO_NATIVE_STRUCT
;
5990 case MONO_NATIVE_CUSTOM
:
5991 return MONO_NATIVE_CUSTOM
;
5992 case MONO_NATIVE_INTERFACE
:
5993 *conv
= MONO_MARSHAL_CONV_OBJECT_INTERFACE
;
5994 return MONO_NATIVE_INTERFACE
;
5995 case MONO_NATIVE_IDISPATCH
:
5996 *conv
= MONO_MARSHAL_CONV_OBJECT_IDISPATCH
;
5997 return MONO_NATIVE_IDISPATCH
;
5998 case MONO_NATIVE_IUNKNOWN
:
5999 *conv
= MONO_MARSHAL_CONV_OBJECT_IUNKNOWN
;
6000 return MONO_NATIVE_IUNKNOWN
;
6001 case MONO_NATIVE_FUNC
:
6002 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
6003 type
->data
.klass
== mono_defaults
.delegate_class
||
6004 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
6005 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
6006 return MONO_NATIVE_FUNC
;
6010 g_error ("cant marshal object as native type %02x", mspec
->native
);
6013 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
6014 type
->data
.klass
== mono_defaults
.delegate_class
||
6015 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
6016 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
6017 return MONO_NATIVE_FUNC
;
6019 if (mono_class_try_get_safehandle_class () && type
->data
.klass
== mono_class_try_get_safehandle_class ()){
6020 *conv
= MONO_MARSHAL_CONV_SAFEHANDLE
;
6021 return MONO_NATIVE_INT
;
6023 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
6024 return MONO_NATIVE_STRUCT
;
6026 case MONO_TYPE_FNPTR
: return MONO_NATIVE_FUNC
;
6027 case MONO_TYPE_GENERICINST
:
6028 type
= &type
->data
.generic_class
->container_class
->byval_arg
;
6031 case MONO_TYPE_TYPEDBYREF
:
6033 g_error ("type 0x%02x not handled in marshal", t
);
6035 return MONO_NATIVE_MAX
;
6039 mono_metadata_get_marshal_info (MonoImage
*meta
, guint32 idx
, gboolean is_field
)
6042 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_FIELDMARSHAL
];
6048 loc
.col_idx
= MONO_FIELD_MARSHAL_PARENT
;
6049 loc
.idx
= ((idx
+ 1) << MONO_HAS_FIELD_MARSHAL_BITS
) | (is_field
? MONO_HAS_FIELD_MARSHAL_FIELDSREF
: MONO_HAS_FIELD_MARSHAL_PARAMDEF
);
6051 /* FIXME: Index translation */
6053 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6056 return mono_metadata_blob_heap (meta
, mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_MARSHAL_NATIVE_TYPE
));
6060 method_from_method_def_or_ref (MonoImage
*m
, guint32 tok
, MonoGenericContext
*context
, MonoError
*error
)
6062 MonoMethod
*result
= NULL
;
6063 guint32 idx
= tok
>> MONO_METHODDEFORREF_BITS
;
6065 mono_error_init (error
);
6067 switch (tok
& MONO_METHODDEFORREF_MASK
) {
6068 case MONO_METHODDEFORREF_METHODDEF
:
6069 result
= mono_get_method_checked (m
, MONO_TOKEN_METHOD_DEF
| idx
, NULL
, context
, error
);
6071 case MONO_METHODDEFORREF_METHODREF
:
6072 result
= mono_get_method_checked (m
, MONO_TOKEN_MEMBER_REF
| idx
, NULL
, context
, error
);
6075 mono_error_set_bad_image (error
, m
, "Invalid MethodDefOfRef token %x", tok
);
6082 * mono_class_get_overrides_full:
6084 * Return the method overrides belonging to class @type_token in @overrides, and
6085 * the number of overrides in @num_overrides.
6087 * Returns: TRUE on success, FALSE on failure.
6090 mono_class_get_overrides_full (MonoImage
*image
, guint32 type_token
, MonoMethod
***overrides
, gint32
*num_overrides
,
6091 MonoGenericContext
*generic_context
)
6095 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_METHODIMPL
];
6098 guint32 cols
[MONO_METHODIMPL_SIZE
];
6099 MonoMethod
**result
;
6110 loc
.col_idx
= MONO_METHODIMPL_CLASS
;
6111 loc
.idx
= mono_metadata_token_index (type_token
);
6113 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6119 * We may end up in the middle of the rows...
6122 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_METHODIMPL_CLASS
))
6127 while (end
< tdef
->rows
) {
6128 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, end
, MONO_METHODIMPL_CLASS
))
6134 result
= g_new (MonoMethod
*, num
* 2);
6135 for (i
= 0; i
< num
; ++i
) {
6138 if (!mono_verifier_verify_methodimpl_row (image
, start
+ i
, &error
)) {
6139 mono_error_cleanup (&error
); /* FIXME don't swallow the error */
6144 mono_metadata_decode_row (tdef
, start
+ i
, cols
, MONO_METHODIMPL_SIZE
);
6145 method
= method_from_method_def_or_ref (
6146 image
, cols
[MONO_METHODIMPL_DECLARATION
], generic_context
, &error
);
6147 if (method
== NULL
) {
6148 mono_error_cleanup (&error
); /* FIXME don't swallow the error */
6151 result
[i
* 2] = method
;
6152 method
= method_from_method_def_or_ref (
6153 image
, cols
[MONO_METHODIMPL_BODY
], generic_context
, &error
);
6154 if (method
== NULL
) {
6155 mono_error_cleanup (&error
); /* FIXME don't swallow the error */
6158 result
[i
* 2 + 1] = method
;
6161 *overrides
= result
;
6163 *num_overrides
= num
;
6168 * mono_guid_to_string:
6170 * Converts a 16 byte Microsoft GUID to the standard string representation.
6173 mono_guid_to_string (const guint8
*guid
)
6175 return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
6176 guid
[3], guid
[2], guid
[1], guid
[0],
6180 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
6184 * mono_guid_to_string_minimal:
6186 * Converts a 16 byte Microsoft GUID to lower case no '-' representation..
6189 mono_guid_to_string_minimal (const guint8
*guid
)
6191 return g_strdup_printf ("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
6192 guid
[3], guid
[2], guid
[1], guid
[0],
6196 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
6199 get_constraints (MonoImage
*image
, int owner
, MonoClass
***constraints
, MonoGenericContainer
*container
, MonoError
*error
)
6201 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
6202 guint32 cols
[MONO_GENPARCONSTRAINT_SIZE
];
6203 guint32 i
, token
, found
;
6204 MonoClass
*klass
, **res
;
6205 GSList
*cons
= NULL
, *tmp
;
6206 MonoGenericContext
*context
= &container
->context
;
6208 mono_error_init (error
);
6210 *constraints
= NULL
;
6212 for (i
= 0; i
< tdef
->rows
; ++i
) {
6213 mono_metadata_decode_row (tdef
, i
, cols
, MONO_GENPARCONSTRAINT_SIZE
);
6214 if (cols
[MONO_GENPARCONSTRAINT_GENERICPAR
] == owner
) {
6215 token
= mono_metadata_token_from_dor (cols
[MONO_GENPARCONSTRAINT_CONSTRAINT
]);
6216 klass
= mono_class_get_and_inflate_typespec_checked (image
, token
, context
, error
);
6218 g_slist_free (cons
);
6221 cons
= g_slist_append (cons
, klass
);
6224 /* contiguous list finished */
6231 res
= (MonoClass
**)mono_image_alloc0 (image
, sizeof (MonoClass
*) * (found
+ 1));
6232 for (i
= 0, tmp
= cons
; i
< found
; ++i
, tmp
= tmp
->next
) {
6233 res
[i
] = (MonoClass
*)tmp
->data
;
6235 g_slist_free (cons
);
6241 * mono_metadata_get_generic_param_row:
6244 * @token: TypeOrMethodDef token, owner for GenericParam
6245 * @owner: coded token, set on return
6247 * Returns: 1-based row-id in the GenericParam table whose
6248 * owner is @token. 0 if not found.
6251 mono_metadata_get_generic_param_row (MonoImage
*image
, guint32 token
, guint32
*owner
)
6253 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
6260 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPEDEF
)
6261 *owner
= MONO_TYPEORMETHOD_TYPE
;
6262 else if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
6263 *owner
= MONO_TYPEORMETHOD_METHOD
;
6265 g_error ("wrong token %x to get_generic_param_row", token
);
6268 *owner
|= mono_metadata_token_index (token
) << MONO_TYPEORMETHOD_BITS
;
6271 loc
.col_idx
= MONO_GENERICPARAM_OWNER
;
6274 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6277 /* Find the first entry by searching backwards */
6278 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_GENERICPARAM_OWNER
) == loc
.idx
))
6281 return loc
.result
+ 1;
6285 mono_metadata_has_generic_params (MonoImage
*image
, guint32 token
)
6288 return mono_metadata_get_generic_param_row (image
, token
, &owner
);
6292 * Memory is allocated from IMAGE's mempool.
6295 mono_metadata_load_generic_param_constraints_checked (MonoImage
*image
, guint32 token
,
6296 MonoGenericContainer
*container
, MonoError
*error
)
6299 guint32 start_row
, i
, owner
;
6300 mono_error_init (error
);
6302 if (! (start_row
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
6304 for (i
= 0; i
< container
->type_argc
; i
++) {
6305 if (!get_constraints (image
, start_row
+ i
, &mono_generic_container_get_param_info (container
, i
)->constraints
, container
, error
)) {
6313 * mono_metadata_load_generic_params:
6315 * Load the type parameters from the type or method definition @token.
6317 * Use this method after parsing a type or method definition to figure out whether it's a generic
6318 * type / method. When parsing a method definition, @parent_container points to the generic container
6319 * of the current class, if any.
6321 * Note: This method does not load the constraints: for typedefs, this has to be done after fully
6322 * creating the type.
6324 * Returns: NULL if @token is not a generic type or method definition or the new generic container.
6326 * LOCKING: Acquires the loader lock
6329 MonoGenericContainer
*
6330 mono_metadata_load_generic_params (MonoImage
*image
, guint32 token
, MonoGenericContainer
*parent_container
)
6332 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
6333 guint32 cols
[MONO_GENERICPARAM_SIZE
];
6334 guint32 i
, owner
= 0, n
;
6335 MonoGenericContainer
*container
;
6336 MonoGenericParamFull
*params
;
6337 MonoGenericContext
*context
;
6339 if (!(i
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
6341 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
6344 container
= (MonoGenericContainer
*)mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
6345 container
->owner
.image
= image
; // Temporarily mark as anonymous, but this will be overriden by caller
6346 container
->is_anonymous
= TRUE
;
6349 params
= (MonoGenericParamFull
*)g_realloc (params
, sizeof (MonoGenericParamFull
) * n
);
6350 memset (¶ms
[n
- 1], 0, sizeof (MonoGenericParamFull
));
6351 params
[n
- 1].param
.owner
= container
;
6352 params
[n
- 1].param
.num
= cols
[MONO_GENERICPARAM_NUMBER
];
6353 params
[n
- 1].info
.token
= i
| MONO_TOKEN_GENERIC_PARAM
;
6354 params
[n
- 1].info
.flags
= cols
[MONO_GENERICPARAM_FLAGS
];
6355 params
[n
- 1].info
.name
= mono_metadata_string_heap (image
, cols
[MONO_GENERICPARAM_NAME
]);
6356 if (params
[n
- 1].param
.num
!= n
- 1)
6357 g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i
);
6358 if (++i
> tdef
->rows
)
6360 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
6361 } while (cols
[MONO_GENERICPARAM_OWNER
] == owner
);
6363 container
->type_argc
= n
;
6364 container
->type_params
= (MonoGenericParamFull
*)mono_image_alloc0 (image
, sizeof (MonoGenericParamFull
) * n
);
6365 memcpy (container
->type_params
, params
, sizeof (MonoGenericParamFull
) * n
);
6367 container
->parent
= parent_container
;
6369 if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
6370 container
->is_method
= 1;
6372 g_assert (container
->parent
== NULL
|| container
->is_method
);
6374 context
= &container
->context
;
6375 if (container
->is_method
) {
6376 context
->class_inst
= container
->parent
? container
->parent
->context
.class_inst
: NULL
;
6377 context
->method_inst
= mono_get_shared_generic_inst (container
);
6379 context
->class_inst
= mono_get_shared_generic_inst (container
);
6386 mono_get_shared_generic_inst (MonoGenericContainer
*container
)
6388 MonoType
**type_argv
;
6390 MonoGenericInst
*nginst
;
6393 type_argv
= g_new0 (MonoType
*, container
->type_argc
);
6394 helper
= g_new0 (MonoType
, container
->type_argc
);
6396 for (i
= 0; i
< container
->type_argc
; i
++) {
6397 MonoType
*t
= &helper
[i
];
6399 t
->type
= container
->is_method
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
6400 t
->data
.generic_param
= mono_generic_container_get_param (container
, i
);
6405 nginst
= mono_metadata_get_generic_inst (container
->type_argc
, type_argv
);
6414 * mono_type_is_byref:
6415 * @type: the MonoType operated on
6417 * Returns: #TRUE if @type represents a type passed by reference,
6421 mono_type_is_byref (MonoType
*type
)
6427 * mono_type_get_type:
6428 * @type: the MonoType operated on
6430 * Returns: the IL type value for @type. This is one of the MonoTypeEnum
6431 * enum members like MONO_TYPE_I4 or MONO_TYPE_STRING.
6434 mono_type_get_type (MonoType
*type
)
6440 * mono_type_get_signature:
6441 * @type: the MonoType operated on
6443 * It is only valid to call this function if @type is a MONO_TYPE_FNPTR.
6445 * Returns: the MonoMethodSignature pointer that describes the signature
6446 * of the function pointer @type represents.
6448 MonoMethodSignature
*
6449 mono_type_get_signature (MonoType
*type
)
6451 g_assert (type
->type
== MONO_TYPE_FNPTR
);
6452 return type
->data
.method
;
6456 * mono_type_get_class:
6457 * @type: the MonoType operated on
6459 * It is only valid to call this function if @type is a MONO_TYPE_CLASS or a
6460 * MONO_TYPE_VALUETYPE. For more general functionality, use mono_class_from_mono_type (),
6463 * Returns: the MonoClass pointer that describes the class that @type represents.
6466 mono_type_get_class (MonoType
*type
)
6468 /* FIXME: review the runtime users before adding the assert here */
6469 return type
->data
.klass
;
6473 * mono_type_get_array_type:
6474 * @type: the MonoType operated on
6476 * It is only valid to call this function if @type is a MONO_TYPE_ARRAY.
6478 * Returns: a MonoArrayType struct describing the array type that @type
6479 * represents. The info includes details such as rank, array element type
6480 * and the sizes and bounds of multidimensional arrays.
6483 mono_type_get_array_type (MonoType
*type
)
6485 return type
->data
.array
;
6489 * mono_type_get_ptr_type:
6490 * @type: the MonoType operated on
6492 * It is only valid to call this function if @type is a MONO_TYPE_PTR.
6495 * Returns: the MonoType pointer that describes the type that @type
6496 * represents a pointer to.
6499 mono_type_get_ptr_type (MonoType
*type
)
6501 g_assert (type
->type
== MONO_TYPE_PTR
);
6502 return type
->data
.type
;
6506 mono_type_get_modifiers (MonoType
*type
, gboolean
*is_required
, gpointer
*iter
)
6508 /* FIXME: implement */
6513 * mono_type_is_struct:
6514 * @type: the MonoType operated on
6516 * Returns: #TRUE is @type is a struct, that is a ValueType but not en enum
6517 * or a basic type like System.Int32. #FALSE otherwise.
6520 mono_type_is_struct (MonoType
*type
)
6522 return (!type
->byref
&& ((type
->type
== MONO_TYPE_VALUETYPE
&&
6523 !type
->data
.klass
->enumtype
) || (type
->type
== MONO_TYPE_TYPEDBYREF
) ||
6524 ((type
->type
== MONO_TYPE_GENERICINST
) &&
6525 mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
) &&
6526 !type
->data
.generic_class
->container_class
->enumtype
)));
6530 * mono_type_is_void:
6531 * @type: the MonoType operated on
6533 * Returns: #TRUE is @type is System.Void. #FALSE otherwise.
6536 mono_type_is_void (MonoType
*type
)
6538 return (type
&& (type
->type
== MONO_TYPE_VOID
) && !type
->byref
);
6542 * mono_type_is_pointer:
6543 * @type: the MonoType operated on
6545 * Returns: #TRUE is @type is a managed or unmanaged pointer type. #FALSE otherwise.
6548 mono_type_is_pointer (MonoType
*type
)
6550 return (type
&& ((type
->byref
|| (type
->type
== MONO_TYPE_I
) || type
->type
== MONO_TYPE_STRING
)
6551 || (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
6552 (type
->type
== MONO_TYPE_U
) || (type
->type
== MONO_TYPE_OBJECT
) ||
6553 (type
->type
== MONO_TYPE_ARRAY
) || (type
->type
== MONO_TYPE_PTR
) ||
6554 (type
->type
== MONO_TYPE_FNPTR
)));
6558 * mono_type_is_reference:
6559 * @type: the MonoType operated on
6561 * Returns: #TRUE is @type represents an object reference . #FALSE otherwise.
6564 mono_type_is_reference (MonoType
*type
)
6566 return (type
&& (((type
->type
== MONO_TYPE_STRING
) ||
6567 (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
6568 (type
->type
== MONO_TYPE_OBJECT
) || (type
->type
== MONO_TYPE_ARRAY
)) ||
6569 ((type
->type
== MONO_TYPE_GENERICINST
) &&
6570 !mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
))));
6574 mono_type_is_generic_parameter (MonoType
*type
)
6576 return !type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
);
6580 * mono_signature_get_return_type:
6581 * @sig: the method signature inspected
6583 * Returns: the return type of the method signature @sig
6586 mono_signature_get_return_type (MonoMethodSignature
*sig
)
6592 * mono_signature_get_params:
6593 * @sig: the method signature inspected
6594 * #iter: pointer to an iterator
6596 * Iterates over the parameters for the method signature @sig.
6597 * A void* pointer must be initualized to #NULL to start the iteration
6598 * and it's address is passed to this function repeteadly until it returns
6601 * Returns: the next parameter type of the method signature @sig,
6602 * #NULL when finished.
6605 mono_signature_get_params (MonoMethodSignature
*sig
, gpointer
*iter
)
6611 /* start from the first */
6612 if (sig
->param_count
) {
6613 *iter
= &sig
->params
[0];
6614 return sig
->params
[0];
6620 type
= (MonoType
**)*iter
;
6622 if (type
< &sig
->params
[sig
->param_count
]) {
6630 * mono_signature_get_param_count:
6631 * @sig: the method signature inspected
6633 * Returns: the number of parameters in the method signature @sig.
6636 mono_signature_get_param_count (MonoMethodSignature
*sig
)
6638 return sig
->param_count
;
6642 * mono_signature_get_call_conv:
6643 * @sig: the method signature inspected
6645 * Returns: the call convention of the method signature @sig.
6648 mono_signature_get_call_conv (MonoMethodSignature
*sig
)
6650 return sig
->call_convention
;
6654 * mono_signature_vararg_start:
6655 * @sig: the method signature inspected
6657 * Returns: the number of the first vararg parameter in the
6658 * method signature @sig. -1 if this is not a vararg signature.
6661 mono_signature_vararg_start (MonoMethodSignature
*sig
)
6663 return sig
->sentinelpos
;
6667 * mono_signature_is_instance:
6668 * @sig: the method signature inspected
6670 * Returns: #TRUE if this the method signature @sig has an implicit
6671 * first instance argument. #FALSE otherwise.
6674 mono_signature_is_instance (MonoMethodSignature
*sig
)
6676 return sig
->hasthis
;
6680 * mono_signature_param_is_out
6681 * @sig: the method signature inspected
6682 * @param_num: the 0-based index of the inspected parameter
6684 * Returns: #TRUE if the parameter is an out parameter, #FALSE
6688 mono_signature_param_is_out (MonoMethodSignature
*sig
, int param_num
)
6690 g_assert (param_num
>= 0 && param_num
< sig
->param_count
);
6691 return (sig
->params
[param_num
]->attrs
& PARAM_ATTRIBUTE_OUT
) != 0;
6695 * mono_signature_explicit_this:
6696 * @sig: the method signature inspected
6698 * Returns: #TRUE if this the method signature @sig has an explicit
6699 * instance argument. #FALSE otherwise.
6702 mono_signature_explicit_this (MonoMethodSignature
*sig
)
6704 return sig
->explicit_this
;
6707 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
6709 mono_aligned_addr_hash (gconstpointer ptr
)
6711 return GPOINTER_TO_UINT (ptr
) >> 3;
6715 * If @field belongs to an inflated generic class, return the corresponding field of the
6716 * generic type definition class.
6719 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField
*field
)
6724 if (!mono_class_is_ginst (field
->parent
))
6727 gtd
= mono_class_get_generic_class (field
->parent
)->container_class
;
6728 offset
= field
- field
->parent
->fields
;
6729 return gtd
->fields
+ offset
;
6733 * If @event belongs to an inflated generic class, return the corresponding event of the
6734 * generic type definition class.
6737 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent
*event
)
6742 if (!mono_class_is_ginst (event
->parent
))
6745 gtd
= mono_class_get_generic_class (event
->parent
)->container_class
;
6746 offset
= event
- mono_class_get_event_info (event
->parent
)->events
;
6747 return mono_class_get_event_info (gtd
)->events
+ offset
;
6751 * If @property belongs to an inflated generic class, return the corresponding property of the
6752 * generic type definition class.
6755 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty
*property
)
6757 MonoClassPropertyInfo
*info
;
6761 if (!mono_class_is_ginst (property
->parent
))
6764 info
= mono_class_get_property_info (property
->parent
);
6765 gtd
= mono_class_get_generic_class (property
->parent
)->container_class
;
6766 offset
= property
- info
->properties
;
6767 return mono_class_get_property_info (gtd
)->properties
+ offset
;
6771 mono_method_get_wrapper_cache (MonoMethod
*method
)
6773 if (method
->is_inflated
) {
6774 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
6775 return &imethod
->owner
->wrapper_caches
;
6777 return &method
->klass
->image
->wrapper_caches
;
6781 // This is support for the mempool reference tracking feature in checked-build, but lives in metadata.c due to use of static variables of this file.
6784 * mono_find_image_set_owner:
6786 * Find the imageset, if any, which a given pointer is located in the memory of.
6789 mono_find_image_set_owner (void *ptr
)
6791 MonoImageSet
*owner
= NULL
;
6798 for (i
= 0; !owner
&& i
< image_sets
->len
; ++i
) {
6799 MonoImageSet
*set
= (MonoImageSet
*)g_ptr_array_index (image_sets
, i
);
6800 if (mono_mempool_contains_addr (set
->mempool
, ptr
))
6805 image_sets_unlock ();