3 * Routines for accessing the metadata
6 * Miguel de Icaza (miguel@ximian.com)
7 * Paolo Molaro (lupus@ximian.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include "tabledefs.h"
21 #include "mono-endian.h"
23 #include "tokentype.h"
24 #include "class-internals.h"
25 #include "metadata-internals.h"
26 #include "verify-internals.h"
29 #include "debug-helpers.h"
30 #include "abi-details.h"
31 #include "cominterop.h"
32 #include <mono/metadata/exception-internals.h>
33 #include <mono/utils/mono-error-internals.h>
34 #include <mono/utils/mono-memory-model.h>
35 #include <mono/utils/bsearch.h>
36 #include <mono/utils/atomic.h>
37 #include <mono/utils/unlocked.h>
38 #include <mono/utils/mono-counters.h>
40 static gint32 img_set_cache_hit
, img_set_cache_miss
, img_set_count
;
43 /* Auxiliary structure used for caching inflated signatures */
45 MonoMethodSignature
*sig
;
46 MonoGenericContext context
;
47 } MonoInflatedMethodSignature
;
49 static gboolean
do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
, gboolean transient
,
50 const char *ptr
, const char **rptr
, MonoError
*error
);
52 static gboolean
do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
);
53 static gboolean
mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
);
54 static gboolean
mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
);
55 static gboolean
_mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
,
56 gboolean signature_only
);
57 static void free_generic_inst (MonoGenericInst
*ginst
);
58 static void free_generic_class (MonoGenericClass
*ginst
);
59 static void free_inflated_method (MonoMethodInflated
*method
);
60 static void free_inflated_signature (MonoInflatedMethodSignature
*sig
);
61 static void free_aggregate_modifiers (MonoAggregateModContainer
*amods
);
62 static void mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
, MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
);
64 static MonoType
* mono_signature_get_params_internal (MonoMethodSignature
*sig
, gpointer
*iter
);
67 * This enumeration is used to describe the data types in the metadata
78 /* Index into Blob heap */
81 /* Index into String heap */
87 /* Pointer into a table */
90 /* HasConstant:Parent pointer (Param, Field or Property) */
93 /* HasCustomAttribute index. Indexes any table except CustomAttribute */
96 /* CustomAttributeType encoded index */
99 /* HasDeclSecurity index: TypeDef Method or Assembly */
102 /* Implementation coded index: File, Export AssemblyRef */
105 /* HasFieldMarshal coded index: Field or Param table */
108 /* MemberForwardedIndex: Field or Method */
111 /* TypeDefOrRef coded index: typedef, typeref, typespec */
114 /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
117 /* MethodDefOrRef coded index: Method or Member Ref table */
120 /* HasSemantic coded index: Event or Property */
123 /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
126 /* CustomDebugInformation parent encoded index */
127 MONO_MT_HASCUSTDEBUG_IDX
130 const static unsigned char TableSchemas
[] = {
131 #define ASSEMBLY_SCHEMA_OFFSET 0
132 MONO_MT_UINT32
, /* "HashId" }, */
133 MONO_MT_UINT16
, /* "Major" }, */
134 MONO_MT_UINT16
, /* "Minor" }, */
135 MONO_MT_UINT16
, /* "BuildNumber" }, */
136 MONO_MT_UINT16
, /* "RevisionNumber" }, */
137 MONO_MT_UINT32
, /* "Flags" }, */
138 MONO_MT_BLOB_IDX
, /* "PublicKey" }, */
139 MONO_MT_STRING_IDX
, /* "Name" }, */
140 MONO_MT_STRING_IDX
, /* "Culture" }, */
143 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
144 MONO_MT_UINT32
, /* "OSPlatformID" }, */
145 MONO_MT_UINT32
, /* "OSMajor" }, */
146 MONO_MT_UINT32
, /* "OSMinor" }, */
149 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
150 MONO_MT_UINT32
, /* "Processor" }, */
153 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
154 MONO_MT_UINT16
, /* "Major" }, */
155 MONO_MT_UINT16
, /* "Minor" }, */
156 MONO_MT_UINT16
, /* "Build" }, */
157 MONO_MT_UINT16
, /* "Revision" }, */
158 MONO_MT_UINT32
, /* "Flags" }, */
159 MONO_MT_BLOB_IDX
, /* "PublicKeyOrToken" }, */
160 MONO_MT_STRING_IDX
, /* "Name" }, */
161 MONO_MT_STRING_IDX
, /* "Culture" }, */
162 MONO_MT_BLOB_IDX
, /* "HashValue" }, */
165 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
166 MONO_MT_UINT32
, /* "OSPlatformID" }, */
167 MONO_MT_UINT32
, /* "OSMajorVersion" }, */
168 MONO_MT_UINT32
, /* "OSMinorVersion" }, */
169 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
172 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
173 MONO_MT_UINT32
, /* "Processor" }, */
174 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
177 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
178 MONO_MT_UINT16
, /* "PackingSize" }, */
179 MONO_MT_UINT32
, /* "ClassSize" }, */
180 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
183 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
184 MONO_MT_UINT8
, /* "Type" }, */
185 MONO_MT_UINT8
, /* "PaddingZero" }, */
186 MONO_MT_CONST_IDX
, /* "Parent" }, */
187 MONO_MT_BLOB_IDX
, /* "Value" }, */
190 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
191 MONO_MT_HASCAT_IDX
, /* "Parent" }, */
192 MONO_MT_CAT_IDX
, /* "Type" }, */
193 MONO_MT_BLOB_IDX
, /* "Value" }, */
196 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
197 MONO_MT_UINT16
, /* "Action" }, */
198 MONO_MT_HASDEC_IDX
, /* "Parent" }, */
199 MONO_MT_BLOB_IDX
, /* "PermissionSet" }, */
202 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
203 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
204 MONO_MT_TABLE_IDX
, /* "EventList:Event" }, */
207 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
208 MONO_MT_UINT16
, /* "EventFlags#EventAttribute" }, */
209 MONO_MT_STRING_IDX
, /* "Name" }, */
210 MONO_MT_TDOR_IDX
, /* "EventType" }, TypeDef or TypeRef or TypeSpec */
213 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
214 MONO_MT_TABLE_IDX
, /* "Event" }, */
217 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
218 MONO_MT_UINT32
, /* "Flags" }, */
219 MONO_MT_TABLE_IDX
, /* "TypeDefId" }, */
220 MONO_MT_STRING_IDX
, /* "TypeName" }, */
221 MONO_MT_STRING_IDX
, /* "TypeNameSpace" }, */
222 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
225 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
226 MONO_MT_UINT16
, /* "Flags" }, */
227 MONO_MT_STRING_IDX
, /* "Name" }, */
228 MONO_MT_BLOB_IDX
, /* "Signature" }, */
231 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
232 MONO_MT_UINT32
, /* "Offset" }, */
233 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
236 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
237 MONO_MT_HFM_IDX
, /* "Parent" }, */
238 MONO_MT_BLOB_IDX
, /* "NativeType" }, */
241 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
242 MONO_MT_UINT32
, /* "RVA" }, */
243 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
246 #define ENCLOG_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
247 MONO_MT_UINT32
, /* "Token" }, */
248 MONO_MT_UINT32
, /* "FuncCode" }, */
251 #define ENCMAP_SCHEMA_OFFSET ENCLOG_SCHEMA_OFFSET + 3
252 MONO_MT_UINT32
, /* "Token" }, */
255 #define FIELD_POINTER_SCHEMA_OFFSET ENCMAP_SCHEMA_OFFSET + 2
256 MONO_MT_TABLE_IDX
, /* "Field" }, */
259 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
260 MONO_MT_UINT32
, /* "Flags" }, */
261 MONO_MT_STRING_IDX
, /* "Name" }, */
262 MONO_MT_BLOB_IDX
, /* "Value" }, */
265 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
266 MONO_MT_UINT16
, /* "MappingFlag" }, */
267 MONO_MT_MF_IDX
, /* "MemberForwarded" }, */
268 MONO_MT_STRING_IDX
, /* "ImportName" }, */
269 MONO_MT_TABLE_IDX
, /* "ImportScope:ModuleRef" }, */
272 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
273 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
274 MONO_MT_TDOR_IDX
, /* "Interface=TypeDefOrRef" }, */
277 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
278 MONO_MT_UINT32
, /* "Offset" }, */
279 MONO_MT_UINT32
, /* "Flags" }, */
280 MONO_MT_STRING_IDX
, /* "Name" }, */
281 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
284 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
285 MONO_MT_MRP_IDX
, /* "Class" }, */
286 MONO_MT_STRING_IDX
, /* "Name" }, */
287 MONO_MT_BLOB_IDX
, /* "Signature" }, */
290 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
291 MONO_MT_UINT32
, /* "RVA" }, */
292 MONO_MT_UINT16
, /* "ImplFlags#MethodImplAttributes" }, */
293 MONO_MT_UINT16
, /* "Flags#MethodAttribute" }, */
294 MONO_MT_STRING_IDX
, /* "Name" }, */
295 MONO_MT_BLOB_IDX
, /* "Signature" }, */
296 MONO_MT_TABLE_IDX
, /* "ParamList:Param" }, */
299 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
300 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
301 MONO_MT_MDOR_IDX
, /* "MethodBody" }, */
302 MONO_MT_MDOR_IDX
, /* "MethodDeclaration" }, */
305 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
306 MONO_MT_UINT16
, /* "MethodSemantic" }, */
307 MONO_MT_TABLE_IDX
, /* "Method:Method" }, */
308 MONO_MT_HS_IDX
, /* "Association" }, */
311 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
312 MONO_MT_TABLE_IDX
, /* "Method" }, */
315 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
316 MONO_MT_UINT16
, /* "Generation" }, */
317 MONO_MT_STRING_IDX
, /* "Name" }, */
318 MONO_MT_GUID_IDX
, /* "MVID" }, */
319 MONO_MT_GUID_IDX
, /* "EncID" }, */
320 MONO_MT_GUID_IDX
, /* "EncBaseID" }, */
323 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
324 MONO_MT_STRING_IDX
, /* "Name" }, */
327 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
328 MONO_MT_TABLE_IDX
, /* "NestedClass:TypeDef" }, */
329 MONO_MT_TABLE_IDX
, /* "EnclosingClass:TypeDef" }, */
332 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
333 MONO_MT_UINT16
, /* "Flags" }, */
334 MONO_MT_UINT16
, /* "Sequence" }, */
335 MONO_MT_STRING_IDX
, /* "Name" }, */
338 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
339 MONO_MT_TABLE_IDX
, /* "Param" }, */
342 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
343 MONO_MT_UINT16
, /* "Flags" }, */
344 MONO_MT_STRING_IDX
, /* "Name" }, */
345 MONO_MT_BLOB_IDX
, /* "Type" }, */
348 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
349 MONO_MT_TABLE_IDX
, /* "Property" }, */
352 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
353 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
354 MONO_MT_TABLE_IDX
, /* "PropertyList:Property" }, */
357 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
358 MONO_MT_BLOB_IDX
, /* "Signature" }, */
361 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
362 MONO_MT_UINT32
, /* "Flags" }, */
363 MONO_MT_STRING_IDX
, /* "Name" }, */
364 MONO_MT_STRING_IDX
, /* "Namespace" }, */
365 MONO_MT_TDOR_IDX
, /* "Extends" }, */
366 MONO_MT_TABLE_IDX
, /* "FieldList:Field" }, */
367 MONO_MT_TABLE_IDX
, /* "MethodList:Method" }, */
370 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
371 MONO_MT_RS_IDX
, /* "ResolutionScope=ResolutionScope" }, */
372 MONO_MT_STRING_IDX
, /* "Name" }, */
373 MONO_MT_STRING_IDX
, /* "Namespace" }, */
376 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
377 MONO_MT_BLOB_IDX
, /* "Signature" }, */
380 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
381 MONO_MT_UINT16
, /* "Number" }, */
382 MONO_MT_UINT16
, /* "Flags" }, */
383 MONO_MT_TABLE_IDX
, /* "Owner" }, TypeDef or MethodDef */
384 MONO_MT_STRING_IDX
, /* "Name" }, */
387 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
388 MONO_MT_MDOR_IDX
, /* "Method" }, */
389 MONO_MT_BLOB_IDX
, /* "Signature" }, */
392 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
393 MONO_MT_TABLE_IDX
, /* "GenericParam" }, */
394 MONO_MT_TDOR_IDX
, /* "Constraint" }, */
397 #define DOCUMENT_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
398 MONO_MT_BLOB_IDX
, /* Name */
399 MONO_MT_GUID_IDX
, /* HashAlgorithm */
400 MONO_MT_BLOB_IDX
, /* Hash */
401 MONO_MT_GUID_IDX
, /* Language */
404 #define METHODBODY_SCHEMA_OFFSET DOCUMENT_SCHEMA_OFFSET + 5
405 MONO_MT_TABLE_IDX
, /* Document */
406 MONO_MT_BLOB_IDX
, /* SequencePoints */
409 #define LOCALSCOPE_SCHEMA_OFFSET METHODBODY_SCHEMA_OFFSET + 3
410 MONO_MT_TABLE_IDX
, /* Method */
411 MONO_MT_TABLE_IDX
, /* ImportScope */
412 MONO_MT_TABLE_IDX
, /* VariableList */
413 MONO_MT_TABLE_IDX
, /* ConstantList */
414 MONO_MT_UINT32
, /* StartOffset */
415 MONO_MT_UINT32
, /* Length */
418 #define LOCALVARIABLE_SCHEMA_OFFSET LOCALSCOPE_SCHEMA_OFFSET + 7
419 MONO_MT_UINT16
, /* Attributes */
420 MONO_MT_UINT16
, /* Index */
421 MONO_MT_STRING_IDX
, /* Name */
424 #define LOCALCONSTANT_SCHEMA_OFFSET LOCALVARIABLE_SCHEMA_OFFSET + 4
425 MONO_MT_STRING_IDX
, /* Name (String heap index) */
426 MONO_MT_BLOB_IDX
, /* Signature (Blob heap index, LocalConstantSig blob) */
429 #define IMPORTSCOPE_SCHEMA_OFFSET LOCALCONSTANT_SCHEMA_OFFSET + 3
430 MONO_MT_TABLE_IDX
, /* Parent (ImportScope row id or nil) */
431 MONO_MT_BLOB_IDX
, /* Imports (Blob index, encoding: Imports blob) */
434 #define ASYNCMETHOD_SCHEMA_OFFSET IMPORTSCOPE_SCHEMA_OFFSET + 3
435 MONO_MT_TABLE_IDX
, /* MoveNextMethod (MethodDef row id) */
436 MONO_MT_TABLE_IDX
, /* KickoffMethod (MethodDef row id) */
439 #define CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET ASYNCMETHOD_SCHEMA_OFFSET + 3
440 MONO_MT_HASCUSTDEBUG_IDX
, /* Parent (HasCustomDebugInformation coded index) */
441 MONO_MT_GUID_IDX
, /* Kind (Guid heap index) */
442 MONO_MT_BLOB_IDX
, /* Value (Blob heap index) */
445 #define NULL_SCHEMA_OFFSET CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET + 4
449 /* Must be the same order as MONO_TABLE_* */
450 const static unsigned char
451 table_description
[] = {
452 MODULE_SCHEMA_OFFSET
,
453 TYPEREF_SCHEMA_OFFSET
,
454 TYPEDEF_SCHEMA_OFFSET
,
455 FIELD_POINTER_SCHEMA_OFFSET
,
457 METHOD_POINTER_SCHEMA_OFFSET
,
458 METHOD_SCHEMA_OFFSET
,
459 PARAM_POINTER_SCHEMA_OFFSET
,
461 IFACEMAP_SCHEMA_OFFSET
,
462 MEMBERREF_SCHEMA_OFFSET
, /* 0xa */
463 CONSTANT_SCHEMA_OFFSET
,
464 CUSTOM_ATTR_SCHEMA_OFFSET
,
465 FIELD_MARSHAL_SCHEMA_OFFSET
,
466 DECL_SEC_SCHEMA_OFFSET
,
467 CLASS_LAYOUT_SCHEMA_OFFSET
,
468 FIELD_LAYOUT_SCHEMA_OFFSET
, /* 0x10 */
469 STDALON_SIG_SCHEMA_OFFSET
,
470 EVENTMAP_SCHEMA_OFFSET
,
471 EVENT_POINTER_SCHEMA_OFFSET
,
473 PROPERTY_MAP_SCHEMA_OFFSET
,
474 PROPERTY_POINTER_SCHEMA_OFFSET
,
475 PROPERTY_SCHEMA_OFFSET
,
476 METHOD_SEMA_SCHEMA_OFFSET
,
477 METHOD_IMPL_SCHEMA_OFFSET
,
478 MODULEREF_SCHEMA_OFFSET
, /* 0x1a */
479 TYPESPEC_SCHEMA_OFFSET
,
480 IMPLMAP_SCHEMA_OFFSET
,
481 FIELD_RVA_SCHEMA_OFFSET
,
482 ENCLOG_SCHEMA_OFFSET
,
483 ENCMAP_SCHEMA_OFFSET
,
484 ASSEMBLY_SCHEMA_OFFSET
, /* 0x20 */
485 ASSEMBLYPROC_SCHEMA_OFFSET
,
486 ASSEMBLYOS_SCHEMA_OFFSET
,
487 ASSEMBLYREF_SCHEMA_OFFSET
,
488 ASSEMBLYREFPROC_SCHEMA_OFFSET
,
489 ASSEMBLYREFOS_SCHEMA_OFFSET
,
491 EXPORTED_TYPE_SCHEMA_OFFSET
,
492 MANIFEST_SCHEMA_OFFSET
,
493 NESTED_CLASS_SCHEMA_OFFSET
,
494 GENPARAM_SCHEMA_OFFSET
, /* 0x2a */
495 METHOD_SPEC_SCHEMA_OFFSET
,
496 GEN_CONSTRAINT_SCHEMA_OFFSET
,
500 DOCUMENT_SCHEMA_OFFSET
, /* 0x30 */
501 METHODBODY_SCHEMA_OFFSET
,
502 LOCALSCOPE_SCHEMA_OFFSET
,
503 LOCALVARIABLE_SCHEMA_OFFSET
,
504 LOCALCONSTANT_SCHEMA_OFFSET
,
505 IMPORTSCOPE_SCHEMA_OFFSET
,
506 ASYNCMETHOD_SCHEMA_OFFSET
,
507 CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET
510 // This, instead of an array of pointers, to optimize away a pointer and a relocation per string.
511 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
512 #define MSGSTRFIELD1(line) str##line
513 static const struct msgstr_t
{
514 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
515 #include "mono/cil/tables.def"
518 #define TABLEDEF(a,b) b,
519 #include "mono/cil/tables.def"
522 static const gint16 tableidx
[] = {
523 #define TABLEDEF(a,b) offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
524 #include "mono/cil/tables.def"
528 /* On legacy, if TRUE (but also see DISABLE_DESKTOP_LOADER #define), Mono will check
529 * that the public key token, culture and version of a candidate assembly matches
530 * the requested strong name. On netcore, it will check the culture and version.
531 * If FALSE, as long as the name matches, the candidate will be allowed.
533 static gboolean check_assembly_names_strictly
= FALSE
;
535 // Amount initially reserved in each imageset's mempool.
536 // FIXME: This number is arbitrary, a more practical number should be found
537 #define INITIAL_IMAGE_SET_SIZE 1024
540 * mono_meta_table_name:
541 * \param table table index
543 * Returns the name of the given ECMA metadata logical format table
544 * as described in ECMA 335, Partition II, Section 22.
546 * \returns the name for the \p table index
549 mono_meta_table_name (int table
)
551 if ((table
< 0) || (table
> MONO_TABLE_LAST
))
554 return (const char*)&tablestr
+ tableidx
[table
];
557 /* The guy who wrote the spec for this should not be allowed near a
560 If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
561 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
562 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
563 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
564 inverse of this mapping.
567 #define rtsize(meta,s,b) (((s) < (1 << (b)) ? 2 : 4))
570 idx_size (MonoImage
*meta
, int idx
)
572 if (meta
->referenced_tables
&& (meta
->referenced_tables
& ((guint64
)1 << idx
)))
573 return meta
->referenced_table_rows
[idx
] < 65536 ? 2 : 4;
575 return meta
->tables
[idx
].rows
< 65536 ? 2 : 4;
579 get_nrows (MonoImage
*meta
, int idx
)
581 if (meta
->referenced_tables
&& (meta
->referenced_tables
& ((guint64
)1 << idx
)))
582 return meta
->referenced_table_rows
[idx
];
584 return meta
->tables
[idx
].rows
;
587 /* Reference: Partition II - 23.2.6 */
589 * mono_metadata_compute_size:
590 * \param meta metadata context
591 * \param tableindex metadata table number
592 * \param result_bitfield pointer to \c guint32 where to store additional info
594 * \c mono_metadata_compute_size computes the length in bytes of a single
595 * row in a metadata table. The size of each column is encoded in the
596 * \p result_bitfield return value along with the number of columns in the table.
597 * the resulting bitfield should be handed to the \c mono_metadata_table_size
598 * and \c mono_metadata_table_count macros.
599 * This is a Mono runtime internal only function.
602 mono_metadata_compute_size (MonoImage
*meta
, int tableindex
, guint32
*result_bitfield
)
604 guint32 bitfield
= 0;
605 int size
= 0, field_size
= 0;
608 const unsigned char *description
= TableSchemas
+ table_description
[tableindex
];
610 for (i
= 0; (code
= description
[i
]) != MONO_MT_END
; i
++){
613 field_size
= 4; break;
616 field_size
= 2; break;
619 field_size
= 1; break;
621 case MONO_MT_BLOB_IDX
:
622 field_size
= meta
->idx_blob_wide
? 4 : 2; break;
624 case MONO_MT_STRING_IDX
:
625 field_size
= meta
->idx_string_wide
? 4 : 2; break;
627 case MONO_MT_GUID_IDX
:
628 field_size
= meta
->idx_guid_wide
? 4 : 2; break;
630 case MONO_MT_TABLE_IDX
:
631 /* Uhm, a table index can point to other tables besides the current one
632 * so, it's not correct to use the rowcount of the current table to
633 * get the size for this column - lupus
635 switch (tableindex
) {
636 case MONO_TABLE_ASSEMBLYREFOS
:
638 field_size
= idx_size (meta
, MONO_TABLE_ASSEMBLYREF
); break;
639 case MONO_TABLE_ASSEMBLYREFPROCESSOR
:
641 field_size
= idx_size (meta
, MONO_TABLE_ASSEMBLYREF
); break;
642 case MONO_TABLE_CLASSLAYOUT
:
644 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
645 case MONO_TABLE_EVENTMAP
:
646 g_assert (i
== 0 || i
== 1);
647 field_size
= i
? idx_size (meta
, MONO_TABLE_EVENT
):
648 idx_size (meta
, MONO_TABLE_TYPEDEF
);
650 case MONO_TABLE_EVENT_POINTER
:
652 field_size
= idx_size (meta
, MONO_TABLE_EVENT
); break;
653 case MONO_TABLE_EXPORTEDTYPE
:
655 /* the index is in another metadata file, so it must be 4 */
656 field_size
= 4; break;
657 case MONO_TABLE_FIELDLAYOUT
:
659 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
660 case MONO_TABLE_FIELDRVA
:
662 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
663 case MONO_TABLE_FIELD_POINTER
:
665 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
666 case MONO_TABLE_IMPLMAP
:
668 field_size
= idx_size (meta
, MONO_TABLE_MODULEREF
); break;
669 case MONO_TABLE_INTERFACEIMPL
:
671 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
672 case MONO_TABLE_METHOD
:
674 field_size
= idx_size (meta
, MONO_TABLE_PARAM
); break;
675 case MONO_TABLE_METHODIMPL
:
677 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
678 case MONO_TABLE_METHODSEMANTICS
:
680 field_size
= idx_size (meta
, MONO_TABLE_METHOD
); break;
681 case MONO_TABLE_METHOD_POINTER
:
683 field_size
= idx_size (meta
, MONO_TABLE_METHOD
); break;
684 case MONO_TABLE_NESTEDCLASS
:
685 g_assert (i
== 0 || i
== 1);
686 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
687 case MONO_TABLE_PARAM_POINTER
:
689 field_size
= idx_size (meta
, MONO_TABLE_PARAM
); break;
690 case MONO_TABLE_PROPERTYMAP
:
691 g_assert (i
== 0 || i
== 1);
692 field_size
= i
? idx_size (meta
, MONO_TABLE_PROPERTY
):
693 idx_size (meta
, MONO_TABLE_TYPEDEF
);
695 case MONO_TABLE_PROPERTY_POINTER
:
697 field_size
= idx_size (meta
, MONO_TABLE_PROPERTY
); break;
698 case MONO_TABLE_TYPEDEF
:
699 g_assert (i
== 4 || i
== 5);
700 field_size
= i
== 4 ? idx_size (meta
, MONO_TABLE_FIELD
):
701 idx_size (meta
, MONO_TABLE_METHOD
);
703 case MONO_TABLE_GENERICPARAM
:
705 n
= MAX (get_nrows (meta
, MONO_TABLE_METHOD
), get_nrows (meta
, MONO_TABLE_TYPEDEF
));
706 /*This is a coded token for 2 tables, so takes 1 bit */
707 field_size
= rtsize (meta
, n
, 16 - MONO_TYPEORMETHOD_BITS
);
709 case MONO_TABLE_GENERICPARAMCONSTRAINT
:
711 field_size
= idx_size (meta
, MONO_TABLE_GENERICPARAM
);
713 case MONO_TABLE_LOCALSCOPE
:
716 // FIXME: This table is in another file
717 field_size
= idx_size (meta
, MONO_TABLE_METHOD
);
720 field_size
= idx_size (meta
, MONO_TABLE_IMPORTSCOPE
);
723 field_size
= idx_size (meta
, MONO_TABLE_LOCALVARIABLE
);
726 field_size
= idx_size (meta
, MONO_TABLE_LOCALCONSTANT
);
729 g_assert_not_reached ();
733 case MONO_TABLE_METHODBODY
:
735 field_size
= idx_size (meta
, MONO_TABLE_DOCUMENT
); break;
736 case MONO_TABLE_IMPORTSCOPE
:
738 field_size
= idx_size (meta
, MONO_TABLE_IMPORTSCOPE
); break;
739 case MONO_TABLE_STATEMACHINEMETHOD
:
740 g_assert(i
== 0 || i
== 1);
741 field_size
= idx_size(meta
, MONO_TABLE_METHOD
); break;
743 g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex
, i
);
748 * HasConstant: ParamDef, FieldDef, Property
750 case MONO_MT_CONST_IDX
:
751 n
= MAX (get_nrows (meta
, MONO_TABLE_PARAM
),
752 get_nrows (meta
, MONO_TABLE_FIELD
));
753 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_PROPERTY
));
755 /* 2 bits to encode tag */
756 field_size
= rtsize (meta
, n
, 16-2);
760 * HasCustomAttribute: points to any table but
763 case MONO_MT_HASCAT_IDX
:
765 * We believe that since the signature and
766 * permission are indexing the Blob heap,
767 * we should consider the blob size first
769 /* I'm not a believer - lupus
770 if (meta->idx_blob_wide){
775 n
= MAX (get_nrows (meta
, MONO_TABLE_METHOD
),
776 get_nrows (meta
, MONO_TABLE_FIELD
));
777 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPEREF
));
778 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPEDEF
));
779 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_PARAM
));
780 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_INTERFACEIMPL
));
781 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MEMBERREF
));
782 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MODULE
));
783 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_DECLSECURITY
));
784 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_PROPERTY
));
785 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_EVENT
));
786 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_STANDALONESIG
));
787 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MODULEREF
));
788 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
789 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLY
));
790 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
791 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_FILE
));
792 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_EXPORTEDTYPE
));
793 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MANIFESTRESOURCE
));
794 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_GENERICPARAM
));
795 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_GENERICPARAMCONSTRAINT
));
796 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_METHODSPEC
));
798 /* 5 bits to encode */
799 field_size
= rtsize (meta
, n
, 16-5);
803 * HasCustomAttribute: points to any table but
807 case MONO_MT_HASCUSTDEBUG_IDX
:
808 n
= MAX(get_nrows (meta
, MONO_TABLE_METHOD
),
809 get_nrows (meta
, MONO_TABLE_FIELD
));
810 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_TYPEREF
));
811 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_TYPEDEF
));
812 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_PARAM
));
813 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_INTERFACEIMPL
));
814 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MEMBERREF
));
815 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MODULE
));
816 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_DECLSECURITY
));
817 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_PROPERTY
));
818 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_EVENT
));
819 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_STANDALONESIG
));
820 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MODULEREF
));
821 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
822 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_ASSEMBLY
));
823 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
824 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_FILE
));
825 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_EXPORTEDTYPE
));
826 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MANIFESTRESOURCE
));
827 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_GENERICPARAM
));
828 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_GENERICPARAMCONSTRAINT
));
829 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_METHODSPEC
));
830 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_DOCUMENT
));
831 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_LOCALSCOPE
));
832 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_LOCALVARIABLE
));
833 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_LOCALCONSTANT
));
834 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_IMPORTSCOPE
));
836 /* 5 bits to encode */
837 field_size
= rtsize(meta
, n
, 16 - 5);
841 * CustomAttributeType: MethodDef, MemberRef.
843 case MONO_MT_CAT_IDX
:
844 n
= MAX (get_nrows (meta
, MONO_TABLE_METHOD
),
845 get_nrows (meta
, MONO_TABLE_MEMBERREF
));
847 /* 3 bits to encode */
848 field_size
= rtsize (meta
, n
, 16-3);
852 * HasDeclSecurity: Typedef, MethodDef, Assembly
854 case MONO_MT_HASDEC_IDX
:
855 n
= MAX (get_nrows (meta
, MONO_TABLE_TYPEDEF
),
856 get_nrows (meta
, MONO_TABLE_METHOD
));
857 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLY
));
859 /* 2 bits to encode */
860 field_size
= rtsize (meta
, n
, 16-2);
864 * Implementation: File, AssemblyRef, ExportedType
866 case MONO_MT_IMPL_IDX
:
867 n
= MAX (get_nrows (meta
, MONO_TABLE_FILE
),
868 get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
869 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_EXPORTEDTYPE
));
871 /* 2 bits to encode tag */
872 field_size
= rtsize (meta
, n
, 16-2);
876 * HasFieldMarshall: FieldDef, ParamDef
878 case MONO_MT_HFM_IDX
:
879 n
= MAX (get_nrows (meta
, MONO_TABLE_FIELD
),
880 get_nrows (meta
, MONO_TABLE_PARAM
));
882 /* 1 bit used to encode tag */
883 field_size
= rtsize (meta
, n
, 16-1);
887 * MemberForwarded: FieldDef, MethodDef
890 n
= MAX (get_nrows (meta
, MONO_TABLE_FIELD
),
891 get_nrows (meta
, MONO_TABLE_METHOD
));
893 /* 1 bit used to encode tag */
894 field_size
= rtsize (meta
, n
, 16-1);
898 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
900 * It is TypeDef, _TypeRef_, TypeSpec, instead.
902 case MONO_MT_TDOR_IDX
:
903 n
= MAX (get_nrows (meta
, MONO_TABLE_TYPEDEF
),
904 get_nrows (meta
, MONO_TABLE_TYPEREF
));
905 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
907 /* 2 bits to encode */
908 field_size
= rtsize (meta
, n
, 16-2);
912 * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
914 case MONO_MT_MRP_IDX
:
915 n
= MAX (get_nrows (meta
, MONO_TABLE_TYPEDEF
),
916 get_nrows (meta
, MONO_TABLE_TYPEREF
));
917 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_METHOD
));
918 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MODULEREF
));
919 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
921 /* 3 bits to encode */
922 field_size
= rtsize (meta
, n
, 16 - 3);
926 * MethodDefOrRef: MethodDef, MemberRef
928 case MONO_MT_MDOR_IDX
:
929 n
= MAX (get_nrows (meta
, MONO_TABLE_METHOD
),
930 get_nrows (meta
, MONO_TABLE_MEMBERREF
));
932 /* 1 bit used to encode tag */
933 field_size
= rtsize (meta
, n
, 16-1);
937 * HasSemantics: Property, Event
940 n
= MAX (get_nrows (meta
, MONO_TABLE_PROPERTY
),
941 get_nrows (meta
, MONO_TABLE_EVENT
));
943 /* 1 bit used to encode tag */
944 field_size
= rtsize (meta
, n
, 16-1);
948 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
951 n
= MAX (get_nrows (meta
, MONO_TABLE_MODULE
),
952 get_nrows (meta
, MONO_TABLE_MODULEREF
));
953 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
954 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPEREF
));
956 /* 2 bits used to encode tag (ECMA spec claims 3) */
957 field_size
= rtsize (meta
, n
, 16 - 2);
962 * encode field size as follows (we just need to
969 bitfield
|= (field_size
-1) << shift
;
972 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
975 *result_bitfield
= (i
<< 24) | bitfield
;
980 * mono_metadata_compute_table_bases:
981 * \param meta metadata context to compute table values
983 * Computes the table bases for the metadata structure.
984 * This is an internal function used by the image loader code.
987 mono_metadata_compute_table_bases (MonoImage
*meta
)
990 const char *base
= meta
->tables_base
;
992 for (i
= 0; i
< MONO_TABLE_NUM
; i
++) {
993 MonoTableInfo
*table
= &meta
->tables
[i
];
994 if (table
->rows
== 0)
997 table
->row_size
= mono_metadata_compute_size (meta
, i
, &table
->size_bitfield
);
999 base
+= table
->rows
* table
->row_size
;
1004 * mono_metadata_locate:
1005 * \param meta metadata context
1006 * \param table table code.
1007 * \param idx index of element to retrieve from \p table.
1009 * \returns a pointer to the \p idx element in the metadata table
1010 * whose code is \p table.
1013 mono_metadata_locate (MonoImage
*meta
, int table
, int idx
)
1015 /* idx == 0 refers always to NULL */
1016 g_return_val_if_fail (idx
> 0 && idx
<= meta
->tables
[table
].rows
, ""); /*FIXME shouldn't we return NULL here?*/
1018 return meta
->tables
[table
].base
+ (meta
->tables
[table
].row_size
* (idx
- 1));
1022 * mono_metadata_locate_token:
1023 * \param meta metadata context
1024 * \param token metadata token
1026 * \returns a pointer to the data in the metadata represented by the
1030 mono_metadata_locate_token (MonoImage
*meta
, guint32 token
)
1032 return mono_metadata_locate (meta
, token
>> 24, token
& 0xffffff);
1036 * mono_metadata_string_heap:
1037 * \param meta metadata context
1038 * \param index index into the string heap.
1039 * \returns an in-memory pointer to the \p index in the string heap.
1042 mono_metadata_string_heap (MonoImage
*meta
, guint32 index
)
1044 g_assert (index
< meta
->heap_strings
.size
);
1045 g_return_val_if_fail (index
< meta
->heap_strings
.size
, "");
1046 return meta
->heap_strings
.data
+ index
;
1050 * mono_metadata_string_heap_checked:
1051 * \param meta metadata context
1052 * \param index index into the string heap.
1053 * \param error set on error
1054 * \returns an in-memory pointer to the \p index in the string heap.
1055 * On failure returns NULL and sets \p error.
1058 mono_metadata_string_heap_checked (MonoImage
*meta
, guint32 index
, MonoError
*error
)
1060 if (G_UNLIKELY (!(index
< meta
->heap_strings
.size
))) {
1061 const char *image_name
= meta
&& meta
->name
? meta
->name
: "unknown image";
1062 mono_error_set_bad_image_by_name (error
, image_name
, "string heap index %ud out bounds %u: %s", index
, meta
->heap_strings
.size
, image_name
);
1065 return meta
->heap_strings
.data
+ index
;
1069 * mono_metadata_user_string:
1070 * \param meta metadata context
1071 * \param index index into the user string heap.
1072 * \returns an in-memory pointer to the \p index in the user string heap (<code>#US</code>).
1075 mono_metadata_user_string (MonoImage
*meta
, guint32 index
)
1077 g_assert (index
< meta
->heap_us
.size
);
1078 g_return_val_if_fail (index
< meta
->heap_us
.size
, "");
1079 return meta
->heap_us
.data
+ index
;
1083 * mono_metadata_blob_heap:
1084 * \param meta metadata context
1085 * \param index index into the blob.
1086 * \returns an in-memory pointer to the \p index in the Blob heap.
1089 mono_metadata_blob_heap (MonoImage
*meta
, guint32 index
)
1091 /* Some tools can produce assemblies with a size 0 Blob stream. If a
1092 * blob value is optional, if the index == 0 and heap_blob.size == 0
1093 * assertion is hit, consider updating caller to use
1094 * mono_metadata_blob_heap_null_ok and handling a null return value. */
1095 g_assert (!(index
== 0 && meta
->heap_blob
.size
== 0));
1096 g_assert (index
< meta
->heap_blob
.size
);
1097 return meta
->heap_blob
.data
+ index
;
1101 * mono_metadata_blob_heap_null_ok:
1102 * \param meta metadata context
1103 * \param index index into the blob.
1104 * \return an in-memory pointer to the \p index in the Blob heap.
1105 * If the Blob heap is empty or missing and index is 0 returns NULL, instead of asserting.
1108 mono_metadata_blob_heap_null_ok (MonoImage
*meta
, guint32 index
)
1110 if (G_UNLIKELY (index
== 0 && meta
->heap_blob
.size
== 0))
1113 return mono_metadata_blob_heap (meta
, index
);
1117 * mono_metadata_blob_heap_checked:
1118 * \param meta metadata context
1119 * \param index index into the blob.
1120 * \param error set on error
1121 * \returns an in-memory pointer to the \p index in the Blob heap. On failure sets \p error and returns NULL;
1122 * If the Blob heap is empty or missing and \p index is 0 returns NULL, without setting error.
1126 mono_metadata_blob_heap_checked (MonoImage
*meta
, guint32 index
, MonoError
*error
)
1128 if (G_UNLIKELY (index
== 0 && meta
->heap_blob
.size
== 0))
1130 if (G_UNLIKELY (!(index
< meta
->heap_blob
.size
))) {
1131 const char *image_name
= meta
&& meta
->name
? meta
->name
: "unknown image";
1132 mono_error_set_bad_image_by_name (error
, image_name
, "blob heap index %u out of bounds %u: %s", index
, meta
->heap_blob
.size
, image_name
);
1135 return meta
->heap_blob
.data
+ index
;
1139 * mono_metadata_guid_heap:
1140 * \param meta metadata context
1141 * \param index index into the guid heap.
1142 * \returns an in-memory pointer to the \p index in the guid heap.
1145 mono_metadata_guid_heap (MonoImage
*meta
, guint32 index
)
1148 index
*= 16; /* adjust for guid size and 1-based index */
1149 g_return_val_if_fail (index
< meta
->heap_guid
.size
, "");
1150 return meta
->heap_guid
.data
+ index
;
1153 static const unsigned char *
1154 dword_align (const unsigned char *ptr
)
1156 return (const unsigned char *) (((gsize
) (ptr
+ 3)) & ~3);
1160 * mono_metadata_decode_row:
1161 * \param t table to extract information from.
1162 * \param idx index in table.
1163 * \param res array of \p res_size cols to store the results in
1165 * This decompresses the metadata element \p idx in table \p t
1166 * into the \c guint32 \p res array that has \p res_size elements
1169 mono_metadata_decode_row (const MonoTableInfo
*t
, int idx
, guint32
*res
, int res_size
)
1171 guint32 bitfield
= t
->size_bitfield
;
1172 int i
, count
= mono_metadata_table_count (bitfield
);
1175 g_assert (idx
< t
->rows
);
1176 g_assert (idx
>= 0);
1177 data
= t
->base
+ idx
* t
->row_size
;
1179 g_assert (res_size
== count
);
1181 for (i
= 0; i
< count
; i
++) {
1182 int n
= mono_metadata_table_size (bitfield
, i
);
1186 res
[i
] = *data
; break;
1188 res
[i
] = read16 (data
); break;
1190 res
[i
] = read32 (data
); break;
1192 g_assert_not_reached ();
1199 * mono_metadata_decode_row_checked:
1200 * \param image the \c MonoImage the table belongs to
1201 * \param t table to extract information from.
1202 * \param idx index in the table.
1203 * \param res array of \p res_size cols to store the results in
1204 * \param error set on bounds error
1207 * This decompresses the metadata element \p idx in the table \p t
1208 * into the \c guint32 \p res array that has \p res_size elements.
1210 * \returns TRUE if the read succeeded. Otherwise sets \p error and returns FALSE.
1213 mono_metadata_decode_row_checked (const MonoImage
*image
, const MonoTableInfo
*t
, int idx
, guint32
*res
, int res_size
, MonoError
*error
)
1215 guint32 bitfield
= t
->size_bitfield
;
1216 int i
, count
= mono_metadata_table_count (bitfield
);
1218 const char *image_name
= image
&& image
->name
? image
->name
: "unknown image";
1220 if (G_UNLIKELY (! (idx
< t
->rows
&& idx
>= 0))) {
1221 mono_error_set_bad_image_by_name (error
, image_name
, "row index %d out of bounds: %d rows: %s", idx
, t
->rows
, image_name
);
1224 const char *data
= t
->base
+ idx
* t
->row_size
;
1226 if (G_UNLIKELY (res_size
!= count
)) {
1227 mono_error_set_bad_image_by_name (error
, image_name
, "res_size %d != count %d: %s", res_size
, count
, image_name
);
1231 for (i
= 0; i
< count
; i
++) {
1232 int n
= mono_metadata_table_size (bitfield
, i
);
1236 res
[i
] = *data
; break;
1238 res
[i
] = read16 (data
); break;
1240 res
[i
] = read32 (data
); break;
1242 mono_error_set_bad_image_by_name (error
, image_name
, "unexpected table [%d] size %d: %s", i
, n
, image_name
);
1252 * mono_metadata_decode_row_col:
1253 * \param t table to extract information from.
1254 * \param idx index for row in table.
1255 * \param col column in the row.
1257 * This function returns the value of column \p col from the \p idx
1258 * row in the table \p t .
1261 mono_metadata_decode_row_col (const MonoTableInfo
*t
, int idx
, guint col
)
1263 guint32 bitfield
= t
->size_bitfield
;
1268 g_assert (idx
< t
->rows
);
1269 g_assert (col
< mono_metadata_table_count (bitfield
));
1270 data
= t
->base
+ idx
* t
->row_size
;
1272 n
= mono_metadata_table_size (bitfield
, 0);
1273 for (i
= 0; i
< col
; ++i
) {
1275 n
= mono_metadata_table_size (bitfield
, i
+ 1);
1281 return read16 (data
);
1283 return read32 (data
);
1285 g_assert_not_reached ();
1291 * mono_metadata_decode_blob_size:
1292 * \param ptr pointer to a blob object
1293 * \param rptr the new position of the pointer
1295 * This decodes a compressed size as described by 24.2.4 (#US and #Blob a blob or user string object)
1297 * \returns the size of the blob object
1300 mono_metadata_decode_blob_size (const char *xptr
, const char **rptr
)
1302 const unsigned char *ptr
= (const unsigned char *)xptr
;
1305 if ((*ptr
& 0x80) == 0){
1306 size
= ptr
[0] & 0x7f;
1308 } else if ((*ptr
& 0x40) == 0){
1309 size
= ((ptr
[0] & 0x3f) << 8) + ptr
[1];
1312 size
= ((ptr
[0] & 0x1f) << 24) +
1324 * mono_metadata_decode_value:
1325 * \param ptr pointer to decode from
1326 * \param rptr the new position of the pointer
1328 * This routine decompresses 32-bit values as specified in the "Blob and
1329 * Signature" section (23.2)
1331 * \returns the decoded value
1334 mono_metadata_decode_value (const char *_ptr
, const char **rptr
)
1336 const unsigned char *ptr
= (const unsigned char *) _ptr
;
1337 unsigned char b
= *ptr
;
1340 if ((b
& 0x80) == 0){
1343 } else if ((b
& 0x40) == 0){
1344 len
= ((b
& 0x3f) << 8 | ptr
[1]);
1347 len
= ((b
& 0x1f) << 24) |
1360 * mono_metadata_decode_signed_value:
1361 * \param ptr pointer to decode from
1362 * \param rptr the new position of the pointer
1364 * This routine decompresses 32-bit signed values
1365 * (not specified in the spec)
1367 * \returns the decoded value
1370 mono_metadata_decode_signed_value (const char *ptr
, const char **rptr
)
1372 guint32 uval
= mono_metadata_decode_value (ptr
, rptr
);
1373 gint32 ival
= uval
>> 1;
1376 /* ival is a truncated 2's complement negative number. */
1378 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1381 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1382 return ival
- 0x2000;
1383 if (ival
< 0x10000000)
1384 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1385 return ival
- 0x10000000;
1386 g_assert (ival
< 0x20000000);
1387 g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival
, uval
);
1388 return ival
- 0x20000000;
1392 * mono_metadata_translate_token_index:
1393 * Translates the given 1-based index into the \c Method, \c Field, \c Event, or \c Param tables
1394 * using the \c *Ptr tables in uncompressed metadata, if they are available.
1396 * FIXME: The caller is not forced to call this function, which is error-prone, since
1397 * forgetting to call it would only show up as a bug on uncompressed metadata.
1400 mono_metadata_translate_token_index (MonoImage
*image
, int table
, guint32 idx
)
1402 if (!image
->uncompressed_metadata
)
1406 case MONO_TABLE_METHOD
:
1407 if (image
->tables
[MONO_TABLE_METHOD_POINTER
].rows
)
1408 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_METHOD_POINTER
], idx
- 1, MONO_METHOD_POINTER_METHOD
);
1411 case MONO_TABLE_FIELD
:
1412 if (image
->tables
[MONO_TABLE_FIELD_POINTER
].rows
)
1413 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_FIELD_POINTER
], idx
- 1, MONO_FIELD_POINTER_FIELD
);
1416 case MONO_TABLE_EVENT
:
1417 if (image
->tables
[MONO_TABLE_EVENT_POINTER
].rows
)
1418 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_EVENT_POINTER
], idx
- 1, MONO_EVENT_POINTER_EVENT
);
1421 case MONO_TABLE_PROPERTY
:
1422 if (image
->tables
[MONO_TABLE_PROPERTY_POINTER
].rows
)
1423 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PROPERTY_POINTER
], idx
- 1, MONO_PROPERTY_POINTER_PROPERTY
);
1426 case MONO_TABLE_PARAM
:
1427 if (image
->tables
[MONO_TABLE_PARAM_POINTER
].rows
)
1428 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PARAM_POINTER
], idx
- 1, MONO_PARAM_POINTER_PARAM
);
1437 * mono_metadata_decode_table_row:
1439 * Same as \c mono_metadata_decode_row, but takes an \p image + \p table ID pair, and takes
1440 * uncompressed metadata into account, so it should be used to access the
1441 * \c Method, \c Field, \c Param and \c Event tables when the access is made from metadata, i.e.
1442 * \p idx is retrieved from a metadata table, like \c MONO_TYPEDEF_FIELD_LIST.
1445 mono_metadata_decode_table_row (MonoImage
*image
, int table
, int idx
, guint32
*res
, int res_size
)
1447 if (image
->uncompressed_metadata
)
1448 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1450 mono_metadata_decode_row (&image
->tables
[table
], idx
, res
, res_size
);
1454 * mono_metadata_decode_table_row_col:
1456 * Same as \c mono_metadata_decode_row_col, but takes an \p image + \p table ID pair, and takes
1457 * uncompressed metadata into account, so it should be used to access the
1458 * \c Method, \c Field, \c Param and \c Event tables.
1460 guint32
mono_metadata_decode_table_row_col (MonoImage
*image
, int table
, int idx
, guint col
)
1462 if (image
->uncompressed_metadata
)
1463 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1465 return mono_metadata_decode_row_col (&image
->tables
[table
], idx
, col
);
1469 * mono_metadata_parse_typedef_or_ref:
1470 * \param m a metadata context.
1471 * \param ptr a pointer to an encoded TypedefOrRef in \p m
1472 * \param rptr pointer updated to match the end of the decoded stream
1473 * \returns a token valid in the \p m metadata decoded from
1474 * the compressed representation.
1477 mono_metadata_parse_typedef_or_ref (MonoImage
*m
, const char *ptr
, const char **rptr
)
1480 token
= mono_metadata_decode_value (ptr
, &ptr
);
1483 return mono_metadata_token_from_dor (token
);
1487 * mono_metadata_parse_custom_mod:
1488 * \param m a metadata context.
1489 * \param dest storage where the info about the custom modifier is stored (may be NULL)
1490 * \param ptr a pointer to (possibly) the start of a custom modifier list
1491 * \param rptr pointer updated to match the end of the decoded stream
1493 * Checks if \p ptr points to a type custom modifier compressed representation.
1495 * \returns TRUE if a custom modifier was found, FALSE if not.
1498 mono_metadata_parse_custom_mod (MonoImage
*m
, MonoCustomMod
*dest
, const char *ptr
, const char **rptr
)
1500 MonoCustomMod local
;
1501 if ((*ptr
== MONO_TYPE_CMOD_OPT
) || (*ptr
== MONO_TYPE_CMOD_REQD
)) {
1504 dest
->required
= *ptr
== MONO_TYPE_CMOD_REQD
? 1 : 0;
1505 dest
->token
= mono_metadata_parse_typedef_or_ref (m
, ptr
+ 1, rptr
);
1512 * mono_metadata_parse_array_internal:
1513 * @m: a metadata context.
1514 * @transient: whenever to allocate data from the heap
1515 * @ptr: a pointer to an encoded array description.
1516 * @rptr: pointer updated to match the end of the decoded stream
1518 * Decodes the compressed array description found in the metadata @m at @ptr.
1520 * Returns: a #MonoArrayType structure describing the array type
1521 * and dimensions. Memory is allocated from the heap or from the image mempool, depending
1522 * on the value of @transient.
1524 * LOCKING: Acquires the loader lock
1526 static MonoArrayType
*
1527 mono_metadata_parse_array_internal (MonoImage
*m
, MonoGenericContainer
*container
,
1528 gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1531 MonoArrayType
*array
;
1534 etype
= mono_metadata_parse_type_checked (m
, container
, 0, FALSE
, ptr
, &ptr
, error
); //FIXME this doesn't respect @transient
1538 array
= transient
? (MonoArrayType
*)g_malloc0 (sizeof (MonoArrayType
)) : (MonoArrayType
*)mono_image_alloc0 (m
, sizeof (MonoArrayType
));
1539 array
->eklass
= mono_class_from_mono_type_internal (etype
);
1540 array
->rank
= mono_metadata_decode_value (ptr
, &ptr
);
1542 array
->numsizes
= mono_metadata_decode_value (ptr
, &ptr
);
1543 if (array
->numsizes
)
1544 array
->sizes
= transient
? (int *)g_malloc0 (sizeof (int) * array
->numsizes
) : (int *)mono_image_alloc0 (m
, sizeof (int) * array
->numsizes
);
1545 for (i
= 0; i
< array
->numsizes
; ++i
)
1546 array
->sizes
[i
] = mono_metadata_decode_value (ptr
, &ptr
);
1548 array
->numlobounds
= mono_metadata_decode_value (ptr
, &ptr
);
1549 if (array
->numlobounds
)
1550 array
->lobounds
= transient
? (int *)g_malloc0 (sizeof (int) * array
->numlobounds
) : (int *)mono_image_alloc0 (m
, sizeof (int) * array
->numlobounds
);
1551 for (i
= 0; i
< array
->numlobounds
; ++i
)
1552 array
->lobounds
[i
] = mono_metadata_decode_signed_value (ptr
, &ptr
);
1560 * mono_metadata_parse_array:
1563 mono_metadata_parse_array (MonoImage
*m
, const char *ptr
, const char **rptr
)
1566 MonoArrayType
*ret
= mono_metadata_parse_array_internal (m
, NULL
, FALSE
, ptr
, rptr
, error
);
1567 mono_error_cleanup (error
);
1573 * mono_metadata_free_array:
1574 * \param array array description
1576 * Frees the array description returned from \c mono_metadata_parse_array.
1579 mono_metadata_free_array (MonoArrayType
*array
)
1581 g_free (array
->sizes
);
1582 g_free (array
->lobounds
);
1587 * need to add common field and param attributes combinations:
1590 * public static literal
1593 * private static literal
1595 static const MonoType
1597 /* data, attrs, type, nmods, byref, pinned */
1598 {{NULL
}, 0, MONO_TYPE_VOID
, 0, 0, 0},
1599 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 0, 0},
1600 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 1, 0},
1601 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 0, 0},
1602 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 1, 0},
1603 {{NULL
}, 0, MONO_TYPE_I1
, 0, 0, 0},
1604 {{NULL
}, 0, MONO_TYPE_I1
, 0, 1, 0},
1605 {{NULL
}, 0, MONO_TYPE_U1
, 0, 0, 0},
1606 {{NULL
}, 0, MONO_TYPE_U1
, 0, 1, 0},
1607 {{NULL
}, 0, MONO_TYPE_I2
, 0, 0, 0},
1608 {{NULL
}, 0, MONO_TYPE_I2
, 0, 1, 0},
1609 {{NULL
}, 0, MONO_TYPE_U2
, 0, 0, 0},
1610 {{NULL
}, 0, MONO_TYPE_U2
, 0, 1, 0},
1611 {{NULL
}, 0, MONO_TYPE_I4
, 0, 0, 0},
1612 {{NULL
}, 0, MONO_TYPE_I4
, 0, 1, 0},
1613 {{NULL
}, 0, MONO_TYPE_U4
, 0, 0, 0},
1614 {{NULL
}, 0, MONO_TYPE_U4
, 0, 1, 0},
1615 {{NULL
}, 0, MONO_TYPE_I8
, 0, 0, 0},
1616 {{NULL
}, 0, MONO_TYPE_I8
, 0, 1, 0},
1617 {{NULL
}, 0, MONO_TYPE_U8
, 0, 0, 0},
1618 {{NULL
}, 0, MONO_TYPE_U8
, 0, 1, 0},
1619 {{NULL
}, 0, MONO_TYPE_R4
, 0, 0, 0},
1620 {{NULL
}, 0, MONO_TYPE_R4
, 0, 1, 0},
1621 {{NULL
}, 0, MONO_TYPE_R8
, 0, 0, 0},
1622 {{NULL
}, 0, MONO_TYPE_R8
, 0, 1, 0},
1623 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 0, 0},
1624 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 1, 0},
1625 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 0, 0},
1626 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 1, 0},
1627 {{NULL
}, 0, MONO_TYPE_TYPEDBYREF
, 0, 0, 0},
1628 {{NULL
}, 0, MONO_TYPE_I
, 0, 0, 0},
1629 {{NULL
}, 0, MONO_TYPE_I
, 0, 1, 0},
1630 {{NULL
}, 0, MONO_TYPE_U
, 0, 0, 0},
1631 {{NULL
}, 0, MONO_TYPE_U
, 0, 1, 0},
1634 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1636 static GHashTable
*type_cache
= NULL
;
1637 static gint32 next_generic_inst_id
= 0;
1639 /* Protected by image_sets_mutex */
1640 static MonoImageSet
*mscorlib_image_set
;
1641 /* Protected by image_sets_mutex */
1642 static GPtrArray
*image_sets
;
1643 static mono_mutex_t image_sets_mutex
;
1645 static guint
mono_generic_class_hash (gconstpointer data
);
1648 * MonoTypes with modifies are never cached, so we never check or use that field.
1651 mono_type_hash (gconstpointer data
)
1653 const MonoType
*type
= (const MonoType
*) data
;
1654 if (type
->type
== MONO_TYPE_GENERICINST
)
1655 return mono_generic_class_hash (type
->data
.generic_class
);
1657 return type
->type
| (type
->byref
<< 8) | (type
->attrs
<< 9);
1661 mono_type_equal (gconstpointer ka
, gconstpointer kb
)
1663 const MonoType
*a
= (const MonoType
*) ka
;
1664 const MonoType
*b
= (const MonoType
*) kb
;
1666 if (a
->type
!= b
->type
|| a
->byref
!= b
->byref
|| a
->attrs
!= b
->attrs
|| a
->pinned
!= b
->pinned
)
1668 /* need other checks */
1673 mono_metadata_generic_inst_hash (gconstpointer data
)
1675 const MonoGenericInst
*ginst
= (const MonoGenericInst
*) data
;
1679 g_assert (ginst
->type_argv
);
1681 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
1683 g_assert (ginst
->type_argv
[i
]);
1684 hash
+= mono_metadata_type_hash (ginst
->type_argv
[i
]);
1687 return hash
^ (ginst
->is_open
<< 8);
1691 mono_generic_inst_equal_full (const MonoGenericInst
*a
, const MonoGenericInst
*b
, gboolean signature_only
)
1695 // An optimization: if the ids of two insts are the same, we know they are the same inst and don't check contents.
1696 // Furthermore, because we perform early de-duping, if the ids differ, we know the contents differ.
1697 #ifndef MONO_SMALL_CONFIG // Optimization does not work in MONO_SMALL_CONFIG: There are no IDs
1698 if (a
->id
&& b
->id
) { // "id 0" means "object has no id"-- de-duping hasn't been performed yet, must check contents.
1701 // In signature-comparison mode id equality implies object equality, but this is not true for inequality.
1702 // Two separate objects could have signature-equavalent contents.
1703 if (!signature_only
)
1708 if (a
->is_open
!= b
->is_open
|| a
->type_argc
!= b
->type_argc
)
1710 for (i
= 0; i
< a
->type_argc
; ++i
) {
1711 if (!do_mono_metadata_type_equal (a
->type_argv
[i
], b
->type_argv
[i
], signature_only
))
1718 mono_metadata_generic_inst_equal (gconstpointer ka
, gconstpointer kb
)
1720 const MonoGenericInst
*a
= (const MonoGenericInst
*) ka
;
1721 const MonoGenericInst
*b
= (const MonoGenericInst
*) kb
;
1723 return mono_generic_inst_equal_full (a
, b
, FALSE
);
1727 mono_generic_class_hash (gconstpointer data
)
1729 const MonoGenericClass
*gclass
= (const MonoGenericClass
*) data
;
1730 guint hash
= mono_metadata_type_hash (m_class_get_byval_arg (gclass
->container_class
));
1733 hash
+= gclass
->is_tb_open
;
1734 hash
+= mono_metadata_generic_context_hash (&gclass
->context
);
1740 mono_generic_class_equal (gconstpointer ka
, gconstpointer kb
)
1742 const MonoGenericClass
*a
= (const MonoGenericClass
*) ka
;
1743 const MonoGenericClass
*b
= (const MonoGenericClass
*) kb
;
1745 return _mono_metadata_generic_class_equal (a
, b
, FALSE
);
1749 * mono_metadata_init:
1751 * Initialize the global variables of this module.
1752 * This is a Mono runtime internal function.
1755 mono_metadata_init (void)
1759 /* We guard against double initialization due to how pedump in verification mode works.
1760 Until runtime initialization is properly factored to work with what it needs we need workarounds like this.
1761 FIXME: https://bugzilla.xamarin.com/show_bug.cgi?id=58793
1763 static gboolean inited
;
1769 type_cache
= g_hash_table_new (mono_type_hash
, mono_type_equal
);
1771 for (i
= 0; i
< NBUILTIN_TYPES (); ++i
)
1772 g_hash_table_insert (type_cache
, (gpointer
) &builtin_types
[i
], (gpointer
) &builtin_types
[i
]);
1774 mono_os_mutex_init_recursive (&image_sets_mutex
);
1776 mono_counters_register ("ImgSet Cache Hit", MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &img_set_cache_hit
);
1777 mono_counters_register ("ImgSet Cache Miss", MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &img_set_cache_miss
);
1778 mono_counters_register ("ImgSet Count", MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &img_set_count
);
1782 * mono_metadata_cleanup:
1784 * Free all resources used by this module.
1785 * This is a Mono runtime internal function.
1788 mono_metadata_cleanup (void)
1790 g_hash_table_destroy (type_cache
);
1792 g_ptr_array_free (image_sets
, TRUE
);
1794 mono_os_mutex_destroy (&image_sets_mutex
);
1798 * mono_metadata_parse_type:
1799 * \param m metadata context
1800 * \param mode kind of type that may be found at \p ptr
1801 * \param opt_attrs optional attributes to store in the returned type
1802 * \param ptr pointer to the type representation
1803 * \param rptr pointer updated to match the end of the decoded stream
1804 * \param transient whenever to allocate the result from the heap or from a mempool
1806 * Decode a compressed type description found at \p ptr in \p m .
1807 * \p mode can be one of \c MONO_PARSE_MOD_TYPE, \c MONO_PARSE_PARAM, \c MONO_PARSE_RET,
1808 * \c MONO_PARSE_FIELD, \c MONO_PARSE_LOCAL, \c MONO_PARSE_TYPE.
1809 * This function can be used to decode type descriptions in method signatures,
1810 * field signatures, locals signatures etc.
1812 * To parse a generic type, \c generic_container points to the current class'es
1813 * (the \c generic_container field in the <code>MonoClass</code>) or the current generic method's
1814 * (stored in <code>image->property_hash</code>) generic container.
1815 * When we encounter a \c MONO_TYPE_VAR or \c MONO_TYPE_MVAR, it's looked up in
1816 * this \c MonoGenericContainer.
1818 * LOCKING: Acquires the loader lock.
1820 * \returns a \c MonoType structure representing the decoded type.
1823 mono_metadata_parse_type_internal (MonoImage
*m
, MonoGenericContainer
*container
,
1824 short opt_attrs
, gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1826 MonoType
*type
, *cached
;
1828 gboolean byref
= FALSE
;
1829 gboolean pinned
= FALSE
;
1830 const char *tmp_ptr
;
1831 int count
= 0; // Number of mod arguments
1837 * According to the spec, custom modifiers should come before the byref
1838 * flag, but the IL produced by ilasm from the following signature:
1839 * object modopt(...) &
1840 * starts with a byref flag, followed by the modifiers. (bug #49802)
1841 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1842 * it would be better to treat byref as real type constructor instead of
1844 * Also, pinned should come before anything else, but some MSV++ produced
1845 * assemblies violate this (#bug 61990).
1848 /* Count the modifiers first */
1853 case MONO_TYPE_PINNED
:
1854 case MONO_TYPE_BYREF
:
1857 case MONO_TYPE_CMOD_REQD
:
1858 case MONO_TYPE_CMOD_OPT
:
1860 mono_metadata_parse_custom_mod (m
, NULL
, tmp_ptr
, &tmp_ptr
);
1867 MonoCustomModContainer
*cmods
= NULL
;
1869 if (count
) { // There are mods, so the MonoType will be of nonstandard size.
1871 mono_error_set_bad_image (error
, m
, "Invalid type with more than 64 modifiers");
1875 size_t size
= mono_sizeof_type_with_mods (count
, FALSE
);
1876 type
= transient
? (MonoType
*)g_malloc0 (size
) : (MonoType
*)mono_image_alloc0 (m
, size
);
1877 type
->has_cmods
= TRUE
;
1879 cmods
= mono_type_get_cmods (type
);
1880 cmods
->count
= count
;
1882 } else { // The type is of standard size, so we can allocate it on the stack.
1884 memset (type
, 0, MONO_SIZEOF_TYPE
);
1887 /* Iterate again, but now parse pinned, byref and custom modifiers */
1889 /* cmods are encoded in reverse order from how we normally see them.
1890 * "int32 modopt (Foo) modopt (Bar)" is encoded as "cmod_opt [typedef_or_ref "Bar"] cmod_opt [typedef_or_ref "Foo"] I4"
1894 case MONO_TYPE_PINNED
:
1898 case MONO_TYPE_BYREF
:
1902 case MONO_TYPE_CMOD_REQD
:
1903 case MONO_TYPE_CMOD_OPT
:
1904 mono_metadata_parse_custom_mod (m
, &(cmods
->modifiers
[--count
]), ptr
, &ptr
);
1911 // either there were no cmods, or else we iterated through all of cmods backwards to populate it.
1912 g_assert (count
== 0);
1914 type
->attrs
= opt_attrs
;
1915 type
->byref
= byref
;
1916 type
->pinned
= pinned
? 1 : 0;
1918 if (!do_mono_metadata_parse_type (type
, m
, container
, transient
, ptr
, &ptr
, error
))
1924 // Possibly we can return an already-allocated type instead of the one we decoded
1925 if (!type
->has_cmods
&& !transient
) {
1926 /* no need to free type here, because it is on the stack */
1927 if ((type
->type
== MONO_TYPE_CLASS
|| type
->type
== MONO_TYPE_VALUETYPE
) && !type
->pinned
&& !type
->attrs
) {
1928 MonoType
*ret
= type
->byref
? m_class_get_this_arg (type
->data
.klass
) : m_class_get_byval_arg (type
->data
.klass
);
1930 /* Consider the case:
1932 class Foo<T> { class Bar {} }
1933 class Test : Foo<Test>.Bar {}
1935 When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
1936 a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1938 We ensure that the MonoClass is in a state that we can canonicalize to:
1940 klass->_byval_arg.data.klass == klass
1941 klass->this_arg.data.klass == klass
1943 If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1945 LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1946 of a MonoClass which currently holds the loader lock. 'type' is local.
1948 if (ret
->data
.klass
== type
->data
.klass
) {
1952 /* No need to use locking since nobody is modifying the hash table */
1953 if ((cached
= (MonoType
*)g_hash_table_lookup (type_cache
, type
))) {
1958 /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1960 if (type
== &stype
) { // Type was allocated on the stack, so we need to copy it to safety
1961 type
= transient
? (MonoType
*)g_malloc (MONO_SIZEOF_TYPE
) : (MonoType
*)mono_image_alloc (m
, MONO_SIZEOF_TYPE
);
1962 memcpy (type
, &stype
, MONO_SIZEOF_TYPE
);
1969 mono_metadata_parse_type_checked (MonoImage
*m
, MonoGenericContainer
*container
,
1970 short opt_attrs
, gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1972 return mono_metadata_parse_type_internal (m
, container
, opt_attrs
, transient
, ptr
, rptr
, error
);
1976 * LOCKING: Acquires the loader lock.
1979 mono_metadata_parse_type (MonoImage
*m
, MonoParseTypeMode mode
, short opt_attrs
,
1980 const char *ptr
, const char **rptr
)
1983 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, opt_attrs
, FALSE
, ptr
, rptr
, error
);
1984 mono_error_cleanup (error
);
1989 mono_metadata_method_has_param_attrs (MonoImage
*m
, int def
)
1991 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1992 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1993 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1995 if (def
< methodt
->rows
)
1996 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1998 lastp
= m
->tables
[MONO_TABLE_PARAM
].rows
+ 1;
2000 for (i
= param_index
; i
< lastp
; ++i
) {
2001 guint32 flags
= mono_metadata_decode_row_col (paramt
, i
- 1, MONO_PARAM_FLAGS
);
2010 * mono_metadata_get_param_attrs:
2012 * @m The image to loader parameter attributes from
2013 * @def method def token (one based)
2014 * @param_count number of params to decode including the return value
2016 * Return the parameter attributes for the method whose MethodDef index is DEF. The
2017 * returned memory needs to be freed by the caller. If all the param attributes are
2018 * 0, then NULL is returned.
2021 mono_metadata_get_param_attrs (MonoImage
*m
, int def
, int param_count
)
2023 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
2024 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
2025 guint32 cols
[MONO_PARAM_SIZE
];
2026 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
2029 if (def
< methodt
->rows
)
2030 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
2032 lastp
= paramt
->rows
+ 1;
2034 for (i
= param_index
; i
< lastp
; ++i
) {
2035 mono_metadata_decode_row (paramt
, i
- 1, cols
, MONO_PARAM_SIZE
);
2036 if (cols
[MONO_PARAM_FLAGS
]) {
2038 pattrs
= g_new0 (int, param_count
);
2039 /* at runtime we just ignore this kind of malformed file:
2040 * the verifier can signal the error to the user
2042 if (cols
[MONO_PARAM_SEQUENCE
] >= param_count
)
2044 pattrs
[cols
[MONO_PARAM_SEQUENCE
]] = cols
[MONO_PARAM_FLAGS
];
2053 * mono_metadata_parse_signature:
2054 * \param image metadata context
2055 * \param token metadata token
2057 * Decode a method signature stored in the \c StandAloneSig table
2059 * \returns a \c MonoMethodSignature describing the signature.
2061 MonoMethodSignature
*
2062 mono_metadata_parse_signature (MonoImage
*image
, guint32 token
)
2065 MonoMethodSignature
*ret
;
2066 ret
= mono_metadata_parse_signature_checked (image
, token
, error
);
2067 mono_error_cleanup (error
);
2072 * mono_metadata_parse_signature_checked:
2073 * @image: metadata context
2074 * @token: metadata token
2075 * @error: set on error
2077 * Decode a method signature stored in the STANDALONESIG table
2079 * Returns: a MonoMethodSignature describing the signature. On failure
2080 * returns NULL and sets @error.
2082 MonoMethodSignature
*
2083 mono_metadata_parse_signature_checked (MonoImage
*image
, guint32 token
, MonoError
*error
)
2087 MonoTableInfo
*tables
= image
->tables
;
2088 guint32 idx
= mono_metadata_token_index (token
);
2092 if (image_is_dynamic (image
)) {
2093 return (MonoMethodSignature
*)mono_lookup_dynamic_token (image
, token
, NULL
, error
);
2096 g_assert (mono_metadata_token_table(token
) == MONO_TABLE_STANDALONESIG
);
2098 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
2100 ptr
= mono_metadata_blob_heap (image
, sig
);
2101 mono_metadata_decode_blob_size (ptr
, &ptr
);
2103 return mono_metadata_parse_method_signature_full (image
, NULL
, 0, ptr
, NULL
, error
);
2107 * mono_metadata_signature_alloc:
2108 * \param image metadata context
2109 * \param nparams number of parameters in the signature
2111 * Allocate a \c MonoMethodSignature structure with the specified number of params.
2112 * The return type and the params types need to be filled later.
2113 * This is a Mono runtime internal function.
2115 * LOCKING: Assumes the loader lock is held.
2117 * \returns the new \c MonoMethodSignature structure.
2119 MonoMethodSignature
*
2120 mono_metadata_signature_alloc (MonoImage
*m
, guint32 nparams
)
2122 MonoMethodSignature
*sig
;
2124 sig
= (MonoMethodSignature
*)mono_image_alloc0 (m
, MONO_SIZEOF_METHOD_SIGNATURE
+ ((gint32
)nparams
) * sizeof (MonoType
*));
2125 sig
->param_count
= nparams
;
2126 sig
->sentinelpos
= -1;
2131 static MonoMethodSignature
*
2132 mono_metadata_signature_dup_internal_with_padding (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
, size_t padding
)
2134 int sigsize
, sig_header_size
;
2135 MonoMethodSignature
*ret
;
2136 sigsize
= sig_header_size
= MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*) + padding
;
2138 sigsize
+= mono_sizeof_type (sig
->ret
);
2141 ret
= (MonoMethodSignature
*)mono_image_alloc (image
, sigsize
);
2143 ret
= (MonoMethodSignature
*)mono_mempool_alloc (mp
, sigsize
);
2145 ret
= (MonoMethodSignature
*)g_malloc (sigsize
);
2148 memcpy (ret
, sig
, sig_header_size
- padding
);
2150 // Copy return value because of ownership semantics.
2152 // Danger! Do not alter padding use without changing the dup_add_this below
2153 intptr_t end_of_header
= (intptr_t)( (char*)(ret
) + sig_header_size
);
2154 ret
->ret
= (MonoType
*)end_of_header
;
2155 memcpy (ret
->ret
, sig
->ret
, mono_sizeof_type (sig
->ret
));
2161 static MonoMethodSignature
*
2162 mono_metadata_signature_dup_internal (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
)
2164 return mono_metadata_signature_dup_internal_with_padding (image
, mp
, sig
, 0);
2167 * signature_dup_add_this:
2169 * Make a copy of @sig, adding an explicit this argument.
2171 MonoMethodSignature
*
2172 mono_metadata_signature_dup_add_this (MonoImage
*image
, MonoMethodSignature
*sig
, MonoClass
*klass
)
2174 MonoMethodSignature
*ret
;
2175 ret
= mono_metadata_signature_dup_internal_with_padding (image
, NULL
, sig
, sizeof (MonoType
*));
2177 ret
->param_count
= sig
->param_count
+ 1;
2178 ret
->hasthis
= FALSE
;
2180 for (int i
= sig
->param_count
- 1; i
>= 0; i
--)
2181 ret
->params
[i
+ 1] = sig
->params
[i
];
2182 ret
->params
[0] = m_class_is_valuetype (klass
) ? m_class_get_this_arg (klass
) : m_class_get_byval_arg (klass
);
2184 for (int i
= sig
->param_count
- 1; i
>= 0; i
--)
2185 g_assert(ret
->params
[i
+ 1]->type
== sig
->params
[i
]->type
&& ret
->params
[i
+1]->type
!= MONO_TYPE_END
);
2186 g_assert (ret
->ret
->type
== sig
->ret
->type
&& ret
->ret
->type
!= MONO_TYPE_END
);
2193 MonoMethodSignature
*
2194 mono_metadata_signature_dup_full (MonoImage
*image
, MonoMethodSignature
*sig
)
2196 MonoMethodSignature
*ret
= mono_metadata_signature_dup_internal (image
, NULL
, sig
);
2198 for (int i
= 0 ; i
< sig
->param_count
; i
++)
2199 g_assert(ret
->params
[i
]->type
== sig
->params
[i
]->type
);
2200 g_assert (ret
->ret
->type
== sig
->ret
->type
);
2205 /*The mempool is accessed without synchronization*/
2206 MonoMethodSignature
*
2207 mono_metadata_signature_dup_mempool (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
2209 return mono_metadata_signature_dup_internal (NULL
, mp
, sig
);
2213 * mono_metadata_signature_dup:
2214 * \param sig method signature
2216 * Duplicate an existing \c MonoMethodSignature so it can be modified.
2217 * This is a Mono runtime internal function.
2219 * \returns the new \c MonoMethodSignature structure.
2221 MonoMethodSignature
*
2222 mono_metadata_signature_dup (MonoMethodSignature
*sig
)
2224 return mono_metadata_signature_dup_full (NULL
, sig
);
2228 * mono_metadata_signature_size:
2230 * Return the amount of memory allocated to SIG.
2233 mono_metadata_signature_size (MonoMethodSignature
*sig
)
2235 return MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*);
2239 * mono_metadata_parse_method_signature_full:
2240 * \param m metadata context
2241 * \param generic_container: generics container
2242 * \param def the \c MethodDef index or 0 for \c Ref signatures.
2243 * \param ptr pointer to the signature metadata representation
2244 * \param rptr pointer updated to match the end of the decoded stream
2245 * \param error set on error
2248 * Decode a method signature stored at \p ptr.
2249 * This is a Mono runtime internal function.
2251 * LOCKING: Assumes the loader lock is held.
2253 * \returns a \c MonoMethodSignature describing the signature. On error sets
2254 * \p error and returns \c NULL.
2256 MonoMethodSignature
*
2257 mono_metadata_parse_method_signature_full (MonoImage
*m
, MonoGenericContainer
*container
,
2258 int def
, const char *ptr
, const char **rptr
, MonoError
*error
)
2260 MonoMethodSignature
*method
;
2261 int i
, *pattrs
= NULL
;
2262 guint32 hasthis
= 0, explicit_this
= 0, call_convention
, param_count
;
2263 guint32 gen_param_count
= 0;
2264 gboolean is_open
= FALSE
;
2269 gen_param_count
= 1;
2274 call_convention
= *ptr
& 0x0F;
2276 if (gen_param_count
)
2277 gen_param_count
= mono_metadata_decode_value (ptr
, &ptr
);
2278 param_count
= mono_metadata_decode_value (ptr
, &ptr
);
2281 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 */
2283 method
= mono_metadata_signature_alloc (m
, param_count
);
2284 method
->hasthis
= hasthis
;
2285 method
->explicit_this
= explicit_this
;
2286 method
->call_convention
= call_convention
;
2287 method
->generic_param_count
= gen_param_count
;
2289 switch (method
->call_convention
) {
2290 case MONO_CALL_DEFAULT
:
2291 case MONO_CALL_VARARG
:
2292 method
->pinvoke
= 0;
2295 case MONO_CALL_STDCALL
:
2296 case MONO_CALL_THISCALL
:
2297 case MONO_CALL_FASTCALL
:
2298 method
->pinvoke
= 1;
2302 if (call_convention
!= 0xa) {
2303 method
->ret
= mono_metadata_parse_type_checked (m
, container
, pattrs
? pattrs
[0] : 0, FALSE
, ptr
, &ptr
, error
);
2305 mono_metadata_free_method_signature (method
);
2309 is_open
= mono_class_is_open_constructed_type (method
->ret
);
2312 for (i
= 0; i
< method
->param_count
; ++i
) {
2313 if (*ptr
== MONO_TYPE_SENTINEL
) {
2314 if (method
->call_convention
!= MONO_CALL_VARARG
|| def
) {
2315 mono_error_set_bad_image (error
, m
, "Found sentinel for methoddef or no vararg");
2319 if (method
->sentinelpos
>= 0) {
2320 mono_error_set_bad_image (error
, m
, "Found sentinel twice in the same signature.");
2324 method
->sentinelpos
= i
;
2327 method
->params
[i
] = mono_metadata_parse_type_checked (m
, container
, pattrs
? pattrs
[i
+1] : 0, FALSE
, ptr
, &ptr
, error
);
2328 if (!method
->params
[i
]) {
2329 mono_metadata_free_method_signature (method
);
2334 is_open
= mono_class_is_open_constructed_type (method
->params
[i
]);
2337 /* The sentinel could be missing if the caller does not pass any additional arguments */
2338 if (!def
&& method
->call_convention
== MONO_CALL_VARARG
&& method
->sentinelpos
< 0)
2339 method
->sentinelpos
= method
->param_count
;
2341 method
->has_type_parameters
= is_open
;
2343 if (def
&& (method
->call_convention
== MONO_CALL_VARARG
))
2344 method
->sentinelpos
= method
->param_count
;
2351 * Add signature to a cache and increase ref count...
2358 * mono_metadata_parse_method_signature:
2359 * \param m metadata context
2360 * \param def the \c MethodDef index or 0 for \c Ref signatures.
2361 * \param ptr pointer to the signature metadata representation
2362 * \param rptr pointer updated to match the end of the decoded stream
2364 * Decode a method signature stored at \p ptr.
2365 * This is a Mono runtime internal function.
2367 * LOCKING: Assumes the loader lock is held.
2369 * \returns a \c MonoMethodSignature describing the signature.
2371 MonoMethodSignature
*
2372 mono_metadata_parse_method_signature (MonoImage
*m
, int def
, const char *ptr
, const char **rptr
)
2375 * This function MUST NOT be called by runtime code as it does error handling incorrectly.
2376 * Use mono_metadata_parse_method_signature_full instead.
2377 * It's ok to asser on failure as we no longer use it.
2380 MonoMethodSignature
*ret
;
2381 ret
= mono_metadata_parse_method_signature_full (m
, NULL
, def
, ptr
, rptr
, error
);
2382 mono_error_assert_ok (error
);
2388 * mono_metadata_free_method_signature:
2389 * \param sig signature to destroy
2391 * Free the memory allocated in the signature \p sig.
2392 * This method needs to be robust and work also on partially-built
2393 * signatures, so it does extra checks.
2396 mono_metadata_free_method_signature (MonoMethodSignature
*sig
)
2398 /* Everything is allocated from mempools */
2402 mono_metadata_free_type (sig->ret);
2403 for (i = 0; i < sig->param_count; ++i) {
2404 if (sig->params [i])
2405 mono_metadata_free_type (sig->params [i]);
2411 mono_metadata_free_inflated_signature (MonoMethodSignature
*sig
)
2415 /* Allocated in inflate_generic_signature () */
2417 mono_metadata_free_type (sig
->ret
);
2418 for (i
= 0; i
< sig
->param_count
; ++i
) {
2419 if (sig
->params
[i
])
2420 mono_metadata_free_type (sig
->params
[i
]);
2426 inflated_method_equal (gconstpointer a
, gconstpointer b
)
2428 const MonoMethodInflated
*ma
= (const MonoMethodInflated
*)a
;
2429 const MonoMethodInflated
*mb
= (const MonoMethodInflated
*)b
;
2430 if (ma
->declaring
!= mb
->declaring
)
2432 return mono_metadata_generic_context_equal (&ma
->context
, &mb
->context
);
2436 inflated_method_hash (gconstpointer a
)
2438 const MonoMethodInflated
*ma
= (const MonoMethodInflated
*)a
;
2439 return (mono_metadata_generic_context_hash (&ma
->context
) ^ mono_aligned_addr_hash (ma
->declaring
));
2443 inflated_signature_equal (gconstpointer a
, gconstpointer b
)
2445 const MonoInflatedMethodSignature
*sig1
= (const MonoInflatedMethodSignature
*)a
;
2446 const MonoInflatedMethodSignature
*sig2
= (const MonoInflatedMethodSignature
*)b
;
2448 /* sig->sig is assumed to be canonized */
2449 if (sig1
->sig
!= sig2
->sig
)
2451 /* The generic instances are canonized */
2452 return mono_metadata_generic_context_equal (&sig1
->context
, &sig2
->context
);
2456 inflated_signature_hash (gconstpointer a
)
2458 const MonoInflatedMethodSignature
*sig
= (const MonoInflatedMethodSignature
*)a
;
2460 /* sig->sig is assumed to be canonized */
2461 return mono_metadata_generic_context_hash (&sig
->context
) ^ mono_aligned_addr_hash (sig
->sig
);
2465 dump_ginst (MonoGenericInst *ginst)
2470 g_print ("Ginst: <");
2471 for (i = 0; i < ginst->type_argc; ++i) {
2474 name = mono_type_get_name (ginst->type_argv [i]);
2475 g_print ("%s", name);
2482 aggregate_modifiers_equal (gconstpointer ka
, gconstpointer kb
)
2484 MonoAggregateModContainer
*amods1
= (MonoAggregateModContainer
*)ka
;
2485 MonoAggregateModContainer
*amods2
= (MonoAggregateModContainer
*)kb
;
2486 if (amods1
->count
!= amods2
->count
)
2488 for (int i
= 0; i
< amods1
->count
; ++i
) {
2489 if (amods1
->modifiers
[i
].required
!= amods2
->modifiers
[i
].required
)
2491 if (!mono_metadata_type_equal_full (amods1
->modifiers
[i
].type
, amods2
->modifiers
[i
].type
, TRUE
))
2498 aggregate_modifiers_hash (gconstpointer a
)
2500 const MonoAggregateModContainer
*amods
= (const MonoAggregateModContainer
*)a
;
2502 for (int i
= 0; i
< amods
->count
; ++i
)
2504 // hash details borrowed from mono_metadata_generic_inst_hash
2506 hash
^= (amods
->modifiers
[i
].required
<< 8);
2507 hash
+= mono_metadata_type_hash (amods
->modifiers
[i
].type
);
2513 static gboolean
type_in_image (MonoType
*type
, MonoImage
*image
);
2514 static gboolean
aggregate_modifiers_in_image (MonoAggregateModContainer
*amods
, MonoImage
*image
);
2517 signature_in_image (MonoMethodSignature
*sig
, MonoImage
*image
)
2519 gpointer iter
= NULL
;
2522 while ((p
= mono_signature_get_params_internal (sig
, &iter
)) != NULL
)
2523 if (type_in_image (p
, image
))
2526 return type_in_image (mono_signature_get_return_type_internal (sig
), image
);
2530 ginst_in_image (MonoGenericInst
*ginst
, MonoImage
*image
)
2534 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2535 if (type_in_image (ginst
->type_argv
[i
], image
))
2543 gclass_in_image (MonoGenericClass
*gclass
, MonoImage
*image
)
2545 return m_class_get_image (gclass
->container_class
) == image
||
2546 ginst_in_image (gclass
->context
.class_inst
, image
);
2550 type_in_image (MonoType
*type
, MonoImage
*image
)
2553 if (type
->has_cmods
&& mono_type_is_aggregate_mods (type
))
2554 if (aggregate_modifiers_in_image (mono_type_get_amods (type
), image
))
2557 switch (type
->type
) {
2558 case MONO_TYPE_GENERICINST
:
2559 return gclass_in_image (type
->data
.generic_class
, image
);
2561 type
= type
->data
.type
;
2563 case MONO_TYPE_SZARRAY
:
2564 type
= m_class_get_byval_arg (type
->data
.klass
);
2566 case MONO_TYPE_ARRAY
:
2567 type
= m_class_get_byval_arg (type
->data
.array
->eklass
);
2569 case MONO_TYPE_FNPTR
:
2570 return signature_in_image (type
->data
.method
, image
);
2572 case MONO_TYPE_MVAR
:
2573 return image
== mono_get_image_for_generic_param (type
->data
.generic_param
);
2575 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type_internal () */
2576 return image
== m_class_get_image (mono_class_from_mono_type_internal (type
));
2581 mono_type_in_image (MonoType
*type
, MonoImage
*image
)
2583 return type_in_image (type
, image
);
2587 aggregate_modifiers_in_image (MonoAggregateModContainer
*amods
, MonoImage
*image
)
2589 for (int i
= 0; i
< amods
->count
; i
++)
2590 if (type_in_image (amods
->modifiers
[i
].type
, image
))
2596 image_sets_lock (void)
2598 mono_os_mutex_lock (&image_sets_mutex
);
2602 image_sets_unlock (void)
2604 mono_os_mutex_unlock (&image_sets_mutex
);
2608 #define HASH_TABLE_SIZE 1103
2609 static MonoImageSet
*img_set_cache
[HASH_TABLE_SIZE
];
2612 mix_hash (uintptr_t source
)
2614 unsigned int hash
= source
;
2617 hash
= (((hash
* 215497) >> 16) ^ ((hash
* 1823231) + hash
));
2619 // Mix in highest bits on 64-bit systems only
2620 if (sizeof (source
) > 4)
2621 hash
= hash
^ ((source
>> 31) >> 1);
2627 hash_images (MonoImage
**images
, int nimages
)
2631 for (i
= 0; i
< nimages
; ++i
)
2632 res
+= mix_hash ((size_t)images
[i
]);
2638 compare_img_set (MonoImageSet
*set
, MonoImage
**images
, int nimages
)
2642 if (set
->nimages
!= nimages
)
2645 for (j
= 0; j
< nimages
; ++j
) {
2646 for (k
= 0; k
< nimages
; ++k
)
2647 if (set
->images
[k
] == images
[j
])
2648 break; // Break on match
2650 // If we iterated all the way through set->images, images[j] was *not* found.
2652 break; // Break on "image not found"
2655 // If we iterated all the way through images without breaking, all items in images were found in set->images
2656 return j
== nimages
;
2660 static MonoImageSet
*
2661 img_set_cache_get (MonoImage
**images
, int nimages
)
2663 guint32 hash_code
= hash_images (images
, nimages
);
2664 int index
= hash_code
% HASH_TABLE_SIZE
;
2665 MonoImageSet
*img
= img_set_cache
[index
];
2666 if (!img
|| !compare_img_set (img
, images
, nimages
)) {
2667 UnlockedIncrement (&img_set_cache_miss
);
2670 UnlockedIncrement (&img_set_cache_hit
);
2675 img_set_cache_add (MonoImageSet
*set
)
2677 guint32 hash_code
= hash_images (set
->images
, set
->nimages
);
2678 int index
= hash_code
% HASH_TABLE_SIZE
;
2679 img_set_cache
[index
] = set
;
2683 img_set_cache_remove (MonoImageSet
*is
)
2685 guint32 hash_code
= hash_images (is
->images
, is
->nimages
);
2686 int index
= hash_code
% HASH_TABLE_SIZE
;
2687 if (img_set_cache
[index
] == is
)
2688 img_set_cache
[index
] = NULL
;
2693 * Return a MonoImageSet representing the set of images in IMAGES.
2695 static MonoImageSet
*
2696 get_image_set (MonoImage
**images
, int nimages
)
2702 /* Common case: Image set contains corlib only. If we've seen that case before, we cached the set. */
2703 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
&& mscorlib_image_set
)
2704 return mscorlib_image_set
;
2706 /* Happens with empty generic instances */
2707 // 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.
2709 return mscorlib_image_set
;
2711 set
= img_set_cache_get (images
, nimages
);
2718 image_sets
= g_ptr_array_new ();
2720 // Before we go on, we should check to see whether a MonoImageSet with these images already exists.
2721 // We can search the referred-by imagesets of any one of our images to do this. Arbitrarily pick one here:
2722 if (images
[0] == mono_defaults
.corlib
&& nimages
> 1)
2723 l
= images
[1]->image_sets
; // Prefer not to search the imagesets of corlib-- that will be a long list.
2725 l
= images
[0]->image_sets
;
2728 while (l
) // Iterate over selected list, looking for an imageset with members equal to our target one
2730 set
= (MonoImageSet
*)l
->data
;
2732 if (set
->nimages
== nimages
) { // Member count differs, this can't be it
2733 // Compare all members to all members-- order might be different
2734 for (j
= 0; j
< nimages
; ++j
) {
2735 for (k
= 0; k
< nimages
; ++k
)
2736 if (set
->images
[k
] == images
[j
])
2737 break; // Break on match
2739 // If we iterated all the way through set->images, images[j] was *not* found.
2741 break; // Break on "image not found"
2744 // If we iterated all the way through images without breaking, all items in images were found in set->images
2746 // Break on "found a set with equal members".
2747 // This happens in case of a hash collision with a previously cached set.
2755 // If we iterated all the way through l without breaking, the imageset does not already exist and we should create it
2757 set
= g_new0 (MonoImageSet
, 1);
2758 set
->nimages
= nimages
;
2759 set
->images
= g_new0 (MonoImage
*, nimages
);
2760 mono_os_mutex_init_recursive (&set
->lock
);
2761 for (i
= 0; i
< nimages
; ++i
)
2762 set
->images
[i
] = images
[i
];
2763 set
->gclass_cache
= mono_conc_hashtable_new_full (mono_generic_class_hash
, mono_generic_class_equal
, NULL
, (GDestroyNotify
)free_generic_class
);
2764 set
->ginst_cache
= g_hash_table_new_full (mono_metadata_generic_inst_hash
, mono_metadata_generic_inst_equal
, NULL
, (GDestroyNotify
)free_generic_inst
);
2765 set
->gmethod_cache
= g_hash_table_new_full (inflated_method_hash
, inflated_method_equal
, NULL
, (GDestroyNotify
)free_inflated_method
);
2766 set
->gsignature_cache
= g_hash_table_new_full (inflated_signature_hash
, inflated_signature_equal
, NULL
, (GDestroyNotify
)free_inflated_signature
);
2768 set
->szarray_cache
= g_hash_table_new_full (mono_aligned_addr_hash
, NULL
, NULL
, NULL
);
2769 set
->array_cache
= g_hash_table_new_full (mono_aligned_addr_hash
, NULL
, NULL
, NULL
);
2771 set
->aggregate_modifiers_cache
= g_hash_table_new_full (aggregate_modifiers_hash
, aggregate_modifiers_equal
, NULL
, (GDestroyNotify
)free_aggregate_modifiers
);
2773 for (i
= 0; i
< nimages
; ++i
)
2774 set
->images
[i
]->image_sets
= g_slist_prepend (set
->images
[i
]->image_sets
, set
);
2776 g_ptr_array_add (image_sets
, set
);
2777 UnlockedIncrement (&img_set_count
); /* locked by image_sets_lock () */
2780 /* Cache the set. If there was a cache collision, the previously cached value will be replaced. */
2781 img_set_cache_add (set
);
2783 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
) {
2784 mono_memory_barrier ();
2785 mscorlib_image_set
= set
;
2788 image_sets_unlock ();
2794 delete_image_set (MonoImageSet
*set
)
2798 mono_conc_hashtable_destroy (set
->gclass_cache
);
2799 g_hash_table_destroy (set
->ginst_cache
);
2800 g_hash_table_destroy (set
->gmethod_cache
);
2801 g_hash_table_destroy (set
->gsignature_cache
);
2803 g_hash_table_destroy (set
->szarray_cache
);
2804 g_hash_table_destroy (set
->array_cache
);
2806 g_hash_table_destroy (set
->ptr_cache
);
2808 g_hash_table_destroy (set
->aggregate_modifiers_cache
);
2810 for (i
= 0; i
< set
->gshared_types_len
; ++i
) {
2811 if (set
->gshared_types
[i
])
2812 g_hash_table_destroy (set
->gshared_types
[i
]);
2814 g_free (set
->gshared_types
);
2816 mono_wrapper_caches_free (&set
->wrapper_caches
);
2820 for (i
= 0; i
< set
->nimages
; ++i
)
2821 set
->images
[i
]->image_sets
= g_slist_remove (set
->images
[i
]->image_sets
, set
);
2823 g_ptr_array_remove (image_sets
, set
);
2825 image_sets_unlock ();
2827 img_set_cache_remove (set
);
2830 mono_mempool_destroy (set
->mempool
);
2831 g_free (set
->images
);
2832 mono_os_mutex_destroy (&set
->lock
);
2837 mono_image_set_lock (MonoImageSet
*set
)
2839 mono_os_mutex_lock (&set
->lock
);
2843 mono_image_set_unlock (MonoImageSet
*set
)
2845 mono_os_mutex_unlock (&set
->lock
);
2849 mono_image_set_alloc (MonoImageSet
*set
, guint size
)
2853 mono_image_set_lock (set
);
2855 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2856 res
= mono_mempool_alloc (set
->mempool
, size
);
2857 mono_image_set_unlock (set
);
2863 mono_image_set_alloc0 (MonoImageSet
*set
, guint size
)
2867 mono_image_set_lock (set
);
2869 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2870 res
= mono_mempool_alloc0 (set
->mempool
, size
);
2871 mono_image_set_unlock (set
);
2877 mono_image_set_strdup (MonoImageSet
*set
, const char *s
)
2881 mono_image_set_lock (set
);
2883 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2884 res
= mono_mempool_strdup (set
->mempool
, s
);
2885 mono_image_set_unlock (set
);
2890 // Get a descriptive string for a MonoImageSet
2891 // Callers are obligated to free buffer with g_free after use
2893 mono_image_set_description (MonoImageSet
*set
)
2895 GString
*result
= g_string_new (NULL
);
2897 g_string_append (result
, "[");
2898 for (img
= 0; img
< set
->nimages
; img
++)
2901 g_string_append (result
, ", ");
2902 g_string_append (result
, set
->images
[img
]->name
);
2904 g_string_append (result
, "]");
2905 return g_string_free (result
, FALSE
);
2909 * Structure used by the collect_..._images functions to store the image list.
2912 MonoImage
*image_buf
[64];
2914 int nimages
, images_len
;
2918 collect_data_init (CollectData
*data
)
2920 data
->images
= data
->image_buf
;
2921 data
->images_len
= 64;
2926 collect_data_free (CollectData
*data
)
2928 if (data
->images
!= data
->image_buf
)
2929 g_free (data
->images
);
2933 enlarge_data (CollectData
*data
)
2935 int new_len
= data
->images_len
< 16 ? 16 : data
->images_len
* 2;
2936 MonoImage
**d
= g_new (MonoImage
*, new_len
);
2939 g_assert_not_reached ();
2940 memcpy (d
, data
->images
, data
->images_len
);
2941 if (data
->images
!= data
->image_buf
)
2942 g_free (data
->images
);
2944 data
->images_len
= new_len
;
2948 add_image (MonoImage
*image
, CollectData
*data
)
2952 /* The arrays are small, so use a linear search instead of a hash table */
2953 for (i
= 0; i
< data
->nimages
; ++i
)
2954 if (data
->images
[i
] == image
)
2957 if (data
->nimages
== data
->images_len
)
2958 enlarge_data (data
);
2960 data
->images
[data
->nimages
++] = image
;
2964 collect_type_images (MonoType
*type
, CollectData
*data
);
2967 collect_ginst_images (MonoGenericInst
*ginst
, CollectData
*data
)
2971 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2972 collect_type_images (ginst
->type_argv
[i
], data
);
2977 collect_gclass_images (MonoGenericClass
*gclass
, CollectData
*data
)
2979 add_image (m_class_get_image (gclass
->container_class
), data
);
2980 if (gclass
->context
.class_inst
)
2981 collect_ginst_images (gclass
->context
.class_inst
, data
);
2985 collect_signature_images (MonoMethodSignature
*sig
, CollectData
*data
)
2987 gpointer iter
= NULL
;
2990 collect_type_images (mono_signature_get_return_type_internal (sig
), data
);
2991 while ((p
= mono_signature_get_params_internal (sig
, &iter
)) != NULL
)
2992 collect_type_images (p
, data
);
2996 collect_inflated_signature_images (MonoInflatedMethodSignature
*sig
, CollectData
*data
)
2998 collect_signature_images (sig
->sig
, data
);
2999 if (sig
->context
.class_inst
)
3000 collect_ginst_images (sig
->context
.class_inst
, data
);
3001 if (sig
->context
.method_inst
)
3002 collect_ginst_images (sig
->context
.method_inst
, data
);
3006 collect_method_images (MonoMethodInflated
*method
, CollectData
*data
)
3008 MonoMethod
*m
= method
->declaring
;
3010 add_image (m_class_get_image (method
->declaring
->klass
), data
);
3011 if (method
->context
.class_inst
)
3012 collect_ginst_images (method
->context
.class_inst
, data
);
3013 if (method
->context
.method_inst
)
3014 collect_ginst_images (method
->context
.method_inst
, data
);
3016 * Dynamic assemblies have no references, so the images they depend on can be unloaded before them.
3018 if (image_is_dynamic (m_class_get_image (m
->klass
)))
3019 collect_signature_images (mono_method_signature_internal (m
), data
);
3023 collect_aggregate_modifiers_images (MonoAggregateModContainer
*amods
, CollectData
*data
)
3025 for (int i
= 0; i
< amods
->count
; ++i
)
3026 collect_type_images (amods
->modifiers
[i
].type
, data
);
3030 collect_type_images (MonoType
*type
, CollectData
*data
)
3033 if (G_UNLIKELY (type
->has_cmods
&& mono_type_is_aggregate_mods (type
))) {
3034 collect_aggregate_modifiers_images (mono_type_get_amods (type
), data
);
3037 switch (type
->type
) {
3038 case MONO_TYPE_GENERICINST
:
3039 collect_gclass_images (type
->data
.generic_class
, data
);
3042 type
= type
->data
.type
;
3044 case MONO_TYPE_SZARRAY
:
3045 type
= m_class_get_byval_arg (type
->data
.klass
);
3047 case MONO_TYPE_ARRAY
:
3048 type
= m_class_get_byval_arg (type
->data
.array
->eklass
);
3050 case MONO_TYPE_FNPTR
:
3051 //return signature_in_image (type->data.method, image);
3052 g_assert_not_reached ();
3054 case MONO_TYPE_MVAR
:
3056 MonoImage
*image
= mono_get_image_for_generic_param (type
->data
.generic_param
);
3057 add_image (image
, data
);
3060 case MONO_TYPE_CLASS
:
3061 case MONO_TYPE_VALUETYPE
:
3062 add_image (m_class_get_image (mono_class_from_mono_type_internal (type
)), data
);
3065 add_image (mono_defaults
.corlib
, data
);
3072 } CleanForImageUserData
;
3075 steal_gclass_in_image (gpointer key
, gpointer value
, gpointer data
)
3077 MonoGenericClass
*gclass
= (MonoGenericClass
*)key
;
3078 CleanForImageUserData
*user_data
= (CleanForImageUserData
*)data
;
3080 g_assert (gclass_in_image (gclass
, user_data
->image
));
3082 user_data
->list
= g_slist_prepend (user_data
->list
, gclass
);
3087 steal_ginst_in_image (gpointer key
, gpointer value
, gpointer data
)
3089 MonoGenericInst
*ginst
= (MonoGenericInst
*)key
;
3090 CleanForImageUserData
*user_data
= (CleanForImageUserData
*)data
;
3092 // This doesn't work during corlib compilation
3093 //g_assert (ginst_in_image (ginst, user_data->image));
3095 user_data
->list
= g_slist_prepend (user_data
->list
, ginst
);
3100 steal_aggregate_modifiers_in_image (gpointer key
, gpointer value
, gpointer data
)
3102 MonoAggregateModContainer
*amods
= (MonoAggregateModContainer
*)key
;
3103 CleanForImageUserData
*user_data
= (CleanForImageUserData
*)data
;
3105 g_assert (aggregate_modifiers_in_image (amods
, user_data
->image
));
3107 user_data
->list
= g_slist_prepend (user_data
->list
, amods
);
3112 inflated_method_in_image (gpointer key
, gpointer value
, gpointer data
)
3114 MonoImage
*image
= (MonoImage
*)data
;
3115 MonoMethodInflated
*method
= (MonoMethodInflated
*)key
;
3118 // https://bugzilla.novell.com/show_bug.cgi?id=458168
3119 g_assert (m_class_get_image (method
->declaring
->klass
) == image
||
3120 (method
->context
.class_inst
&& ginst_in_image (method
->context
.class_inst
, image
)) ||
3121 (method
->context
.method_inst
&& ginst_in_image (method
->context
.method_inst
, image
)) || (((MonoMethod
*)method
)->signature
&& signature_in_image (mono_method_signature_internal ((MonoMethod
*)method
), image
)));
3127 inflated_signature_in_image (gpointer key
, gpointer value
, gpointer data
)
3129 MonoImage
*image
= (MonoImage
*)data
;
3130 MonoInflatedMethodSignature
*sig
= (MonoInflatedMethodSignature
*)key
;
3132 return signature_in_image (sig
->sig
, image
) ||
3133 (sig
->context
.class_inst
&& ginst_in_image (sig
->context
.class_inst
, image
)) ||
3134 (sig
->context
.method_inst
&& ginst_in_image (sig
->context
.method_inst
, image
));
3138 class_in_image (gpointer key
, gpointer value
, gpointer data
)
3140 MonoImage
*image
= (MonoImage
*)data
;
3141 MonoClass
*klass
= (MonoClass
*)key
;
3143 g_assert (type_in_image (m_class_get_byval_arg (klass
), image
));
3149 check_gmethod (gpointer key
, gpointer value
, gpointer data
)
3151 MonoMethodInflated
*method
= (MonoMethodInflated
*)key
;
3152 MonoImage
*image
= (MonoImage
*)data
;
3154 if (method
->context
.class_inst
)
3155 g_assert (!ginst_in_image (method
->context
.class_inst
, image
));
3156 if (method
->context
.method_inst
)
3157 g_assert (!ginst_in_image (method
->context
.method_inst
, image
));
3158 if (((MonoMethod
*)method
)->signature
)
3159 g_assert (!signature_in_image (mono_method_signature_internal ((MonoMethod
*)method
), image
));
3165 * Run a consistency check on the image set data structures.
3167 static G_GNUC_UNUSED
void
3168 check_image_sets (MonoImage
*image
)
3171 GSList
*l
= image
->image_sets
;
3176 for (i
= 0; i
< image_sets
->len
; ++i
) {
3177 MonoImageSet
*set
= (MonoImageSet
*)g_ptr_array_index (image_sets
, i
);
3179 if (!g_slist_find (l
, set
)) {
3180 g_hash_table_foreach (set
->gmethod_cache
, check_gmethod
, image
);
3186 mono_metadata_clean_for_image (MonoImage
*image
)
3188 CleanForImageUserData ginst_data
, gclass_data
, amods_data
;
3189 GSList
*l
, *set_list
;
3191 //check_image_sets (image);
3194 * The data structures could reference each other so we delete them in two phases.
3195 * This is required because of the hashing functions in gclass/ginst_cache.
3197 ginst_data
.image
= gclass_data
.image
= image
;
3198 ginst_data
.list
= gclass_data
.list
= NULL
;
3199 amods_data
.image
= image
;
3200 amods_data
.list
= NULL
;
3202 /* Collect the items to delete */
3203 /* delete_image_set () modifies the lists so make a copy */
3204 for (l
= image
->image_sets
; l
; l
= l
->next
) {
3205 MonoImageSet
*set
= (MonoImageSet
*)l
->data
;
3207 mono_image_set_lock (set
);
3208 mono_conc_hashtable_foreach_steal (set
->gclass_cache
, steal_gclass_in_image
, &gclass_data
);
3209 g_hash_table_foreach_steal (set
->ginst_cache
, steal_ginst_in_image
, &ginst_data
);
3210 g_hash_table_foreach_remove (set
->gmethod_cache
, inflated_method_in_image
, image
);
3211 g_hash_table_foreach_remove (set
->gsignature_cache
, inflated_signature_in_image
, image
);
3213 g_hash_table_foreach_steal (set
->szarray_cache
, class_in_image
, image
);
3214 g_hash_table_foreach_steal (set
->array_cache
, class_in_image
, image
);
3216 g_hash_table_foreach_steal (set
->ptr_cache
, class_in_image
, image
);
3218 g_hash_table_foreach_steal (set
->aggregate_modifiers_cache
, steal_aggregate_modifiers_in_image
, &amods_data
);
3220 mono_image_set_unlock (set
);
3223 /* Delete the removed items */
3224 for (l
= ginst_data
.list
; l
; l
= l
->next
)
3225 free_generic_inst ((MonoGenericInst
*)l
->data
);
3226 for (l
= gclass_data
.list
; l
; l
= l
->next
)
3227 free_generic_class ((MonoGenericClass
*)l
->data
);
3228 for (l
= amods_data
.list
; l
; l
= l
->next
)
3229 free_aggregate_modifiers ((MonoAggregateModContainer
*)l
->data
);
3230 g_slist_free (ginst_data
.list
);
3231 g_slist_free (gclass_data
.list
);
3232 /* delete_image_set () modifies the lists so make a copy */
3233 set_list
= g_slist_copy (image
->image_sets
);
3234 for (l
= set_list
; l
; l
= l
->next
) {
3235 MonoImageSet
*set
= (MonoImageSet
*)l
->data
;
3237 delete_image_set (set
);
3239 g_slist_free (set_list
);
3243 free_inflated_method (MonoMethodInflated
*imethod
)
3245 MonoMethod
*method
= (MonoMethod
*)imethod
;
3247 if (method
->signature
)
3248 mono_metadata_free_inflated_signature (method
->signature
);
3250 if (method
->wrapper_type
)
3251 g_free (((MonoMethodWrapper
*)method
)->method_data
);
3257 free_generic_inst (MonoGenericInst
*ginst
)
3261 /* The ginst itself is allocated from the image set mempool */
3262 for (i
= 0; i
< ginst
->type_argc
; ++i
)
3263 mono_metadata_free_type (ginst
->type_argv
[i
]);
3267 free_generic_class (MonoGenericClass
*gclass
)
3269 /* The gclass itself is allocated from the image set mempool */
3270 if (gclass
->cached_class
&& m_class_get_interface_id (gclass
->cached_class
))
3271 mono_unload_interface_id (gclass
->cached_class
);
3275 free_inflated_signature (MonoInflatedMethodSignature
*sig
)
3277 mono_metadata_free_inflated_signature (sig
->sig
);
3282 free_aggregate_modifiers (MonoAggregateModContainer
*amods
)
3284 for (int i
= 0; i
< amods
->count
; i
++)
3285 mono_metadata_free_type (amods
->modifiers
[i
].type
);
3286 /* the container itself is allocated in the image set mempool */
3290 * mono_metadata_get_inflated_signature:
3292 * Given an inflated signature and a generic context, return a canonical copy of the
3293 * signature. The returned signature might be equal to SIG or it might be a cached copy.
3295 MonoMethodSignature
*
3296 mono_metadata_get_inflated_signature (MonoMethodSignature
*sig
, MonoGenericContext
*context
)
3298 MonoInflatedMethodSignature helper
;
3299 MonoInflatedMethodSignature
*res
;
3304 helper
.context
.class_inst
= context
->class_inst
;
3305 helper
.context
.method_inst
= context
->method_inst
;
3307 collect_data_init (&data
);
3309 collect_inflated_signature_images (&helper
, &data
);
3311 set
= get_image_set (data
.images
, data
.nimages
);
3313 collect_data_free (&data
);
3315 mono_image_set_lock (set
);
3317 res
= (MonoInflatedMethodSignature
*)g_hash_table_lookup (set
->gsignature_cache
, &helper
);
3319 res
= g_new0 (MonoInflatedMethodSignature
, 1);
3321 res
->context
.class_inst
= context
->class_inst
;
3322 res
->context
.method_inst
= context
->method_inst
;
3323 g_hash_table_insert (set
->gsignature_cache
, res
, res
);
3326 mono_image_set_unlock (set
);
3332 mono_metadata_get_image_set_for_type (MonoType
*type
)
3335 CollectData image_set_data
;
3337 collect_data_init (&image_set_data
);
3338 collect_type_images (type
, &image_set_data
);
3339 set
= get_image_set (image_set_data
.images
, image_set_data
.nimages
);
3340 collect_data_free (&image_set_data
);
3346 mono_metadata_get_image_set_for_class (MonoClass
*klass
)
3348 return mono_metadata_get_image_set_for_type (m_class_get_byval_arg (klass
));
3352 mono_metadata_get_image_set_for_method (MonoMethodInflated
*method
)
3355 CollectData image_set_data
;
3357 collect_data_init (&image_set_data
);
3358 collect_method_images (method
, &image_set_data
);
3359 set
= get_image_set (image_set_data
.images
, image_set_data
.nimages
);
3360 collect_data_free (&image_set_data
);
3366 mono_metadata_get_image_set_for_aggregate_modifiers (MonoAggregateModContainer
*amods
)
3369 CollectData image_set_data
;
3370 collect_data_init (&image_set_data
);
3371 collect_aggregate_modifiers_images (amods
, &image_set_data
);
3372 set
= get_image_set (image_set_data
.images
, image_set_data
.nimages
);
3373 collect_data_free (&image_set_data
);
3379 mono_metadata_merge_image_sets (MonoImageSet
*set1
, MonoImageSet
*set2
)
3381 MonoImage
**images
= g_newa (MonoImage
*, set1
->nimages
+ set2
->nimages
);
3383 /* Add images from set1 */
3384 memcpy (images
, set1
->images
, sizeof (MonoImage
*) * set1
->nimages
);
3386 int nimages
= set1
->nimages
;
3388 /* Add images from set2 */
3389 for (int i
= 0; i
< set2
->nimages
; ++i
) {
3391 for (j
= 0; j
< set1
->nimages
; ++j
) {
3392 if (set2
->images
[i
] == set1
->images
[j
])
3395 if (j
== set1
->nimages
)
3396 images
[nimages
++] = set2
->images
[i
];
3398 return get_image_set (images
, nimages
);
3402 type_is_gtd (MonoType
*type
)
3404 switch (type
->type
) {
3405 case MONO_TYPE_CLASS
:
3406 case MONO_TYPE_VALUETYPE
:
3407 return mono_class_is_gtd (type
->data
.klass
);
3414 * mono_metadata_get_generic_inst:
3416 * Given a list of types, return a MonoGenericInst that represents that list.
3417 * The returned MonoGenericInst has its own copy of the list of types. The list
3418 * passed in the argument can be freed, modified or disposed of.
3422 mono_metadata_get_generic_inst (int type_argc
, MonoType
**type_argv
)
3424 MonoGenericInst
*ginst
;
3427 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
3429 for (i
= 0; i
< type_argc
; ++i
)
3430 if (mono_class_is_open_constructed_type (type_argv
[i
]))
3432 is_open
= (i
< type_argc
);
3434 ginst
= (MonoGenericInst
*)g_alloca (size
);
3435 memset (ginst
, 0, MONO_SIZEOF_GENERIC_INST
);
3436 ginst
->is_open
= is_open
;
3437 ginst
->type_argc
= type_argc
;
3438 memcpy (ginst
->type_argv
, type_argv
, type_argc
* sizeof (MonoType
*));
3440 for (i
= 0; i
< type_argc
; ++i
) {
3441 MonoType
*t
= ginst
->type_argv
[i
];
3442 if (type_is_gtd (t
)) {
3443 ginst
->type_argv
[i
] = mono_class_gtd_get_canonical_inst (t
->data
.klass
);
3447 return mono_metadata_get_canonical_generic_inst (ginst
);
3451 * mono_metadata_get_canonical_generic_inst:
3452 * \param candidate an arbitrary generic instantiation
3454 * \returns the canonical generic instantiation that represents the given
3455 * candidate by identifying the image set for the candidate instantiation and
3456 * finding the instance in the image set or adding a copy of the given instance
3459 * The returned MonoGenericInst has its own copy of the list of types. The list
3460 * passed in the argument can be freed, modified or disposed of.
3464 mono_metadata_get_canonical_generic_inst (MonoGenericInst
*candidate
)
3467 int type_argc
= candidate
->type_argc
;
3468 gboolean is_open
= candidate
->is_open
;
3471 collect_data_init (&data
);
3473 collect_ginst_images (candidate
, &data
);
3475 set
= get_image_set (data
.images
, data
.nimages
);
3477 collect_data_free (&data
);
3479 mono_image_set_lock (set
);
3481 MonoGenericInst
*ginst
= (MonoGenericInst
*)g_hash_table_lookup (set
->ginst_cache
, candidate
);
3483 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
3484 ginst
= (MonoGenericInst
*)mono_image_set_alloc0 (set
, size
);
3485 #ifndef MONO_SMALL_CONFIG
3486 ginst
->id
= mono_atomic_inc_i32 (&next_generic_inst_id
);
3488 ginst
->is_open
= is_open
;
3489 ginst
->type_argc
= type_argc
;
3491 for (int i
= 0; i
< type_argc
; ++i
)
3492 ginst
->type_argv
[i
] = mono_metadata_type_dup (NULL
, candidate
->type_argv
[i
]);
3494 g_hash_table_insert (set
->ginst_cache
, ginst
, ginst
);
3497 mono_image_set_unlock (set
);
3501 MonoAggregateModContainer
*
3502 mono_metadata_get_canonical_aggregate_modifiers (MonoAggregateModContainer
*candidate
)
3504 g_assert (candidate
->count
> 0);
3505 MonoImageSet
*set
= mono_metadata_get_image_set_for_aggregate_modifiers (candidate
);
3507 mono_image_set_lock (set
);
3509 MonoAggregateModContainer
*amods
= (MonoAggregateModContainer
*)g_hash_table_lookup (set
->aggregate_modifiers_cache
, candidate
);
3511 size_t size
= mono_sizeof_aggregate_modifiers (candidate
->count
);
3512 amods
= (MonoAggregateModContainer
*)mono_image_set_alloc0 (set
, size
);
3513 amods
->count
= candidate
->count
;
3514 for (int i
= 0; i
< candidate
->count
; ++i
) {
3515 amods
->modifiers
[i
].required
= candidate
->modifiers
[i
].required
;
3516 amods
->modifiers
[i
].type
= mono_metadata_type_dup (NULL
, candidate
->modifiers
[i
].type
);
3519 g_hash_table_insert (set
->aggregate_modifiers_cache
, amods
, amods
);
3521 mono_image_set_unlock (set
);
3526 mono_metadata_is_type_builder_generic_type_definition (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
3528 MonoGenericContainer
*container
= mono_class_get_generic_container (container_class
);
3530 if (!is_dynamic
|| m_class_was_typebuilder (container_class
) || container
->type_argc
!= inst
->type_argc
)
3532 return inst
== container
->context
.class_inst
;
3536 * mono_metadata_lookup_generic_class:
3538 * Returns a MonoGenericClass with the given properties.
3542 mono_metadata_lookup_generic_class (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
3544 MonoGenericClass
*gclass
;
3545 MonoGenericClass helper
;
3546 gboolean is_tb_open
= mono_metadata_is_type_builder_generic_type_definition (container_class
, inst
, is_dynamic
);
3550 g_assert (mono_class_get_generic_container (container_class
)->type_argc
== inst
->type_argc
);
3552 memset (&helper
, 0, sizeof(helper
)); // act like g_new0
3553 helper
.container_class
= container_class
;
3554 helper
.context
.class_inst
= inst
;
3555 helper
.is_dynamic
= is_dynamic
; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
3556 helper
.is_tb_open
= is_tb_open
;
3558 collect_data_init (&data
);
3560 collect_gclass_images (&helper
, &data
);
3562 set
= get_image_set (data
.images
, data
.nimages
);
3564 collect_data_free (&data
);
3566 gclass
= (MonoGenericClass
*)mono_conc_hashtable_lookup (set
->gclass_cache
, &helper
);
3568 /* A tripwire just to keep us honest */
3569 g_assert (!helper
.cached_class
);
3574 gclass
= mono_image_set_new0 (set
, MonoGenericClass
, 1);
3576 gclass
->is_dynamic
= 1;
3578 gclass
->is_tb_open
= is_tb_open
;
3579 gclass
->container_class
= container_class
;
3580 gclass
->context
.class_inst
= inst
;
3581 gclass
->context
.method_inst
= NULL
;
3582 gclass
->owner
= set
;
3583 if (inst
== mono_class_get_generic_container (container_class
)->context
.class_inst
&& !is_tb_open
)
3584 gclass
->cached_class
= container_class
;
3586 mono_image_set_lock (set
);
3588 MonoGenericClass
*gclass2
= (MonoGenericClass
*)mono_conc_hashtable_insert (set
->gclass_cache
, gclass
, gclass
);
3592 // g_hash_table_insert (set->gclass_cache, gclass, gclass);
3594 mono_image_set_unlock (set
);
3600 * mono_metadata_inflate_generic_inst:
3602 * Instantiate the generic instance @ginst with the context @context.
3603 * Check @error for success.
3607 mono_metadata_inflate_generic_inst (MonoGenericInst
*ginst
, MonoGenericContext
*context
, MonoError
*error
)
3609 MonoType
**type_argv
;
3610 MonoGenericInst
*nginst
= NULL
;
3615 if (!ginst
->is_open
)
3618 type_argv
= g_new0 (MonoType
*, ginst
->type_argc
);
3620 for (i
= 0; i
< ginst
->type_argc
; i
++) {
3621 type_argv
[i
] = mono_class_inflate_generic_type_checked (ginst
->type_argv
[i
], context
, error
);
3627 nginst
= mono_metadata_get_generic_inst (ginst
->type_argc
, type_argv
);
3630 for (i
= 0; i
< count
; i
++)
3631 mono_metadata_free_type (type_argv
[i
]);
3638 mono_metadata_parse_generic_inst (MonoImage
*m
, MonoGenericContainer
*container
,
3639 int count
, const char *ptr
, const char **rptr
, MonoError
*error
)
3641 MonoType
**type_argv
;
3642 MonoGenericInst
*ginst
= NULL
;
3643 int i
, parse_count
= 0;
3646 type_argv
= g_new0 (MonoType
*, count
);
3648 for (i
= 0; i
< count
; i
++) {
3649 /* this can be a transient type, mono_metadata_get_generic_inst will allocate
3650 * a canonical one, if needed.
3652 MonoType
*t
= mono_metadata_parse_type_checked (m
, container
, 0, TRUE
, ptr
, &ptr
, error
);
3662 g_assert (parse_count
== count
);
3663 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
3666 for (i
= 0; i
< parse_count
; i
++)
3667 mono_metadata_free_type (type_argv
[i
]);
3674 do_mono_metadata_parse_generic_class (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
3675 const char *ptr
, const char **rptr
, MonoError
*error
)
3677 MonoGenericInst
*inst
;
3684 // XXX how about transient?
3685 gtype
= mono_metadata_parse_type_checked (m
, NULL
, 0, FALSE
, ptr
, &ptr
, error
);
3689 gklass
= mono_class_from_mono_type_internal (gtype
);
3690 if (!mono_class_is_gtd (gklass
)) {
3691 mono_error_set_bad_image (error
, m
, "Generic instance with non-generic definition");
3695 count
= mono_metadata_decode_value (ptr
, &ptr
);
3696 inst
= mono_metadata_parse_generic_inst (m
, container
, count
, ptr
, &ptr
, error
);
3703 type
->data
.generic_class
= mono_metadata_lookup_generic_class (gklass
, inst
, FALSE
);
3709 * @gc: The generic container to normalize
3710 * @type: The kind of generic parameters the resulting generic-container should contain
3713 static MonoGenericContainer
*
3714 select_container (MonoGenericContainer
*gc
, MonoTypeEnum type
)
3716 gboolean is_var
= (type
== MONO_TYPE_VAR
);
3720 g_assert (is_var
|| type
== MONO_TYPE_MVAR
);
3723 if (gc
->is_method
|| gc
->parent
)
3725 * The current MonoGenericContainer is a generic method -> its `parent'
3726 * points to the containing class'es container.
3734 MonoGenericContainer
*
3735 mono_get_anonymous_container_for_image (MonoImage
*image
, gboolean is_mvar
)
3737 MonoGenericContainer
**container_pointer
;
3739 container_pointer
= &image
->anonymous_generic_method_container
;
3741 container_pointer
= &image
->anonymous_generic_class_container
;
3742 MonoGenericContainer
*result
= *container_pointer
;
3744 // This container has never been created; make it now.
3747 // Note this is never deallocated anywhere-- it exists for the lifetime of the image it's allocated from
3748 result
= (MonoGenericContainer
*)mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
3749 result
->owner
.image
= image
;
3750 result
->is_anonymous
= TRUE
;
3751 result
->is_method
= is_mvar
;
3753 // If another thread already made a container, use that and leak this new one.
3754 // (Technically it would currently be safe to just assign instead of CASing.)
3755 MonoGenericContainer
*exchange
= (MonoGenericContainer
*)mono_atomic_cas_ptr ((volatile gpointer
*)container_pointer
, result
, NULL
);
3762 #define FAST_GPARAM_CACHE_SIZE 16
3764 static MonoGenericParam
*
3765 lookup_anon_gparam (MonoImage
*image
, MonoGenericContainer
*container
, gint32 param_num
, gboolean is_mvar
)
3767 if (param_num
>= 0 && param_num
< FAST_GPARAM_CACHE_SIZE
) {
3768 MonoGenericParam
*cache
= is_mvar
? image
->mvar_gparam_cache_fast
: image
->var_gparam_cache_fast
;
3771 return &cache
[param_num
];
3773 MonoGenericParam key
;
3774 memset (&key
, 0, sizeof (key
));
3775 key
.owner
= container
;
3776 key
.num
= param_num
;
3777 key
.gshared_constraint
= NULL
;
3778 MonoConcurrentHashTable
*cache
= is_mvar
? image
->mvar_gparam_cache
: image
->var_gparam_cache
;
3781 return (MonoGenericParam
*)mono_conc_hashtable_lookup (cache
, &key
);
3785 static MonoGenericParam
*
3786 publish_anon_gparam_fast (MonoImage
*image
, MonoGenericContainer
*container
, gint32 param_num
)
3788 g_assert (param_num
>= 0 && param_num
< FAST_GPARAM_CACHE_SIZE
);
3789 MonoGenericParam
**cache
= container
->is_method
? &image
->mvar_gparam_cache_fast
: &image
->var_gparam_cache_fast
;
3791 mono_image_lock (image
);
3793 *cache
= (MonoGenericParam
*)mono_image_alloc0 (image
, sizeof (MonoGenericParam
) * FAST_GPARAM_CACHE_SIZE
);
3794 for (gint32 i
= 0; i
< FAST_GPARAM_CACHE_SIZE
; ++i
) {
3795 MonoGenericParam
*param
= &(*cache
)[i
];
3796 param
->owner
= container
;
3800 mono_image_unlock (image
);
3802 return &(*cache
)[param_num
];
3806 * publish_anon_gparam_slow:
3808 * Publish \p gparam anonymous generic parameter to the anon gparam cache for \p image.
3810 * LOCKING: takes the image lock.
3812 static MonoGenericParam
*
3813 publish_anon_gparam_slow (MonoImage
*image
, MonoGenericParam
*gparam
)
3815 MonoConcurrentHashTable
**cache
= gparam
->owner
->is_method
? &image
->mvar_gparam_cache
: &image
->var_gparam_cache
;
3817 mono_image_lock (image
);
3819 MonoConcurrentHashTable
*ht
= mono_conc_hashtable_new ((GHashFunc
)mono_metadata_generic_param_hash
,
3820 (GEqualFunc
) mono_metadata_generic_param_equal
);
3821 mono_atomic_store_release (cache
, ht
);
3823 mono_image_unlock (image
);
3825 MonoGenericParam
*other
= (MonoGenericParam
*)mono_conc_hashtable_insert (*cache
, gparam
, gparam
);
3826 // If another thread published first return their param, otherwise return ours.
3827 return other
? other
: gparam
;
3831 * mono_metadata_create_anon_gparam:
3832 * \param image the MonoImage that owns the anonymous generic parameter
3833 * \param param_num the parameter number
3834 * \param is_mvar TRUE if this is a method generic parameter, FALSE if it's a class generic parameter.
3836 * Returns: a new, or exisisting \c MonoGenericParam for an anonymous generic parameter with the given properties.
3838 * LOCKING: takes the image lock.
3841 mono_metadata_create_anon_gparam (MonoImage
*image
, gint32 param_num
, gboolean is_mvar
)
3843 MonoGenericContainer
*container
= mono_get_anonymous_container_for_image (image
, is_mvar
);
3844 MonoGenericParam
*gparam
= lookup_anon_gparam (image
, container
, param_num
, is_mvar
);
3847 if (param_num
>= 0 && param_num
< FAST_GPARAM_CACHE_SIZE
) {
3848 return publish_anon_gparam_fast (image
, container
, param_num
);
3850 // Create a candidate generic param and try to insert it in the cache.
3851 // If multiple threads both try to publish the same param, all but one
3852 // will leak, but that's okay.
3853 gparam
= (MonoGenericParam
*)mono_image_alloc0 (image
, sizeof (MonoGenericParam
));
3854 gparam
->owner
= container
;
3855 gparam
->num
= param_num
;
3857 return publish_anon_gparam_slow (image
, gparam
);
3862 * mono_metadata_parse_generic_param:
3863 * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3864 * see mono_metadata_parse_type_checked() for details.
3865 * Internal routine to parse a generic type parameter.
3866 * LOCKING: Acquires the loader lock
3868 static MonoGenericParam
*
3869 mono_metadata_parse_generic_param (MonoImage
*m
, MonoGenericContainer
*generic_container
,
3870 MonoTypeEnum type
, const char *ptr
, const char **rptr
, MonoError
*error
)
3872 int index
= mono_metadata_decode_value (ptr
, &ptr
);
3878 generic_container
= select_container (generic_container
, type
);
3879 if (!generic_container
) {
3880 gboolean is_mvar
= FALSE
;
3885 case MONO_TYPE_MVAR
:
3889 g_error ("Cerating generic param object with invalid MonoType"); // This is not a generic param
3892 return mono_metadata_create_anon_gparam (m
, index
, is_mvar
);
3895 if (index
>= generic_container
->type_argc
) {
3896 mono_error_set_bad_image (error
, m
, "Invalid generic %s parameter index %d, max index is %d",
3897 generic_container
->is_method
? "method" : "type",
3898 index
, generic_container
->type_argc
);
3902 //This can't return NULL
3903 return mono_generic_container_get_param (generic_container
, index
);
3907 * mono_metadata_get_shared_type:
3909 * Return a shared instance of TYPE, if available, NULL otherwise.
3910 * Shared MonoType instances help save memory. Their contents should not be modified
3911 * by the caller. They do not need to be freed as their lifetime is bound by either
3912 * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3913 * instance they are embedded in. If they are freed, they should be freed using
3914 * mono_metadata_free_type () instead of g_free ().
3917 mono_metadata_get_shared_type (MonoType
*type
)
3921 /* No need to use locking since nobody is modifying the hash table */
3922 if ((cached
= (MonoType
*)g_hash_table_lookup (type_cache
, type
)))
3925 switch (type
->type
){
3926 case MONO_TYPE_CLASS
:
3927 case MONO_TYPE_VALUETYPE
:
3928 if (type
== m_class_get_byval_arg (type
->data
.klass
))
3930 if (type
== m_class_get_this_arg (type
->data
.klass
))
3941 compare_type_literals (MonoImage
*image
, int class_type
, int type_type
, MonoError
*error
)
3945 /* _byval_arg.type can be zero if we're decoding a type that references a class been loading.
3946 * See mcs/test/gtest-440. and #650936.
3947 * FIXME This better be moved to the metadata verifier as it can catch more cases.
3951 /* NET 1.1 assemblies might encode string and object in a denormalized way.
3954 if (class_type
== type_type
)
3957 if (type_type
== MONO_TYPE_CLASS
) {
3958 if (class_type
== MONO_TYPE_STRING
|| class_type
== MONO_TYPE_OBJECT
)
3960 //XXX stringify this argument
3961 mono_error_set_bad_image (error
, image
, "Expected reference type but got type kind %d", class_type
);
3965 g_assert (type_type
== MONO_TYPE_VALUETYPE
);
3966 switch (class_type
) {
3967 case MONO_TYPE_BOOLEAN
:
3968 case MONO_TYPE_CHAR
:
3981 case MONO_TYPE_CLASS
:
3984 //XXX stringify this argument
3985 mono_error_set_bad_image (error
, image
, "Expected value type but got type kind %d", class_type
);
3991 verify_var_type_and_container (MonoImage
*image
, int var_type
, MonoGenericContainer
*container
, MonoError
*error
)
3994 if (var_type
== MONO_TYPE_MVAR
) {
3995 if (!container
->is_method
) { //MVAR and a method container
3996 mono_error_set_bad_image (error
, image
, "MVAR parsed in a context without a method container");
4000 if (!(!container
->is_method
|| //VAR and class container
4001 (container
->is_method
&& container
->parent
))) { //VAR and method container with parent
4002 mono_error_set_bad_image (error
, image
, "VAR parsed in a context without a class container");
4010 * do_mono_metadata_parse_type:
4011 * @type: MonoType to be filled in with the return value
4013 * @generic_context: generics_context
4014 * @transient: whenever to allocate data from the heap
4015 * @ptr: pointer to the encoded type
4016 * @rptr: pointer where the end of the encoded type is saved
4018 * Internal routine used to "fill" the contents of @type from an
4019 * allocated pointer. This is done this way to avoid doing too
4020 * many mini-allocations (particularly for the MonoFieldType which
4021 * most of the time is just a MonoType, but sometimes might be augmented).
4023 * This routine is used by mono_metadata_parse_type and
4024 * mono_metadata_parse_field_type
4026 * This extracts a Type as specified in Partition II (22.2.12)
4028 * Returns: FALSE if the type could not be loaded
4031 do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
4032 gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
4036 type
->type
= (MonoTypeEnum
)mono_metadata_decode_value (ptr
, &ptr
);
4038 switch (type
->type
){
4039 case MONO_TYPE_VOID
:
4040 case MONO_TYPE_BOOLEAN
:
4041 case MONO_TYPE_CHAR
:
4054 case MONO_TYPE_STRING
:
4055 case MONO_TYPE_OBJECT
:
4056 case MONO_TYPE_TYPEDBYREF
:
4058 case MONO_TYPE_VALUETYPE
:
4059 case MONO_TYPE_CLASS
: {
4062 token
= mono_metadata_parse_typedef_or_ref (m
, ptr
, &ptr
);
4063 klass
= mono_class_get_checked (m
, token
, error
);
4064 type
->data
.klass
= klass
;
4068 if (!compare_type_literals (m
, m_class_get_byval_arg (klass
)->type
, type
->type
, error
))
4073 case MONO_TYPE_SZARRAY
: {
4074 MonoType
*etype
= mono_metadata_parse_type_checked (m
, container
, 0, transient
, ptr
, &ptr
, error
);
4078 type
->data
.klass
= mono_class_from_mono_type_internal (etype
);
4081 mono_metadata_free_type (etype
);
4083 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.
4086 case MONO_TYPE_PTR
: {
4087 type
->data
.type
= mono_metadata_parse_type_checked (m
, container
, 0, transient
, ptr
, &ptr
, error
);
4088 if (!type
->data
.type
)
4092 case MONO_TYPE_FNPTR
: {
4093 type
->data
.method
= mono_metadata_parse_method_signature_full (m
, container
, 0, ptr
, &ptr
, error
);
4094 if (!type
->data
.method
)
4098 case MONO_TYPE_ARRAY
: {
4099 type
->data
.array
= mono_metadata_parse_array_internal (m
, container
, transient
, ptr
, &ptr
, error
);
4100 if (!type
->data
.array
)
4104 case MONO_TYPE_MVAR
:
4105 case MONO_TYPE_VAR
: {
4106 if (container
&& !verify_var_type_and_container (m
, type
->type
, container
, error
))
4109 type
->data
.generic_param
= mono_metadata_parse_generic_param (m
, container
, type
->type
, ptr
, &ptr
, error
);
4110 if (!type
->data
.generic_param
)
4115 case MONO_TYPE_GENERICINST
: {
4116 if (!do_mono_metadata_parse_generic_class (type
, m
, container
, ptr
, &ptr
, error
))
4121 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
);
4131 * mono_metadata_free_type:
4132 * \param type type to free
4134 * Free the memory allocated for type \p type which is allocated on the heap.
4137 mono_metadata_free_type (MonoType
*type
)
4139 if (type
>= builtin_types
&& type
< builtin_types
+ NBUILTIN_TYPES ())
4142 switch (type
->type
){
4143 case MONO_TYPE_OBJECT
:
4144 case MONO_TYPE_STRING
:
4145 if (!type
->data
.klass
)
4148 case MONO_TYPE_CLASS
:
4149 case MONO_TYPE_VALUETYPE
:
4150 if (type
== m_class_get_byval_arg (type
->data
.klass
) || type
== m_class_get_this_arg (type
->data
.klass
))
4154 mono_metadata_free_type (type
->data
.type
);
4156 case MONO_TYPE_FNPTR
:
4157 mono_metadata_free_method_signature (type
->data
.method
);
4159 case MONO_TYPE_ARRAY
:
4160 mono_metadata_free_array (type
->data
.array
);
4171 hex_dump (const char *buffer
, int base
, int count
)
4173 int show_header
= 1;
4181 for (i
= 0; i
< count
; i
++){
4184 printf ("\n0x%08x: ", (unsigned char) base
+ i
);
4186 printf ("%02x ", (unsigned char) (buffer
[i
]));
4193 * @ptr: Points to the beginning of the Section Data (25.3)
4195 static MonoExceptionClause
*
4196 parse_section_data (MonoImage
*m
, int *num_clauses
, const unsigned char *ptr
, MonoError
*error
)
4198 unsigned char sect_data_flags
;
4200 guint32 sect_data_len
;
4201 MonoExceptionClause
* clauses
= NULL
;
4206 /* align on 32-bit boundary */
4207 ptr
= dword_align (ptr
);
4208 sect_data_flags
= *ptr
;
4211 is_fat
= sect_data_flags
& METHOD_HEADER_SECTION_FAT_FORMAT
;
4213 sect_data_len
= (ptr
[2] << 16) | (ptr
[1] << 8) | ptr
[0];
4216 sect_data_len
= ptr
[0];
4220 if (sect_data_flags
& METHOD_HEADER_SECTION_EHTABLE
) {
4221 const unsigned char *p
= dword_align (ptr
);
4223 *num_clauses
= is_fat
? sect_data_len
/ 24: sect_data_len
/ 12;
4224 /* we could just store a pointer if we don't need to byteswap */
4225 clauses
= (MonoExceptionClause
*)g_malloc0 (sizeof (MonoExceptionClause
) * (*num_clauses
));
4226 for (i
= 0; i
< *num_clauses
; ++i
) {
4227 MonoExceptionClause
*ec
= &clauses
[i
];
4230 ec
->flags
= read32 (p
);
4231 ec
->try_offset
= read32 (p
+ 4);
4232 ec
->try_len
= read32 (p
+ 8);
4233 ec
->handler_offset
= read32 (p
+ 12);
4234 ec
->handler_len
= read32 (p
+ 16);
4235 tof_value
= read32 (p
+ 20);
4238 ec
->flags
= read16 (p
);
4239 ec
->try_offset
= read16 (p
+ 2);
4240 ec
->try_len
= *(p
+ 4);
4241 ec
->handler_offset
= read16 (p
+ 5);
4242 ec
->handler_len
= *(p
+ 7);
4243 tof_value
= read32 (p
+ 8);
4246 if (ec
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
) {
4247 ec
->data
.filter_offset
= tof_value
;
4248 } else if (ec
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) {
4249 ec
->data
.catch_class
= NULL
;
4251 ec
->data
.catch_class
= mono_class_get_checked (m
, tof_value
, error
);
4252 if (!is_ok (error
)) {
4258 ec
->data
.catch_class
= NULL
;
4260 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
4264 if (sect_data_flags
& METHOD_HEADER_SECTION_MORE_SECTS
)
4265 ptr
+= sect_data_len
- 4; /* LAMESPEC: it seems the size includes the header */
4272 * mono_method_get_header_summary:
4273 * @method: The method to get the header.
4274 * @summary: Where to store the header
4277 * Returns: TRUE if the header was properly decoded.
4280 mono_method_get_header_summary (MonoMethod
*method
, MonoMethodHeaderSummary
*summary
)
4286 unsigned char flags
, format
;
4290 /*Only the GMD has a pointer to the metadata.*/
4291 while (method
->is_inflated
)
4292 method
= ((MonoMethodInflated
*)method
)->declaring
;
4294 summary
->code
= NULL
;
4295 summary
->code_size
= 0;
4296 summary
->max_stack
= 0;
4297 summary
->has_clauses
= FALSE
;
4298 summary
->has_locals
= FALSE
;
4300 /*FIXME extract this into a MACRO and share it with mono_method_get_header*/
4301 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
))
4304 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| method
->sre_method
) {
4305 MonoMethodHeader
*header
= ((MonoMethodWrapper
*)method
)->header
;
4308 summary
->code
= header
->code
;
4309 summary
->code_size
= header
->code_size
;
4310 summary
->max_stack
= header
->max_stack
;
4311 summary
->has_clauses
= header
->num_clauses
> 0;
4312 summary
->has_locals
= header
->num_locals
> 0;
4317 idx
= mono_metadata_token_index (method
->token
);
4318 img
= m_class_get_image (method
->klass
);
4319 rva
= mono_metadata_decode_row_col (&img
->tables
[MONO_TABLE_METHOD
], idx
- 1, MONO_METHOD_RVA
);
4321 /*We must run the verifier since we'll be decoding it.*/
4322 if (!mono_verifier_verify_method_header (img
, rva
, error
)) {
4323 mono_error_cleanup (error
);
4327 ptr
= mono_image_rva_map (img
, rva
);
4331 flags
= *(const unsigned char *)ptr
;
4332 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
4335 case METHOD_HEADER_TINY_FORMAT
:
4337 summary
->max_stack
= 8;
4338 summary
->code
= (unsigned char *) ptr
;
4339 summary
->code_size
= flags
>> 2;
4341 case METHOD_HEADER_FAT_FORMAT
:
4342 fat_flags
= read16 (ptr
);
4344 summary
->max_stack
= read16 (ptr
);
4346 summary
->code_size
= read32 (ptr
);
4348 summary
->has_locals
= !!read32 (ptr
);
4350 if (fat_flags
& METHOD_HEADER_MORE_SECTS
)
4351 summary
->has_clauses
= TRUE
;
4352 summary
->code
= (unsigned char *) ptr
;
4361 * mono_metadata_parse_mh_full:
4362 * @m: metadata context
4363 * @generic_context: generics context
4364 * @ptr: pointer to the method header.
4366 * Decode the method header at @ptr, including pointer to the IL code,
4367 * info about local variables and optional exception tables.
4368 * This is a Mono runtime internal function.
4370 * LOCKING: Acquires the loader lock.
4372 * Returns: a transient MonoMethodHeader allocated from the heap.
4375 mono_metadata_parse_mh_full (MonoImage
*m
, MonoGenericContainer
*container
, const char *ptr
, MonoError
*error
)
4377 MonoMethodHeader
*mh
= NULL
;
4378 unsigned char flags
= *(const unsigned char *) ptr
;
4379 unsigned char format
= flags
& METHOD_HEADER_FORMAT_MASK
;
4381 guint32 local_var_sig_tok
, max_stack
, code_size
, init_locals
;
4382 const unsigned char *code
;
4383 MonoExceptionClause
* clauses
= NULL
;
4384 int num_clauses
= 0;
4385 MonoTableInfo
*t
= &m
->tables
[MONO_TABLE_STANDALONESIG
];
4386 guint32 cols
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
4391 mono_error_set_bad_image (error
, m
, "Method header with null pointer");
4396 case METHOD_HEADER_TINY_FORMAT
:
4397 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
);
4400 mh
->is_transient
= TRUE
;
4401 local_var_sig_tok
= 0;
4402 mh
->code_size
= flags
>> 2;
4403 mh
->code
= (unsigned char*)ptr
;
4405 case METHOD_HEADER_FAT_FORMAT
:
4406 fat_flags
= read16 (ptr
);
4408 max_stack
= read16 (ptr
);
4410 code_size
= read32 (ptr
);
4412 local_var_sig_tok
= read32 (ptr
);
4415 if (fat_flags
& METHOD_HEADER_INIT_LOCALS
)
4420 code
= (unsigned char*)ptr
;
4422 if (!(fat_flags
& METHOD_HEADER_MORE_SECTS
))
4426 * There are more sections
4428 ptr
= (char*)code
+ code_size
;
4431 mono_error_set_bad_image (error
, m
, "Invalid method header format %d", format
);
4435 if (local_var_sig_tok
) {
4436 int idx
= (local_var_sig_tok
& 0xffffff)-1;
4437 if (idx
>= t
->rows
|| idx
< 0) {
4438 mono_error_set_bad_image (error
, m
, "Invalid method header local vars signature token 0x%8x", idx
);
4441 mono_metadata_decode_row (t
, idx
, cols
, 1);
4443 if (!mono_verifier_verify_standalone_signature (m
, cols
[MONO_STAND_ALONE_SIGNATURE
], error
))
4446 if (fat_flags
& METHOD_HEADER_MORE_SECTS
) {
4447 clauses
= parse_section_data (m
, &num_clauses
, (const unsigned char*)ptr
, error
);
4448 goto_if_nok (error
, fail
);
4450 if (local_var_sig_tok
) {
4451 const char *locals_ptr
;
4454 locals_ptr
= mono_metadata_blob_heap (m
, cols
[MONO_STAND_ALONE_SIGNATURE
]);
4455 mono_metadata_decode_blob_size (locals_ptr
, &locals_ptr
);
4456 if (*locals_ptr
!= 0x07)
4457 g_warning ("wrong signature for locals blob");
4459 len
= mono_metadata_decode_value (locals_ptr
, &locals_ptr
);
4460 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ len
* sizeof (MonoType
*) + num_clauses
* sizeof (MonoExceptionClause
));
4461 mh
->num_locals
= len
;
4462 for (i
= 0; i
< len
; ++i
) {
4463 mh
->locals
[i
] = mono_metadata_parse_type_internal (m
, container
, 0, TRUE
, locals_ptr
, &locals_ptr
, error
);
4464 goto_if_nok (error
, fail
);
4467 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ num_clauses
* sizeof (MonoExceptionClause
));
4470 mh
->code_size
= code_size
;
4471 mh
->max_stack
= max_stack
;
4472 mh
->is_transient
= TRUE
;
4473 mh
->init_locals
= init_locals
;
4475 MonoExceptionClause
* clausesp
= (MonoExceptionClause
*)&mh
->locals
[mh
->num_locals
];
4476 memcpy (clausesp
, clauses
, num_clauses
* sizeof (MonoExceptionClause
));
4478 mh
->clauses
= clausesp
;
4479 mh
->num_clauses
= num_clauses
;
4490 * mono_metadata_parse_mh:
4491 * \param generic_context generics context
4492 * \param ptr pointer to the method header.
4494 * Decode the method header at \p ptr, including pointer to the IL code,
4495 * info about local variables and optional exception tables.
4497 * \returns a transient \c MonoMethodHeader allocated from the heap.
4500 mono_metadata_parse_mh (MonoImage
*m
, const char *ptr
)
4503 MonoMethodHeader
*header
= mono_metadata_parse_mh_full (m
, NULL
, ptr
, error
);
4504 mono_error_cleanup (error
);
4509 * mono_metadata_free_mh:
4510 * \param mh a method header
4512 * Free the memory allocated for the method header.
4515 mono_metadata_free_mh (MonoMethodHeader
*mh
)
4519 /* If it is not transient it means it's part of a wrapper method,
4520 * or a SRE-generated method, so the lifetime in that case is
4521 * dictated by the method's own lifetime
4523 if (mh
&& mh
->is_transient
) {
4524 for (i
= 0; i
< mh
->num_locals
; ++i
)
4525 mono_metadata_free_type (mh
->locals
[i
]);
4531 * mono_method_header_get_code:
4532 * \param header a \c MonoMethodHeader pointer
4533 * \param code_size memory location for returning the code size
4534 * \param max_stack memory location for returning the max stack
4536 * Method header accessor to retreive info about the IL code properties:
4537 * a pointer to the IL code itself, the size of the code and the max number
4538 * of stack slots used by the code.
4540 * \returns pointer to the IL code represented by the method header.
4542 const unsigned char*
4543 mono_method_header_get_code (MonoMethodHeader
*header
, guint32
* code_size
, guint32
* max_stack
)
4546 *code_size
= header
->code_size
;
4548 *max_stack
= header
->max_stack
;
4549 return header
->code
;
4553 * mono_method_header_get_locals:
4554 * \param header a \c MonoMethodHeader pointer
4555 * \param num_locals memory location for returning the number of local variables
4556 * \param init_locals memory location for returning the init_locals flag
4558 * Method header accessor to retreive info about the local variables:
4559 * an array of local types, the number of locals and whether the locals
4560 * are supposed to be initialized to 0 on method entry
4562 * \returns pointer to an array of types of the local variables
4565 mono_method_header_get_locals (MonoMethodHeader
*header
, guint32
* num_locals
, gboolean
*init_locals
)
4568 *num_locals
= header
->num_locals
;
4570 *init_locals
= header
->init_locals
;
4571 return header
->locals
;
4575 * mono_method_header_get_num_clauses:
4576 * @header: a MonoMethodHeader pointer
4578 * Method header accessor to retreive the number of exception clauses.
4580 * Returns: the number of exception clauses present
4583 mono_method_header_get_num_clauses (MonoMethodHeader
*header
)
4585 return header
->num_clauses
;
4589 * mono_method_header_get_clauses:
4590 * \param header a \c MonoMethodHeader pointer
4591 * \param method \c MonoMethod the header belongs to
4592 * \param iter pointer to a iterator
4593 * \param clause pointer to a \c MonoExceptionClause structure which will be filled with the info
4595 * Get the info about the exception clauses in the method. Set \c *iter to NULL to
4596 * initiate the iteration, then call the method repeatedly until it returns FALSE.
4597 * At each iteration, the structure pointed to by clause if filled with the
4598 * exception clause information.
4600 * \returns TRUE if clause was filled with info, FALSE if there are no more exception
4604 mono_method_header_get_clauses (MonoMethodHeader
*header
, MonoMethod
*method
, gpointer
*iter
, MonoExceptionClause
*clause
)
4606 MonoExceptionClause
*sc
;
4607 /* later we'll be able to use this interface to parse the clause info on demand,
4608 * without allocating anything.
4610 if (!iter
|| !header
->num_clauses
)
4613 *iter
= sc
= header
->clauses
;
4617 sc
= (MonoExceptionClause
*)*iter
;
4619 if (sc
< header
->clauses
+ header
->num_clauses
) {
4628 * mono_metadata_parse_field_type:
4629 * \param m metadata context to extract information from
4630 * \param ptr pointer to the field signature
4631 * \param rptr pointer updated to match the end of the decoded stream
4633 * Parses the field signature, and returns the type information for it.
4635 * \returns The \c MonoType that was extracted from \p ptr .
4638 mono_metadata_parse_field_type (MonoImage
*m
, short field_flags
, const char *ptr
, const char **rptr
)
4641 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, field_flags
, FALSE
, ptr
, rptr
, error
);
4642 mono_error_cleanup (error
);
4647 * mono_metadata_parse_param:
4648 * \param m metadata context to extract information from
4649 * \param ptr pointer to the param signature
4650 * \param rptr pointer updated to match the end of the decoded stream
4652 * Parses the param signature, and returns the type information for it.
4654 * \returns The \c MonoType that was extracted from \p ptr .
4657 mono_metadata_parse_param (MonoImage
*m
, const char *ptr
, const char **rptr
)
4660 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, 0, FALSE
, ptr
, rptr
, error
);
4661 mono_error_cleanup (error
);
4666 * mono_metadata_token_from_dor:
4667 * \param dor_token A \c TypeDefOrRef coded index
4669 * \p dor_token is a \c TypeDefOrRef coded index: it contains either
4670 * a \c TypeDef, \c TypeRef or \c TypeSpec in the lower bits, and the upper
4671 * bits contain an index into the table.
4673 * \returns an expanded token
4676 mono_metadata_token_from_dor (guint32 dor_index
)
4680 table
= dor_index
& 0x03;
4681 idx
= dor_index
>> 2;
4684 case 0: /* TypeDef */
4685 return MONO_TOKEN_TYPE_DEF
| idx
;
4686 case 1: /* TypeRef */
4687 return MONO_TOKEN_TYPE_REF
| idx
;
4688 case 2: /* TypeSpec */
4689 return MONO_TOKEN_TYPE_SPEC
| idx
;
4691 g_assert_not_reached ();
4698 * We use this to pass context information to the row locator
4701 int idx
; /* The index that we are trying to locate */
4702 int col_idx
; /* The index in the row where idx may be stored */
4703 MonoTableInfo
*t
; /* pointer to the table */
4708 * How the row locator works.
4713 * ___|___------> _______
4716 * A column in the rows of table A references an index in table B.
4717 * For example A may be the TYPEDEF table and B the METHODDEF table.
4719 * Given an index in table B we want to get the row in table A
4720 * where the column n references our index in B.
4722 * In the locator_t structure:
4724 * col_idx is the column number
4725 * index is the index in table B
4726 * result will be the index in table A
4729 * Table A Table B column (in table A)
4730 * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
4731 * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
4732 * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
4733 * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
4734 * METHODSEM PROPERTY ASSOCIATION (encoded index)
4736 * Note that we still don't support encoded indexes.
4740 typedef_locator (const void *a
, const void *b
)
4742 locator_t
*loc
= (locator_t
*) a
;
4743 const char *bb
= (const char *) b
;
4744 int typedef_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4745 guint32 col
, col_next
;
4747 col
= mono_metadata_decode_row_col (loc
->t
, typedef_index
, loc
->col_idx
);
4753 * Need to check that the next row is valid.
4755 if (typedef_index
+ 1 < loc
->t
->rows
) {
4756 col_next
= mono_metadata_decode_row_col (loc
->t
, typedef_index
+ 1, loc
->col_idx
);
4757 if (loc
->idx
>= col_next
)
4760 if (col
== col_next
)
4764 loc
->result
= typedef_index
;
4770 table_locator (const void *a
, const void *b
)
4772 locator_t
*loc
= (locator_t
*) a
;
4773 const char *bb
= (const char *) b
;
4774 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4777 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
4779 if (loc
->idx
== col
) {
4780 loc
->result
= table_index
;
4790 declsec_locator (const void *a
, const void *b
)
4792 locator_t
*loc
= (locator_t
*) a
;
4793 const char *bb
= (const char *) b
;
4794 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4797 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
4799 if (loc
->idx
== col
) {
4800 loc
->result
= table_index
;
4812 * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
4813 * which contains IDX.
4816 search_ptr_table (MonoImage
*image
, int table
, int idx
)
4818 MonoTableInfo
*ptrdef
= &image
->tables
[table
];
4821 /* Use a linear search to find our index in the table */
4822 for (i
= 0; i
< ptrdef
->rows
; i
++)
4823 /* All the Ptr tables have the same structure */
4824 if (mono_metadata_decode_row_col (ptrdef
, i
, 0) == idx
)
4827 if (i
< ptrdef
->rows
)
4834 * mono_metadata_typedef_from_field:
4835 * \param meta metadata context
4836 * \param index FieldDef token
4838 * \returns the 1-based index into the \c TypeDef table of the type that
4839 * declared the field described by \p index, or 0 if not found.
4842 mono_metadata_typedef_from_field (MonoImage
*meta
, guint32 index
)
4844 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
4850 loc
.idx
= mono_metadata_token_index (index
);
4851 loc
.col_idx
= MONO_TYPEDEF_FIELD_LIST
;
4854 if (meta
->uncompressed_metadata
)
4855 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
4857 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
4860 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4861 return loc
.result
+ 1;
4865 * mono_metadata_typedef_from_method:
4866 * \param meta metadata context
4867 * \param index \c MethodDef token
4868 * \returns the 1-based index into the \c TypeDef table of the type that
4869 * declared the method described by \p index. 0 if not found.
4872 mono_metadata_typedef_from_method (MonoImage
*meta
, guint32 index
)
4874 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
4880 loc
.idx
= mono_metadata_token_index (index
);
4881 loc
.col_idx
= MONO_TYPEDEF_METHOD_LIST
;
4884 if (meta
->uncompressed_metadata
)
4885 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_METHOD_POINTER
, loc
.idx
);
4887 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
4890 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4891 return loc
.result
+ 1;
4895 * mono_metadata_interfaces_from_typedef_full:
4896 * \param meta metadata context
4897 * \param index typedef token
4898 * \param interfaces Out parameter used to store the interface array
4899 * \param count Out parameter used to store the number of interfaces
4900 * \param heap_alloc_result if TRUE the result array will be \c g_malloc'd
4901 * \param context The generic context
4902 * \param error set on error
4904 * The array of interfaces that the \p index typedef token implements is returned in
4905 * \p interfaces. The number of elements in the array is returned in \p count.
4907 * \returns \c TRUE on success, \c FALSE on failure and sets \p error.
4910 mono_metadata_interfaces_from_typedef_full (MonoImage
*meta
, guint32 index
, MonoClass
***interfaces
, guint
*count
, gboolean heap_alloc_result
, MonoGenericContext
*context
, MonoError
*error
)
4912 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_INTERFACEIMPL
];
4915 guint32 cols
[MONO_INTERFACEIMPL_SIZE
];
4926 loc
.idx
= mono_metadata_token_index (index
);
4927 loc
.col_idx
= MONO_INTERFACEIMPL_CLASS
;
4930 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4935 * We may end up in the middle of the rows...
4938 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_INTERFACEIMPL_CLASS
))
4944 while (pos
< tdef
->rows
) {
4945 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
4946 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
4951 if (heap_alloc_result
)
4952 result
= g_new0 (MonoClass
*, pos
- start
);
4954 result
= (MonoClass
**)mono_image_alloc0 (meta
, sizeof (MonoClass
*) * (pos
- start
));
4957 while (pos
< tdef
->rows
) {
4960 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
4961 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
4963 iface
= mono_class_get_and_inflate_typespec_checked (
4964 meta
, mono_metadata_token_from_dor (cols
[MONO_INTERFACEIMPL_INTERFACE
]), context
, error
);
4967 result
[pos
- start
] = iface
;
4970 *count
= pos
- start
;
4971 *interfaces
= result
;
4976 * mono_metadata_interfaces_from_typedef:
4977 * \param meta metadata context
4978 * \param index typedef token
4979 * \param count Out parameter used to store the number of interfaces
4981 * The array of interfaces that the \p index typedef token implements is returned in
4982 * \p interfaces. The number of elements in the array is returned in \p count. The returned
4983 * array is allocated with \c g_malloc and the caller must free it.
4985 * LOCKING: Acquires the loader lock .
4987 * \returns the interface array on success, NULL on failure.
4990 mono_metadata_interfaces_from_typedef (MonoImage
*meta
, guint32 index
, guint
*count
)
4993 MonoClass
**interfaces
= NULL
;
4996 rv
= mono_metadata_interfaces_from_typedef_full (meta
, index
, &interfaces
, count
, TRUE
, NULL
, error
);
4997 mono_error_assert_ok (error
);
5005 * mono_metadata_nested_in_typedef:
5006 * \param meta metadata context
5007 * \param index typedef token
5008 * \returns the 1-based index into the TypeDef table of the type
5009 * where the type described by \p index is nested.
5010 * Returns 0 if \p index describes a non-nested type.
5013 mono_metadata_nested_in_typedef (MonoImage
*meta
, guint32 index
)
5015 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
5021 loc
.idx
= mono_metadata_token_index (index
);
5022 loc
.col_idx
= MONO_NESTED_CLASS_NESTED
;
5025 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5028 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
5029 return mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_NESTED_CLASS_ENCLOSING
) | MONO_TOKEN_TYPE_DEF
;
5033 * mono_metadata_nesting_typedef:
5034 * \param meta metadata context
5035 * \param index typedef token
5036 * \returns the 1-based index into the \c TypeDef table of the first type
5037 * that is nested inside the type described by \p index. The search starts at
5038 * \p start_index. Returns 0 if no such type is found.
5041 mono_metadata_nesting_typedef (MonoImage
*meta
, guint32 index
, guint32 start_index
)
5043 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
5045 guint32 class_index
= mono_metadata_token_index (index
);
5050 start
= start_index
;
5052 while (start
<= tdef
->rows
) {
5053 if (class_index
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_NESTED_CLASS_ENCLOSING
))
5059 if (start
> tdef
->rows
)
5066 * mono_metadata_packing_from_typedef:
5067 * \param meta metadata context
5068 * \param index token representing a type
5069 * \returns the info stored in the \c ClassLayout table for the given typedef token
5070 * into the \p packing and \p size pointers.
5071 * Returns 0 if the info is not found.
5074 mono_metadata_packing_from_typedef (MonoImage
*meta
, guint32 index
, guint32
*packing
, guint32
*size
)
5076 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CLASSLAYOUT
];
5078 guint32 cols
[MONO_CLASS_LAYOUT_SIZE
];
5083 loc
.idx
= mono_metadata_token_index (index
);
5084 loc
.col_idx
= MONO_CLASS_LAYOUT_PARENT
;
5087 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5090 mono_metadata_decode_row (tdef
, loc
.result
, cols
, MONO_CLASS_LAYOUT_SIZE
);
5092 *packing
= cols
[MONO_CLASS_LAYOUT_PACKING_SIZE
];
5094 *size
= cols
[MONO_CLASS_LAYOUT_CLASS_SIZE
];
5096 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
5097 return loc
.result
+ 1;
5101 * mono_metadata_custom_attrs_from_index:
5102 * \param meta metadata context
5103 * \param index token representing the parent
5104 * \returns: the 1-based index into the \c CustomAttribute table of the first
5105 * attribute which belongs to the metadata object described by \p index.
5106 * Returns 0 if no such attribute is found.
5109 mono_metadata_custom_attrs_from_index (MonoImage
*meta
, guint32 index
)
5111 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
5118 loc
.col_idx
= MONO_CUSTOM_ATTR_PARENT
;
5121 /* FIXME: Index translation */
5123 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5126 /* Find the first entry by searching backwards */
5127 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_CUSTOM_ATTR_PARENT
) == index
))
5130 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
5131 return loc
.result
+ 1;
5135 * mono_metadata_declsec_from_index:
5136 * \param meta metadata context
5137 * \param index token representing the parent
5138 * \returns the 0-based index into the \c DeclarativeSecurity table of the first
5139 * attribute which belongs to the metadata object described by \p index.
5140 * Returns \c -1 if no such attribute is found.
5143 mono_metadata_declsec_from_index (MonoImage
*meta
, guint32 index
)
5145 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_DECLSECURITY
];
5152 loc
.col_idx
= MONO_DECL_SECURITY_PARENT
;
5155 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, declsec_locator
))
5158 /* Find the first entry by searching backwards */
5159 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_DECL_SECURITY_PARENT
) == index
))
5166 * mono_metadata_localscope_from_methoddef:
5167 * @meta: metadata context
5168 * @index: methoddef index
5170 * Returns: the 1-based index into the LocalScope table of the first
5171 * scope which belongs to the method described by @index.
5172 * Returns 0 if no such row is found.
5175 mono_metadata_localscope_from_methoddef (MonoImage
*meta
, guint32 index
)
5177 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_LOCALSCOPE
];
5184 loc
.col_idx
= MONO_LOCALSCOPE_METHOD
;
5187 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5190 /* Find the first entry by searching backwards */
5191 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_LOCALSCOPE_METHOD
) == index
))
5194 return loc
.result
+ 1;
5199 mono_backtrace (int limit
)
5204 backtrace (array
, limit
);
5205 names
= backtrace_symbols (array
, limit
);
5206 for (i
=0; i
< limit
; ++i
) {
5207 g_print ("\t%s\n", names
[i
]);
5213 static int i8_align
;
5216 * mono_type_set_alignment:
5218 * Set the alignment used by runtime to layout fields etc. of type TYPE to ALIGN.
5219 * This should only be used in AOT mode since the resulting layout will not match the
5223 mono_type_set_alignment (MonoTypeEnum type
, int align
)
5225 /* Support only a few types whose alignment is abi dependent */
5231 g_assert_not_reached ();
5238 * \param t the type to return the size of
5239 * \returns The number of bytes required to hold an instance of this
5243 mono_type_size (MonoType
*t
, int *align
)
5245 MonoTypeEnum simple_type
;
5252 *align
= MONO_ABI_ALIGNOF (gpointer
);
5253 return MONO_ABI_SIZEOF (gpointer
);
5256 simple_type
= t
->type
;
5258 switch (simple_type
) {
5259 case MONO_TYPE_VOID
:
5262 case MONO_TYPE_BOOLEAN
:
5263 *align
= MONO_ABI_ALIGNOF (gint8
);
5267 *align
= MONO_ABI_ALIGNOF (gint8
);
5269 case MONO_TYPE_CHAR
:
5272 *align
= MONO_ABI_ALIGNOF (gint16
);
5276 *align
= MONO_ABI_ALIGNOF (gint32
);
5279 *align
= MONO_ABI_ALIGNOF (float);
5283 *align
= MONO_ABI_ALIGNOF (gint64
);
5286 *align
= MONO_ABI_ALIGNOF (double);
5290 *align
= MONO_ABI_ALIGNOF (gpointer
);
5291 return MONO_ABI_SIZEOF (gpointer
);
5292 case MONO_TYPE_VALUETYPE
: {
5293 if (m_class_is_enumtype (t
->data
.klass
))
5294 return mono_type_size (mono_class_enum_basetype_internal (t
->data
.klass
), align
);
5296 return mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
5298 case MONO_TYPE_STRING
:
5299 case MONO_TYPE_OBJECT
:
5300 case MONO_TYPE_CLASS
:
5301 case MONO_TYPE_SZARRAY
:
5303 case MONO_TYPE_FNPTR
:
5304 case MONO_TYPE_ARRAY
:
5305 *align
= MONO_ABI_ALIGNOF (gpointer
);
5306 return MONO_ABI_SIZEOF (gpointer
);
5307 case MONO_TYPE_TYPEDBYREF
:
5308 return mono_class_value_size (mono_defaults
.typed_reference_class
, (guint32
*)align
);
5309 case MONO_TYPE_GENERICINST
: {
5310 MonoGenericClass
*gclass
= t
->data
.generic_class
;
5311 MonoClass
*container_class
= gclass
->container_class
;
5313 // g_assert (!gclass->inst->is_open);
5315 if (m_class_is_valuetype (container_class
)) {
5316 if (m_class_is_enumtype (container_class
))
5317 return mono_type_size (mono_class_enum_basetype_internal (container_class
), align
);
5319 return mono_class_value_size (mono_class_from_mono_type_internal (t
), (guint32
*)align
);
5321 *align
= MONO_ABI_ALIGNOF (gpointer
);
5322 return MONO_ABI_SIZEOF (gpointer
);
5326 case MONO_TYPE_MVAR
:
5327 if (!t
->data
.generic_param
->gshared_constraint
|| t
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_VALUETYPE
) {
5328 *align
= MONO_ABI_ALIGNOF (gpointer
);
5329 return MONO_ABI_SIZEOF (gpointer
);
5331 /* The gparam can only match types given by gshared_constraint */
5332 return mono_type_size (t
->data
.generic_param
->gshared_constraint
, align
);
5336 g_error ("mono_type_size: type 0x%02x unknown", t
->type
);
5342 * mono_type_stack_size:
5343 * \param t the type to return the size it uses on the stack
5344 * \returns The number of bytes required to hold an instance of this
5345 * type on the runtime stack
5348 mono_type_stack_size (MonoType
*t
, int *align
)
5350 return mono_type_stack_size_internal (t
, align
, FALSE
);
5354 mono_type_stack_size_internal (MonoType
*t
, int *align
, gboolean allow_open
)
5357 MonoTypeEnum simple_type
;
5358 int stack_slot_size
= TARGET_SIZEOF_VOID_P
;
5359 int stack_slot_align
= TARGET_SIZEOF_VOID_P
;
5361 g_assert (t
!= NULL
);
5367 *align
= stack_slot_align
;
5368 return stack_slot_size
;
5371 simple_type
= t
->type
;
5372 switch (simple_type
) {
5373 case MONO_TYPE_BOOLEAN
:
5374 case MONO_TYPE_CHAR
:
5383 case MONO_TYPE_STRING
:
5384 case MONO_TYPE_OBJECT
:
5385 case MONO_TYPE_CLASS
:
5386 case MONO_TYPE_SZARRAY
:
5388 case MONO_TYPE_FNPTR
:
5389 case MONO_TYPE_ARRAY
:
5390 *align
= stack_slot_align
;
5391 return stack_slot_size
;
5393 case MONO_TYPE_MVAR
:
5394 g_assert (allow_open
);
5395 if (!t
->data
.generic_param
->gshared_constraint
|| t
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_VALUETYPE
) {
5396 *align
= stack_slot_align
;
5397 return stack_slot_size
;
5399 /* The gparam can only match types given by gshared_constraint */
5400 return mono_type_stack_size_internal (t
->data
.generic_param
->gshared_constraint
, align
, allow_open
);
5402 case MONO_TYPE_TYPEDBYREF
:
5403 *align
= stack_slot_align
;
5404 return stack_slot_size
* 3;
5406 *align
= MONO_ABI_ALIGNOF (float);
5407 return sizeof (float);
5410 *align
= MONO_ABI_ALIGNOF (gint64
);
5411 return sizeof (gint64
);
5413 *align
= MONO_ABI_ALIGNOF (double);
5414 return sizeof (double);
5415 case MONO_TYPE_VALUETYPE
: {
5418 if (m_class_is_enumtype (t
->data
.klass
))
5419 return mono_type_stack_size_internal (mono_class_enum_basetype_internal (t
->data
.klass
), align
, allow_open
);
5421 size
= mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
5423 *align
= *align
+ stack_slot_align
- 1;
5424 *align
&= ~(stack_slot_align
- 1);
5426 size
+= stack_slot_size
- 1;
5427 size
&= ~(stack_slot_size
- 1);
5432 case MONO_TYPE_GENERICINST
: {
5433 MonoGenericClass
*gclass
= t
->data
.generic_class
;
5434 MonoClass
*container_class
= gclass
->container_class
;
5437 g_assert (!gclass
->context
.class_inst
->is_open
);
5439 if (m_class_is_valuetype (container_class
)) {
5440 if (m_class_is_enumtype (container_class
))
5441 return mono_type_stack_size_internal (mono_class_enum_basetype_internal (container_class
), align
, allow_open
);
5443 guint32 size
= mono_class_value_size (mono_class_from_mono_type_internal (t
), (guint32
*)align
);
5445 *align
= *align
+ stack_slot_align
- 1;
5446 *align
&= ~(stack_slot_align
- 1);
5448 size
+= stack_slot_size
- 1;
5449 size
&= ~(stack_slot_size
- 1);
5454 *align
= stack_slot_align
;
5455 return stack_slot_size
;
5459 g_error ("type 0x%02x unknown", t
->type
);
5465 mono_type_generic_inst_is_valuetype (MonoType
*type
)
5467 g_assert (type
->type
== MONO_TYPE_GENERICINST
);
5468 return m_class_is_valuetype (type
->data
.generic_class
->container_class
);
5472 * mono_metadata_generic_class_is_valuetype:
5475 mono_metadata_generic_class_is_valuetype (MonoGenericClass
*gclass
)
5477 return m_class_is_valuetype (gclass
->container_class
);
5481 _mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
, gboolean signature_only
)
5483 MonoGenericInst
*i1
= g1
->context
.class_inst
;
5484 MonoGenericInst
*i2
= g2
->context
.class_inst
;
5486 if (g1
->is_dynamic
!= g2
->is_dynamic
)
5488 if (!mono_metadata_class_equal (g1
->container_class
, g2
->container_class
, signature_only
))
5490 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
5492 return g1
->is_tb_open
== g2
->is_tb_open
;
5496 _mono_metadata_generic_class_container_equal (const MonoGenericClass
*g1
, MonoClass
*c2
, gboolean signature_only
)
5498 MonoGenericInst
*i1
= g1
->context
.class_inst
;
5499 MonoGenericInst
*i2
= mono_class_get_generic_container (c2
)->context
.class_inst
;
5501 if (!mono_metadata_class_equal (g1
->container_class
, c2
, signature_only
))
5503 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
5505 return !g1
->is_tb_open
;
5509 mono_metadata_generic_context_hash (const MonoGenericContext
*context
)
5511 /* FIXME: check if this seed is good enough */
5512 guint hash
= 0xc01dfee7;
5513 if (context
->class_inst
)
5514 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->class_inst
);
5515 if (context
->method_inst
)
5516 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->method_inst
);
5521 mono_metadata_generic_context_equal (const MonoGenericContext
*g1
, const MonoGenericContext
*g2
)
5523 return g1
->class_inst
== g2
->class_inst
&& g1
->method_inst
== g2
->method_inst
;
5527 * mono_metadata_str_hash:
5529 * This should be used instead of g_str_hash for computing hash codes visible
5530 * outside this module, since g_str_hash () is not guaranteed to be stable
5531 * (its not the same in eglib for example).
5534 mono_metadata_str_hash (gconstpointer v1
)
5536 /* Same as g_str_hash () in glib */
5537 char *p
= (char *) v1
;
5542 hash
= (hash
<< 5) - hash
+ *p
;
5549 * mono_metadata_type_hash:
5551 * Computes a hash value for \p t1 to be used in \c GHashTable.
5552 * The returned hash is guaranteed to be the same across executions.
5555 mono_metadata_type_hash (MonoType
*t1
)
5557 guint hash
= t1
->type
;
5559 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
5561 case MONO_TYPE_VALUETYPE
:
5562 case MONO_TYPE_CLASS
:
5563 case MONO_TYPE_SZARRAY
: {
5564 MonoClass
*klass
= t1
->data
.klass
;
5566 * Dynamic classes must not be hashed on their type since it can change
5567 * during runtime. For example, if we hash a reference type that is
5568 * later made into a valuetype.
5570 * This is specially problematic with generic instances since they are
5571 * inserted in a bunch of hash tables before been finished.
5573 if (image_is_dynamic (m_class_get_image (klass
)))
5574 return (t1
->byref
<< 6) | mono_metadata_str_hash (m_class_get_name (klass
));
5575 return ((hash
<< 5) - hash
) ^ mono_metadata_str_hash (m_class_get_name (klass
));
5578 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (t1
->data
.type
);
5579 case MONO_TYPE_ARRAY
:
5580 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (m_class_get_byval_arg (t1
->data
.array
->eklass
));
5581 case MONO_TYPE_GENERICINST
:
5582 return ((hash
<< 5) - hash
) ^ mono_generic_class_hash (t1
->data
.generic_class
);
5584 case MONO_TYPE_MVAR
:
5585 return ((hash
<< 5) - hash
) ^ mono_metadata_generic_param_hash (t1
->data
.generic_param
);
5592 mono_metadata_generic_param_hash (MonoGenericParam
*p
)
5595 MonoGenericParamInfo
*info
;
5597 hash
= (mono_generic_param_num (p
) << 2);
5598 if (p
->gshared_constraint
)
5599 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (p
->gshared_constraint
);
5600 info
= mono_generic_param_info (p
);
5601 /* Can't hash on the owner klass/method, since those might not be set when this is called */
5602 if (!p
->owner
->is_anonymous
)
5603 hash
= ((hash
<< 5) - hash
) ^ info
->token
;
5608 mono_metadata_generic_param_equal_internal (MonoGenericParam
*p1
, MonoGenericParam
*p2
, gboolean signature_only
)
5612 if (mono_generic_param_num (p1
) != mono_generic_param_num (p2
))
5614 if (p1
->gshared_constraint
&& p2
->gshared_constraint
) {
5615 if (!mono_metadata_type_equal (p1
->gshared_constraint
, p2
->gshared_constraint
))
5618 if (p1
->gshared_constraint
!= p2
->gshared_constraint
)
5623 * We have to compare the image as well because if we didn't,
5624 * the generic_inst_cache lookup wouldn't care about the image
5625 * of generic params, so what could happen is that a generic
5626 * inst with params from image A is put into the cache, then
5627 * image B gets that generic inst from the cache, image A is
5628 * unloaded, so the inst is deleted, but image B still retains
5631 if (mono_generic_param_owner (p1
) == mono_generic_param_owner (p2
))
5635 * If `signature_only' is true, we're comparing two (method) signatures.
5636 * In this case, the owner of two type parameters doesn't need to match.
5639 return signature_only
;
5643 mono_metadata_generic_param_equal (MonoGenericParam
*p1
, MonoGenericParam
*p2
)
5645 return mono_metadata_generic_param_equal_internal (p1
, p2
, TRUE
);
5649 mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
)
5653 if (mono_class_is_ginst (c1
) && mono_class_is_ginst (c2
))
5654 return _mono_metadata_generic_class_equal (mono_class_get_generic_class (c1
), mono_class_get_generic_class (c2
), signature_only
);
5655 if (mono_class_is_ginst (c1
) && mono_class_is_gtd (c2
))
5656 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c1
), c2
, signature_only
);
5657 if (mono_class_is_gtd (c1
) && mono_class_is_ginst (c2
))
5658 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c2
), c1
, signature_only
);
5659 MonoType
*c1_type
= m_class_get_byval_arg (c1
);
5660 MonoType
*c2_type
= m_class_get_byval_arg (c2
);
5661 if ((c1_type
->type
== MONO_TYPE_VAR
) && (c2_type
->type
== MONO_TYPE_VAR
))
5662 return mono_metadata_generic_param_equal_internal (
5663 c1_type
->data
.generic_param
, c2_type
->data
.generic_param
, signature_only
);
5664 if ((c1_type
->type
== MONO_TYPE_MVAR
) && (c2_type
->type
== MONO_TYPE_MVAR
))
5665 return mono_metadata_generic_param_equal_internal (
5666 c1_type
->data
.generic_param
, c2_type
->data
.generic_param
, signature_only
);
5667 if (signature_only
&&
5668 (c1_type
->type
== MONO_TYPE_SZARRAY
) && (c2_type
->type
== MONO_TYPE_SZARRAY
))
5669 return mono_metadata_class_equal (c1_type
->data
.klass
, c2_type
->data
.klass
, signature_only
);
5670 if (signature_only
&&
5671 (c1_type
->type
== MONO_TYPE_ARRAY
) && (c2_type
->type
== MONO_TYPE_ARRAY
))
5672 return do_mono_metadata_type_equal (c1_type
, c2_type
, signature_only
);
5677 mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
)
5679 gpointer iter1
= 0, iter2
= 0;
5683 if (s1
->call_convention
!= s2
->call_convention
)
5685 if (s1
->sentinelpos
!= s2
->sentinelpos
)
5687 if (s1
->hasthis
!= s2
->hasthis
)
5689 if (s1
->explicit_this
!= s2
->explicit_this
)
5691 if (! do_mono_metadata_type_equal (s1
->ret
, s2
->ret
, signature_only
))
5693 if (s1
->param_count
!= s2
->param_count
)
5697 MonoType
*t1
= mono_signature_get_params_internal (s1
, &iter1
);
5698 MonoType
*t2
= mono_signature_get_params_internal (s2
, &iter2
);
5700 if (t1
== NULL
|| t2
== NULL
)
5702 if (! do_mono_metadata_type_equal (t1
, t2
, signature_only
))
5708 mono_metadata_custom_modifiers_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
5711 // The CLI itself shall treat required and optional modifiers in the same manner.
5712 // Two signatures that differ only by the addition of a custom modifier
5713 // (required or optional) shall not be considered to match.
5714 int count
= mono_type_custom_modifier_count (t1
);
5715 if (count
!= mono_type_custom_modifier_count (t2
))
5718 for (int i
=0; i
< count
; i
++) {
5719 // FIXME: propagate error to caller
5721 gboolean cm1_required
, cm2_required
;
5723 MonoType
*cm1_type
= mono_type_get_custom_modifier (t1
, i
, &cm1_required
, error
);
5724 mono_error_assert_ok (error
);
5725 MonoType
*cm2_type
= mono_type_get_custom_modifier (t2
, i
, &cm2_required
, error
);
5726 mono_error_assert_ok (error
);
5728 if (cm1_required
!= cm2_required
)
5731 if (!do_mono_metadata_type_equal (cm1_type
, cm2_type
, signature_only
))
5738 * mono_metadata_type_equal:
5741 * @signature_only: If true, treat ginsts as equal which are instantiated separately but have equal positional value
5743 * Determine if @t1 and @t2 represent the same type.
5744 * Returns: #TRUE if @t1 and @t2 are equal.
5747 do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
5749 if (t1
->type
!= t2
->type
|| t1
->byref
!= t2
->byref
)
5752 gboolean cmod_reject
= FALSE
;
5754 if (t1
->has_cmods
!= t2
->has_cmods
)
5756 else if (t1
->has_cmods
&& t2
->has_cmods
) {
5757 cmod_reject
= !mono_metadata_custom_modifiers_equal (t1
, t2
, signature_only
);
5760 gboolean result
= FALSE
;
5763 case MONO_TYPE_VOID
:
5764 case MONO_TYPE_BOOLEAN
:
5765 case MONO_TYPE_CHAR
:
5776 case MONO_TYPE_STRING
:
5779 case MONO_TYPE_OBJECT
:
5780 case MONO_TYPE_TYPEDBYREF
:
5783 case MONO_TYPE_VALUETYPE
:
5784 case MONO_TYPE_CLASS
:
5785 case MONO_TYPE_SZARRAY
:
5786 result
= mono_metadata_class_equal (t1
->data
.klass
, t2
->data
.klass
, signature_only
);
5789 result
= do_mono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
, signature_only
);
5791 case MONO_TYPE_ARRAY
:
5792 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
5795 result
= mono_metadata_class_equal (t1
->data
.array
->eklass
, t2
->data
.array
->eklass
, signature_only
);
5797 case MONO_TYPE_GENERICINST
:
5798 result
= _mono_metadata_generic_class_equal (
5799 t1
->data
.generic_class
, t2
->data
.generic_class
, signature_only
);
5802 result
= mono_metadata_generic_param_equal_internal (
5803 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
5805 case MONO_TYPE_MVAR
:
5806 result
= mono_metadata_generic_param_equal_internal (
5807 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
5809 case MONO_TYPE_FNPTR
:
5810 result
= mono_metadata_fnptr_equal (t1
->data
.method
, t2
->data
.method
, signature_only
);
5813 g_error ("implement type compare for %0x!", t1
->type
);
5817 return result
&& !cmod_reject
;
5821 * mono_metadata_type_equal:
5824 mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
5826 return do_mono_metadata_type_equal (t1
, t2
, FALSE
);
5830 * mono_metadata_type_equal_full:
5832 * \param t2 another type
5833 * \param signature_only if signature only comparison should be made
5835 * Determine if \p t1 and \p t2 are signature compatible if \p signature_only is TRUE, otherwise
5836 * behaves the same way as mono_metadata_type_equal.
5837 * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
5838 * \returns TRUE if \p t1 and \p t2 are equal taking \p signature_only into account.
5841 mono_metadata_type_equal_full (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
5843 return do_mono_metadata_type_equal (t1
, t2
, signature_only
);
5847 * mono_metadata_signature_equal:
5848 * \param sig1 a signature
5849 * \param sig2 another signature
5851 * Determine if \p sig1 and \p sig2 represent the same signature, with the
5852 * same number of arguments and the same types.
5853 * \returns TRUE if \p sig1 and \p sig2 are equal.
5856 mono_metadata_signature_equal (MonoMethodSignature
*sig1
, MonoMethodSignature
*sig2
)
5860 if (sig1
->hasthis
!= sig2
->hasthis
|| sig1
->param_count
!= sig2
->param_count
)
5863 if (sig1
->generic_param_count
!= sig2
->generic_param_count
)
5867 * We're just comparing the signatures of two methods here:
5869 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
5870 * U and V are equal here.
5872 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
5875 for (i
= 0; i
< sig1
->param_count
; i
++) {
5876 MonoType
*p1
= sig1
->params
[i
];
5877 MonoType
*p2
= sig2
->params
[i
];
5879 /* if (p1->attrs != p2->attrs)
5882 if (!do_mono_metadata_type_equal (p1
, p2
, TRUE
))
5886 if (!do_mono_metadata_type_equal (sig1
->ret
, sig2
->ret
, TRUE
))
5892 mono_type_get_custom_modifier (const MonoType
*ty
, uint8_t idx
, gboolean
*required
, MonoError
*error
)
5894 g_assert (ty
->has_cmods
);
5895 if (mono_type_is_aggregate_mods (ty
)) {
5896 MonoAggregateModContainer
*amods
= mono_type_get_amods (ty
);
5897 g_assert (idx
< amods
->count
);
5898 MonoSingleCustomMod
*cmod
= &amods
->modifiers
[idx
];
5900 *required
= !!cmod
->required
;
5903 MonoCustomModContainer
*cmods
= mono_type_get_cmods (ty
);
5904 g_assert (idx
< cmods
->count
);
5905 MonoCustomMod
*cmod
= &cmods
->modifiers
[idx
];
5907 *required
= !!cmod
->required
;
5908 MonoImage
*image
= cmods
->image
;
5909 uint32_t token
= cmod
->token
;
5910 return mono_type_get_checked (image
, token
, NULL
, error
);
5916 * mono_metadata_type_dup:
5917 * \param image image to alloc memory from
5918 * \param original type to duplicate
5919 * \returns copy of type allocated from the image's mempool (or from the heap, if \p image is null).
5922 mono_metadata_type_dup (MonoImage
*image
, const MonoType
*o
)
5924 return mono_metadata_type_dup_with_cmods (image
, o
, o
);
5928 deep_type_dup_fixup (MonoImage
*image
, MonoType
*r
, const MonoType
*o
);
5931 custom_modifier_copy (MonoAggregateModContainer
*dest
, uint8_t dest_offset
, const MonoType
*source
)
5933 if (mono_type_is_aggregate_mods (source
)) {
5934 MonoAggregateModContainer
*src_cmods
= mono_type_get_amods (source
);
5935 memcpy (&dest
->modifiers
[dest_offset
], &src_cmods
->modifiers
[0], src_cmods
->count
* sizeof (MonoSingleCustomMod
));
5936 dest_offset
+= src_cmods
->count
;
5938 MonoCustomModContainer
*src_cmods
= mono_type_get_cmods (source
);
5939 for (int i
= 0; i
< src_cmods
->count
; i
++) {
5940 ERROR_DECL (error
); // XXX FIXME: AK - propagate the error to the caller.
5941 MonoSingleCustomMod
*cmod
= &dest
->modifiers
[dest_offset
++];
5942 cmod
->type
= mono_type_get_checked (src_cmods
->image
, src_cmods
->modifiers
[i
].token
, NULL
, error
);
5943 mono_error_assert_ok (error
);
5944 cmod
->required
= src_cmods
->modifiers
[i
].required
;
5950 /* makes a dup of 'o' but also appends the custom modifiers from 'cmods_source' */
5952 do_metadata_type_dup_append_cmods (MonoImage
*image
, const MonoType
*o
, const MonoType
*cmods_source
)
5954 g_assert (o
!= cmods_source
);
5955 g_assert (o
->has_cmods
);
5956 g_assert (cmods_source
->has_cmods
);
5957 if (!mono_type_is_aggregate_mods (o
) &&
5958 !mono_type_is_aggregate_mods (cmods_source
) &&
5959 mono_type_get_cmods (o
)->image
== mono_type_get_cmods (cmods_source
)->image
) {
5960 /* the uniform case: all the cmods are from the same image. */
5961 MonoCustomModContainer
*o_cmods
= mono_type_get_cmods (o
);
5962 MonoCustomModContainer
*extra_cmods
= mono_type_get_cmods (cmods_source
);
5963 uint8_t total_cmods
= o_cmods
->count
+ extra_cmods
->count
;
5964 gboolean aggregate
= FALSE
;
5965 size_t sizeof_dup
= mono_sizeof_type_with_mods (total_cmods
, aggregate
);
5966 MonoType
*r
= image
? (MonoType
*)mono_image_alloc0 (image
, sizeof_dup
) : (MonoType
*)g_malloc0 (sizeof_dup
);
5968 mono_type_with_mods_init (r
, total_cmods
, aggregate
);
5970 /* copy the original type o, not including its modifiers */
5971 memcpy (r
, o
, mono_sizeof_type_with_mods (0, FALSE
));
5972 deep_type_dup_fixup (image
, r
, o
);
5974 /* The modifier order matters to Roslyn, they expect the extra cmods to come first:
5976 * Suppose we substitute 'int32 modopt(IsLong)' for 'T' in 'void Test
5977 * (T modopt(IsConst))'. Roslyn expects the result to be 'void Test
5978 * (int32 modopt(IsLong) modopt(IsConst))'.
5980 * but! cmods are encoded in IL in reverse order, so 'int32 modopt(IsConst) modopt(IsLong)' is
5981 * encoded as `cmod_opt [typeref IsLong] cmod_opt [typeref IsConst] I4`
5982 * so in our array, extra_cmods (IsLong) come first, followed by o_cmods (IsConst)
5984 * (Here 'o' is 'int32 modopt(IsLong)' and cmods_source is 'T modopt(IsConst)')
5986 /* append the modifiers from cmods_source and o */
5987 MonoCustomModContainer
*r_container
= mono_type_get_cmods (r
);
5988 uint8_t dest_offset
= 0;
5989 r_container
->image
= extra_cmods
->image
;
5991 memcpy (&r_container
->modifiers
[dest_offset
], &o_cmods
->modifiers
[0], o_cmods
->count
* sizeof (MonoCustomMod
));
5992 dest_offset
+= o_cmods
->count
;
5993 memcpy (&r_container
->modifiers
[dest_offset
], &extra_cmods
->modifiers
[0], extra_cmods
->count
* sizeof (MonoCustomMod
));
5994 dest_offset
+= extra_cmods
->count
;
5995 g_assert (dest_offset
== total_cmods
);
5999 /* The aggregate case: either o_cmods or extra_cmods has aggregate cmods, or they're both simple but from different images. */
6000 uint8_t total_cmods
= 0;
6001 total_cmods
+= mono_type_custom_modifier_count (o
);
6002 total_cmods
+= mono_type_custom_modifier_count (cmods_source
);
6004 gboolean aggregate
= TRUE
;
6005 size_t sizeof_dup
= mono_sizeof_type_with_mods (total_cmods
, aggregate
);
6007 /* FIXME: if image, and the images of the custom modifiers from
6008 * o and cmods_source are all different, we need an image
6010 MonoType
*r
= image
? (MonoType
*)mono_image_alloc0 (image
, sizeof_dup
) : (MonoType
*)g_malloc0 (sizeof_dup
);
6012 mono_type_with_mods_init (r
, total_cmods
, aggregate
);
6014 memcpy (r
, o
, mono_sizeof_type_with_mods (0, FALSE
));
6015 deep_type_dup_fixup (image
, r
, o
);
6017 /* Try not to blow up the stack. See comment on
6018 * MONO_MAX_EXPECTED_CMODS. Since here we're appending all the
6019 * mods together, it's possible we'll end up with more than the
6020 * maximum allowed. If that ever happens in practice, we
6021 * should redefine the bound and possibly make this function
6022 * fail dynamically instead of asserting.
6024 g_assert (total_cmods
< MONO_MAX_EXPECTED_CMODS
);
6025 size_t r_container_size
= mono_sizeof_aggregate_modifiers (total_cmods
);
6026 MonoAggregateModContainer
*r_container_candidate
= g_alloca (r_container_size
);
6027 memset (r_container_candidate
, 0, r_container_size
);
6028 uint8_t dest_offset
= 0;
6030 dest_offset
= custom_modifier_copy (r_container_candidate
, dest_offset
, o
);
6031 dest_offset
= custom_modifier_copy (r_container_candidate
, dest_offset
, cmods_source
);
6032 g_assert (dest_offset
== total_cmods
);
6033 r_container_candidate
->count
= total_cmods
;
6035 mono_type_set_amods (r
, mono_metadata_get_canonical_aggregate_modifiers (r_container_candidate
));
6042 * Works the same way as mono_metadata_type_dup but pick cmods from @cmods_source
6045 mono_metadata_type_dup_with_cmods (MonoImage
*image
, const MonoType
*o
, const MonoType
*cmods_source
)
6047 if (o
->has_cmods
&& o
!= cmods_source
&& cmods_source
->has_cmods
) {
6048 return do_metadata_type_dup_append_cmods (image
, o
, cmods_source
);
6053 /* if we get here, either o and cmods_source alias, or else exactly one of them has cmods. */
6055 uint8_t num_mods
= MAX (mono_type_custom_modifier_count (o
), mono_type_custom_modifier_count (cmods_source
));
6056 gboolean aggregate
= mono_type_is_aggregate_mods (o
) || mono_type_is_aggregate_mods (cmods_source
);
6057 size_t sizeof_r
= mono_sizeof_type_with_mods (num_mods
, aggregate
);
6059 r
= image
? (MonoType
*)mono_image_alloc0 (image
, sizeof_r
) : (MonoType
*)g_malloc0 (sizeof_r
);
6061 if (cmods_source
->has_cmods
) {
6062 /* FIXME: if it's aggregate what do we assert here? */
6063 g_assert (!image
|| (!aggregate
&& image
== mono_type_get_cmods (cmods_source
)->image
));
6064 memcpy (r
, cmods_source
, mono_sizeof_type (cmods_source
));
6067 memcpy (r
, o
, mono_sizeof_type (o
));
6069 /* reset custom mod count and aggregateness to be correct. */
6070 mono_type_with_mods_init (r
, num_mods
, aggregate
);
6072 mono_type_set_amods (r
, mono_type_is_aggregate_mods (o
) ? mono_type_get_amods (o
) : mono_type_get_amods (cmods_source
));
6073 deep_type_dup_fixup (image
, r
, o
);
6079 deep_type_dup_fixup (MonoImage
*image
, MonoType
*r
, const MonoType
*o
)
6081 if (o
->type
== MONO_TYPE_PTR
) {
6082 r
->data
.type
= mono_metadata_type_dup (image
, o
->data
.type
);
6083 } else if (o
->type
== MONO_TYPE_ARRAY
) {
6084 r
->data
.array
= mono_dup_array_type (image
, o
->data
.array
);
6085 } else if (o
->type
== MONO_TYPE_FNPTR
) {
6086 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
6087 r
->data
.method
= mono_metadata_signature_deep_dup (image
, o
->data
.method
);
6092 * mono_signature_hash:
6095 mono_signature_hash (MonoMethodSignature
*sig
)
6097 guint i
, res
= sig
->ret
->type
;
6099 for (i
= 0; i
< sig
->param_count
; i
++)
6100 res
= (res
<< 5) - res
+ mono_type_hash (sig
->params
[i
]);
6106 * mono_metadata_encode_value:
6107 * @value: value to encode
6108 * @buf: buffer where to write the compressed representation
6109 * @endbuf: pointer updated to point at the end of the encoded output
6111 * Encodes the value @value in the compressed representation used
6112 * in metadata and stores the result in @buf. @buf needs to be big
6113 * enough to hold the data (4 bytes).
6116 mono_metadata_encode_value (guint32 value
, char *buf
, char **endbuf
)
6122 else if (value
< 0x4000) {
6123 p
[0] = 0x80 | (value
>> 8);
6124 p
[1] = value
& 0xff;
6127 p
[0] = (value
>> 24) | 0xc0;
6128 p
[1] = (value
>> 16) & 0xff;
6129 p
[2] = (value
>> 8) & 0xff;
6130 p
[3] = value
& 0xff;
6138 * mono_metadata_field_info:
6139 * \param meta the Image the field is defined in
6140 * \param index the index in the field table representing the field
6141 * \param offset a pointer to an integer where to store the offset that may have been specified for the field in a FieldLayout table
6142 * \param rva a pointer to the RVA of the field data in the image that may have been defined in a \c FieldRVA table
6143 * \param marshal_spec a pointer to the marshal spec that may have been defined for the field in a \c FieldMarshal table.
6145 * Gather info for field \p index that may have been defined in the \c FieldLayout,
6146 * \c FieldRVA and \c FieldMarshal tables.
6147 * Either of \p offset, \p rva and \p marshal_spec can be NULL if you're not interested
6151 mono_metadata_field_info (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
6152 MonoMarshalSpec
**marshal_spec
)
6154 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, FALSE
);
6158 mono_metadata_field_info_with_mempool (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
6159 MonoMarshalSpec
**marshal_spec
)
6161 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, TRUE
);
6165 mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
6166 MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
)
6168 MonoTableInfo
*tdef
;
6171 loc
.idx
= index
+ 1;
6172 if (meta
->uncompressed_metadata
)
6173 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
6176 tdef
= &meta
->tables
[MONO_TABLE_FIELDLAYOUT
];
6178 loc
.col_idx
= MONO_FIELD_LAYOUT_FIELD
;
6181 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
6182 *offset
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_LAYOUT_OFFSET
);
6184 *offset
= (guint32
)-1;
6188 tdef
= &meta
->tables
[MONO_TABLE_FIELDRVA
];
6190 loc
.col_idx
= MONO_FIELD_RVA_FIELD
;
6193 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
6195 * LAMESPEC: There is no signature, no nothing, just the raw data.
6197 *rva
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_RVA_RVA
);
6205 if ((p
= mono_metadata_get_marshal_info (meta
, index
, TRUE
))) {
6206 *marshal_spec
= mono_metadata_parse_marshal_spec_full (alloc_from_image
? meta
: NULL
, meta
, p
);
6213 * mono_metadata_get_constant_index:
6214 * \param meta the Image the field is defined in
6215 * \param index the token that may have a row defined in the constants table
6216 * \param hint possible position for the row
6218 * \p token must be a \c FieldDef, \c ParamDef or \c PropertyDef token.
6220 * \returns the index into the \c Constants table or 0 if not found.
6223 mono_metadata_get_constant_index (MonoImage
*meta
, guint32 token
, guint32 hint
)
6225 MonoTableInfo
*tdef
;
6227 guint32 index
= mono_metadata_token_index (token
);
6229 tdef
= &meta
->tables
[MONO_TABLE_CONSTANT
];
6230 index
<<= MONO_HASCONSTANT_BITS
;
6231 switch (mono_metadata_token_table (token
)) {
6232 case MONO_TABLE_FIELD
:
6233 index
|= MONO_HASCONSTANT_FIEDDEF
;
6235 case MONO_TABLE_PARAM
:
6236 index
|= MONO_HASCONSTANT_PARAM
;
6238 case MONO_TABLE_PROPERTY
:
6239 index
|= MONO_HASCONSTANT_PROPERTY
;
6242 g_warning ("Not a valid token for the constant table: 0x%08x", token
);
6246 loc
.col_idx
= MONO_CONSTANT_PARENT
;
6249 /* FIXME: Index translation */
6251 if ((hint
> 0) && (hint
< tdef
->rows
) && (mono_metadata_decode_row_col (tdef
, hint
- 1, MONO_CONSTANT_PARENT
) == index
))
6254 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
6255 return loc
.result
+ 1;
6261 * mono_metadata_events_from_typedef:
6262 * \param meta metadata context
6263 * \param index 0-based index (in the \c TypeDef table) describing a type
6264 * \returns the 0-based index in the \c Event table for the events in the
6265 * type. The last event that belongs to the type (plus 1) is stored
6266 * in the \p end_idx pointer.
6269 mono_metadata_events_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
6273 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_EVENTMAP
];
6281 loc
.col_idx
= MONO_EVENT_MAP_PARENT
;
6282 loc
.idx
= index
+ 1;
6284 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6287 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_EVENT_MAP_EVENTLIST
);
6288 if (loc
.result
+ 1 < tdef
->rows
) {
6289 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_EVENT_MAP_EVENTLIST
) - 1;
6291 end
= meta
->tables
[MONO_TABLE_EVENT
].rows
;
6299 * mono_metadata_methods_from_event:
6300 * \param meta metadata context
6301 * \param index 0-based index (in the \c Event table) describing a event
6302 * \returns the 0-based index in the \c MethodDef table for the methods in the
6303 * event. The last method that belongs to the event (plus 1) is stored
6304 * in the \p end_idx pointer.
6307 mono_metadata_methods_from_event (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
6311 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
6312 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
6318 if (meta
->uncompressed_metadata
)
6319 index
= search_ptr_table (meta
, MONO_TABLE_EVENT_POINTER
, index
+ 1) - 1;
6322 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
6323 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
; /* Method association coded index */
6325 if (!mono_binary_search (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
6330 * We may end up in the middle of the rows...
6333 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
6339 while (end
< msemt
->rows
) {
6340 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
6341 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
6350 * mono_metadata_properties_from_typedef:
6351 * \param meta metadata context
6352 * \param index 0-based index (in the \c TypeDef table) describing a type
6353 * \returns the 0-based index in the \c Property table for the properties in the
6354 * type. The last property that belongs to the type (plus 1) is stored
6355 * in the \p end_idx pointer.
6358 mono_metadata_properties_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
6362 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_PROPERTYMAP
];
6370 loc
.col_idx
= MONO_PROPERTY_MAP_PARENT
;
6371 loc
.idx
= index
+ 1;
6373 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6376 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_PROPERTY_MAP_PROPERTY_LIST
);
6377 if (loc
.result
+ 1 < tdef
->rows
) {
6378 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_PROPERTY_MAP_PROPERTY_LIST
) - 1;
6380 end
= meta
->tables
[MONO_TABLE_PROPERTY
].rows
;
6388 * mono_metadata_methods_from_property:
6389 * \param meta metadata context
6390 * \param index 0-based index (in the \c PropertyDef table) describing a property
6391 * \returns the 0-based index in the \c MethodDef table for the methods in the
6392 * property. The last method that belongs to the property (plus 1) is stored
6393 * in the \p end_idx pointer.
6396 mono_metadata_methods_from_property (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
6400 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
6401 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
6407 if (meta
->uncompressed_metadata
)
6408 index
= search_ptr_table (meta
, MONO_TABLE_PROPERTY_POINTER
, index
+ 1) - 1;
6411 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
6412 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
; /* Method association coded index */
6414 if (!mono_binary_search (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
6419 * We may end up in the middle of the rows...
6422 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
6428 while (end
< msemt
->rows
) {
6429 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
6430 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
6439 * mono_metadata_implmap_from_method:
6442 mono_metadata_implmap_from_method (MonoImage
*meta
, guint32 method_idx
)
6445 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_IMPLMAP
];
6450 /* No index translation seems to be needed */
6453 loc
.col_idx
= MONO_IMPLMAP_MEMBER
;
6454 loc
.idx
= ((method_idx
+ 1) << MONO_MEMBERFORWD_BITS
) | MONO_MEMBERFORWD_METHODDEF
;
6456 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6459 return loc
.result
+ 1;
6463 * mono_type_create_from_typespec:
6464 * \param image context where the image is created
6465 * \param type_spec typespec token
6466 * \deprecated use \c mono_type_create_from_typespec_checked that has proper error handling
6468 * Creates a \c MonoType representing the \c TypeSpec indexed by the \p type_spec
6472 mono_type_create_from_typespec (MonoImage
*image
, guint32 type_spec
)
6475 MonoType
*type
= mono_type_create_from_typespec_checked (image
, type_spec
, error
);
6477 g_error ("Could not create typespec %x due to %s", type_spec
, mono_error_get_message (error
));
6482 mono_type_create_from_typespec_checked (MonoImage
*image
, guint32 type_spec
, MonoError
*error
)
6485 guint32 idx
= mono_metadata_token_index (type_spec
);
6487 guint32 cols
[MONO_TYPESPEC_SIZE
];
6489 MonoType
*type
, *type2
;
6493 type
= (MonoType
*)mono_conc_hashtable_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
6497 t
= &image
->tables
[MONO_TABLE_TYPESPEC
];
6499 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPESPEC_SIZE
);
6500 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_TYPESPEC_SIGNATURE
]);
6502 if (!mono_verifier_verify_typespec_signature (image
, cols
[MONO_TYPESPEC_SIGNATURE
], type_spec
, error
))
6505 mono_metadata_decode_value (ptr
, &ptr
);
6507 type
= mono_metadata_parse_type_checked (image
, NULL
, 0, TRUE
, ptr
, &ptr
, error
);
6511 type2
= mono_metadata_type_dup (image
, type
);
6512 mono_metadata_free_type (type
);
6514 mono_image_lock (image
);
6516 /* We might leak some data in the image mempool if found */
6517 type
= (MonoType
*)mono_conc_hashtable_insert (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
), type2
);
6521 mono_image_unlock (image
);
6528 mono_image_strndup (MonoImage
*image
, const char *data
, guint len
)
6532 return g_strndup (data
, len
);
6533 res
= (char *)mono_image_alloc (image
, len
+ 1);
6534 memcpy (res
, data
, len
);
6540 * mono_metadata_parse_marshal_spec:
6543 mono_metadata_parse_marshal_spec (MonoImage
*image
, const char *ptr
)
6545 return mono_metadata_parse_marshal_spec_full (NULL
, image
, ptr
);
6549 * If IMAGE is non-null, memory will be allocated from its mempool, otherwise it will be allocated using malloc.
6550 * PARENT_IMAGE is the image containing the marshal spec.
6553 mono_metadata_parse_marshal_spec_full (MonoImage
*image
, MonoImage
*parent_image
, const char *ptr
)
6555 MonoMarshalSpec
*res
;
6557 const char *start
= ptr
;
6559 /* fixme: this is incomplete, but I cant find more infos in the specs */
6562 res
= (MonoMarshalSpec
*)mono_image_alloc0 (image
, sizeof (MonoMarshalSpec
));
6564 res
= g_new0 (MonoMarshalSpec
, 1);
6566 len
= mono_metadata_decode_value (ptr
, &ptr
);
6567 res
->native
= (MonoMarshalNative
)*ptr
++;
6569 if (res
->native
== MONO_NATIVE_LPARRAY
) {
6570 res
->data
.array_data
.param_num
= -1;
6571 res
->data
.array_data
.num_elem
= -1;
6572 res
->data
.array_data
.elem_mult
= -1;
6574 if (ptr
- start
<= len
)
6575 res
->data
.array_data
.elem_type
= (MonoMarshalNative
)*ptr
++;
6576 if (ptr
- start
<= len
)
6577 res
->data
.array_data
.param_num
= mono_metadata_decode_value (ptr
, &ptr
);
6578 if (ptr
- start
<= len
)
6579 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
6580 if (ptr
- start
<= len
) {
6582 * LAMESPEC: Older spec versions say this parameter comes before
6583 * num_elem. Never spec versions don't talk about elem_mult at
6584 * all, but csc still emits it, and it is used to distinguish
6585 * between param_num being 0, and param_num being omitted.
6586 * So if (param_num == 0) && (num_elem > 0), then
6587 * elem_mult == 0 -> the array size is num_elem
6588 * elem_mult == 1 -> the array size is @param_num + num_elem
6590 res
->data
.array_data
.elem_mult
= mono_metadata_decode_value (ptr
, &ptr
);
6594 if (res
->native
== MONO_NATIVE_BYVALTSTR
) {
6595 if (ptr
- start
<= len
)
6596 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
6599 if (res
->native
== MONO_NATIVE_BYVALARRAY
) {
6600 if (ptr
- start
<= len
)
6601 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
6604 if (res
->native
== MONO_NATIVE_CUSTOM
) {
6605 /* skip unused type guid */
6606 len
= mono_metadata_decode_value (ptr
, &ptr
);
6608 /* skip unused native type name */
6609 len
= mono_metadata_decode_value (ptr
, &ptr
);
6611 /* read custom marshaler type name */
6612 len
= mono_metadata_decode_value (ptr
, &ptr
);
6613 res
->data
.custom_data
.custom_name
= mono_image_strndup (image
, ptr
, len
);
6615 /* read cookie string */
6616 len
= mono_metadata_decode_value (ptr
, &ptr
);
6617 res
->data
.custom_data
.cookie
= mono_image_strndup (image
, ptr
, len
);
6618 res
->data
.custom_data
.image
= parent_image
;
6621 if (res
->native
== MONO_NATIVE_SAFEARRAY
) {
6622 res
->data
.safearray_data
.elem_type
= (MonoMarshalVariant
)0;
6623 res
->data
.safearray_data
.num_elem
= 0;
6624 if (ptr
- start
<= len
)
6625 res
->data
.safearray_data
.elem_type
= (MonoMarshalVariant
)*ptr
++;
6626 if (ptr
- start
<= len
)
6627 res
->data
.safearray_data
.num_elem
= *ptr
++;
6633 * mono_metadata_free_marshal_spec:
6636 mono_metadata_free_marshal_spec (MonoMarshalSpec
*spec
)
6641 if (spec
->native
== MONO_NATIVE_CUSTOM
) {
6642 g_free (spec
->data
.custom_data
.custom_name
);
6643 g_free (spec
->data
.custom_data
.cookie
);
6649 * mono_type_to_unmanaged:
6650 * The value pointed to by \p conv will contain the kind of marshalling required for this
6651 * particular type one of the \c MONO_MARSHAL_CONV_ enumeration values.
6652 * \returns A \c MonoMarshalNative enumeration value (<code>MONO_NATIVE_</code>) value
6653 * describing the underlying native reprensetation of the type.
6655 guint32
// FIXMEcxx MonoMarshalNative
6656 mono_type_to_unmanaged (MonoType
*type
, MonoMarshalSpec
*mspec
, gboolean as_field
,
6657 gboolean unicode
, MonoMarshalConv
*conv
)
6659 MonoMarshalConv dummy_conv
;
6665 *conv
= MONO_MARSHAL_CONV_NONE
;
6668 return MONO_NATIVE_UINT
;
6672 case MONO_TYPE_BOOLEAN
:
6674 switch (mspec
->native
) {
6675 case MONO_NATIVE_VARIANTBOOL
:
6676 *conv
= MONO_MARSHAL_CONV_BOOL_VARIANTBOOL
;
6677 return MONO_NATIVE_VARIANTBOOL
;
6678 case MONO_NATIVE_BOOLEAN
:
6679 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
6680 return MONO_NATIVE_BOOLEAN
;
6681 case MONO_NATIVE_I1
:
6682 case MONO_NATIVE_U1
:
6683 return mspec
->native
;
6685 g_error ("cant marshal bool to native type %02x", mspec
->native
);
6688 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
6689 return MONO_NATIVE_BOOLEAN
;
6690 case MONO_TYPE_CHAR
:
6692 switch (mspec
->native
) {
6693 case MONO_NATIVE_U2
:
6694 case MONO_NATIVE_U1
:
6695 return mspec
->native
;
6697 g_error ("cant marshal char to native type %02x", mspec
->native
);
6700 return unicode
? MONO_NATIVE_U2
: MONO_NATIVE_U1
;
6701 case MONO_TYPE_I1
: return MONO_NATIVE_I1
;
6702 case MONO_TYPE_U1
: return MONO_NATIVE_U1
;
6703 case MONO_TYPE_I2
: return MONO_NATIVE_I2
;
6704 case MONO_TYPE_U2
: return MONO_NATIVE_U2
;
6705 case MONO_TYPE_I4
: return MONO_NATIVE_I4
;
6706 case MONO_TYPE_U4
: return MONO_NATIVE_U4
;
6707 case MONO_TYPE_I8
: return MONO_NATIVE_I8
;
6708 case MONO_TYPE_U8
: return MONO_NATIVE_U8
;
6709 case MONO_TYPE_R4
: return MONO_NATIVE_R4
;
6710 case MONO_TYPE_R8
: return MONO_NATIVE_R8
;
6711 case MONO_TYPE_STRING
:
6713 switch (mspec
->native
) {
6714 case MONO_NATIVE_BSTR
:
6715 *conv
= MONO_MARSHAL_CONV_STR_BSTR
;
6716 return MONO_NATIVE_BSTR
;
6717 case MONO_NATIVE_LPSTR
:
6718 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
6719 return MONO_NATIVE_LPSTR
;
6720 case MONO_NATIVE_LPWSTR
:
6721 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
6722 return MONO_NATIVE_LPWSTR
;
6723 case MONO_NATIVE_LPTSTR
:
6724 *conv
= MONO_MARSHAL_CONV_STR_LPTSTR
;
6725 return MONO_NATIVE_LPTSTR
;
6726 case MONO_NATIVE_ANSIBSTR
:
6727 *conv
= MONO_MARSHAL_CONV_STR_ANSIBSTR
;
6728 return MONO_NATIVE_ANSIBSTR
;
6729 case MONO_NATIVE_TBSTR
:
6730 *conv
= MONO_MARSHAL_CONV_STR_TBSTR
;
6731 return MONO_NATIVE_TBSTR
;
6732 case MONO_NATIVE_UTF8STR
:
6733 *conv
= MONO_MARSHAL_CONV_STR_UTF8STR
;
6734 return MONO_NATIVE_UTF8STR
;
6735 case MONO_NATIVE_BYVALTSTR
:
6737 *conv
= MONO_MARSHAL_CONV_STR_BYVALWSTR
;
6739 *conv
= MONO_MARSHAL_CONV_STR_BYVALSTR
;
6740 return MONO_NATIVE_BYVALTSTR
;
6742 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
);
6746 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
6747 return MONO_NATIVE_LPWSTR
;
6750 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
6751 return MONO_NATIVE_LPSTR
;
6753 case MONO_TYPE_PTR
: return MONO_NATIVE_UINT
;
6754 case MONO_TYPE_VALUETYPE
: /*FIXME*/
6755 if (m_class_is_enumtype (type
->data
.klass
)) {
6756 t
= mono_class_enum_basetype_internal (type
->data
.klass
)->type
;
6759 if (type
->data
.klass
== mono_class_try_get_handleref_class ()){
6760 *conv
= MONO_MARSHAL_CONV_HANDLEREF
;
6761 return MONO_NATIVE_INT
;
6763 return MONO_NATIVE_STRUCT
;
6764 case MONO_TYPE_SZARRAY
:
6765 case MONO_TYPE_ARRAY
:
6767 switch (mspec
->native
) {
6768 case MONO_NATIVE_BYVALARRAY
:
6769 if ((m_class_get_element_class (type
->data
.klass
) == mono_defaults
.char_class
) && !unicode
)
6770 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY
;
6772 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALARRAY
;
6773 return MONO_NATIVE_BYVALARRAY
;
6774 case MONO_NATIVE_SAFEARRAY
:
6775 *conv
= MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
;
6776 return MONO_NATIVE_SAFEARRAY
;
6777 case MONO_NATIVE_LPARRAY
:
6778 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
6779 return MONO_NATIVE_LPARRAY
;
6781 g_error ("cant marshal array as native type %02x", mspec
->native
);
6785 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
6786 return MONO_NATIVE_LPARRAY
;
6787 case MONO_TYPE_I
: return MONO_NATIVE_INT
;
6788 case MONO_TYPE_U
: return MONO_NATIVE_UINT
;
6789 case MONO_TYPE_CLASS
:
6790 case MONO_TYPE_OBJECT
: {
6791 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
6793 switch (mspec
->native
) {
6794 case MONO_NATIVE_STRUCT
:
6795 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
6796 return MONO_NATIVE_STRUCT
;
6797 case MONO_NATIVE_CUSTOM
:
6798 return MONO_NATIVE_CUSTOM
;
6799 case MONO_NATIVE_INTERFACE
:
6800 *conv
= MONO_MARSHAL_CONV_OBJECT_INTERFACE
;
6801 return MONO_NATIVE_INTERFACE
;
6802 case MONO_NATIVE_IDISPATCH
:
6803 *conv
= MONO_MARSHAL_CONV_OBJECT_IDISPATCH
;
6804 return MONO_NATIVE_IDISPATCH
;
6805 case MONO_NATIVE_IUNKNOWN
:
6806 *conv
= MONO_MARSHAL_CONV_OBJECT_IUNKNOWN
;
6807 return MONO_NATIVE_IUNKNOWN
;
6808 case MONO_NATIVE_FUNC
:
6809 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
6810 type
->data
.klass
== mono_defaults
.delegate_class
||
6811 m_class_get_parent (type
->data
.klass
) == mono_defaults
.multicastdelegate_class
)) {
6812 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
6813 return MONO_NATIVE_FUNC
;
6817 g_error ("cant marshal object as native type %02x", mspec
->native
);
6820 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
6821 type
->data
.klass
== mono_defaults
.delegate_class
||
6822 m_class_get_parent (type
->data
.klass
) == mono_defaults
.multicastdelegate_class
)) {
6823 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
6824 return MONO_NATIVE_FUNC
;
6826 if (mono_class_try_get_safehandle_class () && type
->data
.klass
!= NULL
&&
6827 mono_class_is_subclass_of_internal (type
->data
.klass
, mono_class_try_get_safehandle_class (), FALSE
)){
6828 *conv
= MONO_MARSHAL_CONV_SAFEHANDLE
;
6829 return MONO_NATIVE_INT
;
6832 if (t
== MONO_TYPE_CLASS
&& mono_cominterop_is_interface (type
->data
.klass
)){
6833 *conv
= MONO_MARSHAL_CONV_OBJECT_INTERFACE
;
6834 return MONO_NATIVE_INTERFACE
;
6837 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
6838 return MONO_NATIVE_STRUCT
;
6840 case MONO_TYPE_FNPTR
: return MONO_NATIVE_FUNC
;
6841 case MONO_TYPE_GENERICINST
:
6842 type
= m_class_get_byval_arg (type
->data
.generic_class
->container_class
);
6845 case MONO_TYPE_TYPEDBYREF
:
6847 g_error ("type 0x%02x not handled in marshal", t
);
6849 return MONO_NATIVE_MAX
;
6853 * mono_metadata_get_marshal_info:
6856 mono_metadata_get_marshal_info (MonoImage
*meta
, guint32 idx
, gboolean is_field
)
6859 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_FIELDMARSHAL
];
6865 loc
.col_idx
= MONO_FIELD_MARSHAL_PARENT
;
6866 loc
.idx
= ((idx
+ 1) << MONO_HAS_FIELD_MARSHAL_BITS
) | (is_field
? MONO_HAS_FIELD_MARSHAL_FIELDSREF
: MONO_HAS_FIELD_MARSHAL_PARAMDEF
);
6868 /* FIXME: Index translation */
6870 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6873 return mono_metadata_blob_heap (meta
, mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_MARSHAL_NATIVE_TYPE
));
6877 mono_method_from_method_def_or_ref (MonoImage
*m
, guint32 tok
, MonoGenericContext
*context
, MonoError
*error
)
6879 MonoMethod
*result
= NULL
;
6880 guint32 idx
= tok
>> MONO_METHODDEFORREF_BITS
;
6884 switch (tok
& MONO_METHODDEFORREF_MASK
) {
6885 case MONO_METHODDEFORREF_METHODDEF
:
6886 result
= mono_get_method_checked (m
, MONO_TOKEN_METHOD_DEF
| idx
, NULL
, context
, error
);
6888 case MONO_METHODDEFORREF_METHODREF
:
6889 result
= mono_get_method_checked (m
, MONO_TOKEN_MEMBER_REF
| idx
, NULL
, context
, error
);
6892 mono_error_set_bad_image (error
, m
, "Invalid MethodDefOfRef token %x", tok
);
6899 * mono_class_get_overrides_full:
6901 * Compute the method overrides belonging to class @type_token in @overrides, and the number of overrides in @num_overrides.
6905 mono_class_get_overrides_full (MonoImage
*image
, guint32 type_token
, MonoMethod
***overrides
, gint32
*num_overrides
, MonoGenericContext
*generic_context
, MonoError
*error
)
6908 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_METHODIMPL
];
6911 guint32 cols
[MONO_METHODIMPL_SIZE
];
6912 MonoMethod
**result
;
6924 loc
.col_idx
= MONO_METHODIMPL_CLASS
;
6925 loc
.idx
= mono_metadata_token_index (type_token
);
6927 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6933 * We may end up in the middle of the rows...
6936 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_METHODIMPL_CLASS
))
6941 while (end
< tdef
->rows
) {
6942 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, end
, MONO_METHODIMPL_CLASS
))
6948 result
= g_new (MonoMethod
*, num
* 2);
6949 for (i
= 0; i
< num
; ++i
) {
6952 if (!mono_verifier_verify_methodimpl_row (image
, start
+ i
, error
))
6955 mono_metadata_decode_row (tdef
, start
+ i
, cols
, MONO_METHODIMPL_SIZE
);
6956 method
= mono_method_from_method_def_or_ref (image
, cols
[MONO_METHODIMPL_DECLARATION
], generic_context
, error
);
6960 result
[i
* 2] = method
;
6961 method
= mono_method_from_method_def_or_ref (image
, cols
[MONO_METHODIMPL_BODY
], generic_context
, error
);
6965 result
[i
* 2 + 1] = method
;
6968 if (!is_ok (error
)) {
6974 *overrides
= result
;
6976 *num_overrides
= num
;
6981 * mono_guid_to_string:
6983 * Converts a 16 byte Microsoft GUID to the standard string representation.
6986 mono_guid_to_string (const guint8
*guid
)
6988 return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
6989 guid
[3], guid
[2], guid
[1], guid
[0],
6993 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
6997 * mono_guid_to_string_minimal:
6999 * Converts a 16 byte Microsoft GUID to lower case no '-' representation..
7002 mono_guid_to_string_minimal (const guint8
*guid
)
7004 return g_strdup_printf ("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
7005 guid
[3], guid
[2], guid
[1], guid
[0],
7009 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
7012 get_constraints (MonoImage
*image
, int owner
, MonoClass
***constraints
, MonoGenericContainer
*container
, MonoError
*error
)
7014 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
7015 guint32 cols
[MONO_GENPARCONSTRAINT_SIZE
];
7016 guint32 i
, token
, found
;
7017 MonoClass
*klass
, **res
;
7018 GSList
*cons
= NULL
, *tmp
;
7019 MonoGenericContext
*context
= &container
->context
;
7023 *constraints
= NULL
;
7025 for (i
= 0; i
< tdef
->rows
; ++i
) {
7026 mono_metadata_decode_row (tdef
, i
, cols
, MONO_GENPARCONSTRAINT_SIZE
);
7027 if (cols
[MONO_GENPARCONSTRAINT_GENERICPAR
] == owner
) {
7028 token
= mono_metadata_token_from_dor (cols
[MONO_GENPARCONSTRAINT_CONSTRAINT
]);
7029 klass
= mono_class_get_and_inflate_typespec_checked (image
, token
, context
, error
);
7031 g_slist_free (cons
);
7034 cons
= g_slist_append (cons
, klass
);
7037 /* contiguous list finished */
7044 res
= (MonoClass
**)mono_image_alloc0 (image
, sizeof (MonoClass
*) * (found
+ 1));
7045 for (i
= 0, tmp
= cons
; i
< found
; ++i
, tmp
= tmp
->next
) {
7046 res
[i
] = (MonoClass
*)tmp
->data
;
7048 g_slist_free (cons
);
7054 * mono_metadata_get_generic_param_row:
7057 * @token: TypeOrMethodDef token, owner for GenericParam
7058 * @owner: coded token, set on return
7060 * Returns: 1-based row-id in the GenericParam table whose
7061 * owner is @token. 0 if not found.
7064 mono_metadata_get_generic_param_row (MonoImage
*image
, guint32 token
, guint32
*owner
)
7066 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
7073 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPEDEF
)
7074 *owner
= MONO_TYPEORMETHOD_TYPE
;
7075 else if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
7076 *owner
= MONO_TYPEORMETHOD_METHOD
;
7078 g_error ("wrong token %x to get_generic_param_row", token
);
7081 *owner
|= mono_metadata_token_index (token
) << MONO_TYPEORMETHOD_BITS
;
7084 loc
.col_idx
= MONO_GENERICPARAM_OWNER
;
7087 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
7090 /* Find the first entry by searching backwards */
7091 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_GENERICPARAM_OWNER
) == loc
.idx
))
7094 return loc
.result
+ 1;
7098 mono_metadata_has_generic_params (MonoImage
*image
, guint32 token
)
7101 return mono_metadata_get_generic_param_row (image
, token
, &owner
);
7105 * Memory is allocated from IMAGE's mempool.
7108 mono_metadata_load_generic_param_constraints_checked (MonoImage
*image
, guint32 token
,
7109 MonoGenericContainer
*container
, MonoError
*error
)
7112 guint32 start_row
, i
, owner
;
7115 if (! (start_row
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
7117 for (i
= 0; i
< container
->type_argc
; i
++) {
7118 if (!get_constraints (image
, start_row
+ i
, &mono_generic_container_get_param_info (container
, i
)->constraints
, container
, error
)) {
7126 * mono_metadata_load_generic_params:
7128 * Load the type parameters from the type or method definition @token.
7130 * Use this method after parsing a type or method definition to figure out whether it's a generic
7131 * type / method. When parsing a method definition, @parent_container points to the generic container
7132 * of the current class, if any.
7134 * Note: This method does not load the constraints: for typedefs, this has to be done after fully
7135 * creating the type.
7137 * Returns: NULL if @token is not a generic type or method definition or the new generic container.
7139 * LOCKING: Acquires the loader lock
7142 MonoGenericContainer
*
7143 mono_metadata_load_generic_params (MonoImage
*image
, guint32 token
, MonoGenericContainer
*parent_container
, gpointer real_owner
)
7145 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
7146 guint32 cols
[MONO_GENERICPARAM_SIZE
];
7147 guint32 i
, owner
= 0, n
;
7148 MonoGenericContainer
*container
;
7149 MonoGenericParamFull
*params
;
7150 MonoGenericContext
*context
;
7151 gboolean is_method
= mono_metadata_token_table (token
) == MONO_TABLE_METHOD
;
7152 gboolean is_anonymous
= real_owner
== NULL
;
7154 if (!(i
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
7156 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
7159 container
= (MonoGenericContainer
*)mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
7160 container
->is_anonymous
= is_anonymous
;
7162 container
->owner
.image
= image
;
7165 container
->owner
.method
= (MonoMethod
*)real_owner
;
7167 container
->owner
.klass
= (MonoClass
*)real_owner
;
7171 params
= (MonoGenericParamFull
*)g_realloc (params
, sizeof (MonoGenericParamFull
) * n
);
7172 memset (¶ms
[n
- 1], 0, sizeof (MonoGenericParamFull
));
7173 params
[n
- 1].owner
= container
;
7174 params
[n
- 1].num
= cols
[MONO_GENERICPARAM_NUMBER
];
7175 params
[n
- 1].info
.token
= i
| MONO_TOKEN_GENERIC_PARAM
;
7176 params
[n
- 1].info
.flags
= cols
[MONO_GENERICPARAM_FLAGS
];
7177 params
[n
- 1].info
.name
= mono_metadata_string_heap (image
, cols
[MONO_GENERICPARAM_NAME
]);
7178 if (params
[n
- 1].num
!= n
- 1)
7179 g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i
);
7180 if (++i
> tdef
->rows
)
7182 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
7183 } while (cols
[MONO_GENERICPARAM_OWNER
] == owner
);
7185 container
->type_argc
= n
;
7186 container
->type_params
= (MonoGenericParamFull
*)mono_image_alloc0 (image
, sizeof (MonoGenericParamFull
) * n
);
7187 memcpy (container
->type_params
, params
, sizeof (MonoGenericParamFull
) * n
);
7189 container
->parent
= parent_container
;
7192 container
->is_method
= 1;
7194 g_assert (container
->parent
== NULL
|| container
->is_method
);
7196 context
= &container
->context
;
7197 if (container
->is_method
) {
7198 context
->class_inst
= container
->parent
? container
->parent
->context
.class_inst
: NULL
;
7199 context
->method_inst
= mono_get_shared_generic_inst (container
);
7201 context
->class_inst
= mono_get_shared_generic_inst (container
);
7208 mono_get_shared_generic_inst (MonoGenericContainer
*container
)
7210 MonoType
**type_argv
;
7212 MonoGenericInst
*nginst
;
7215 type_argv
= g_new0 (MonoType
*, container
->type_argc
);
7216 helper
= g_new0 (MonoType
, container
->type_argc
);
7218 for (i
= 0; i
< container
->type_argc
; i
++) {
7219 MonoType
*t
= &helper
[i
];
7221 t
->type
= container
->is_method
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
7222 t
->data
.generic_param
= mono_generic_container_get_param (container
, i
);
7227 nginst
= mono_metadata_get_generic_inst (container
->type_argc
, type_argv
);
7236 * mono_type_is_byref:
7237 * \param type the \c MonoType operated on
7238 * \returns TRUE if \p type represents a type passed by reference,
7242 mono_type_is_byref (MonoType
*type
)
7245 MONO_ENTER_GC_UNSAFE
; // FIXME slow
7246 result
= mono_type_is_byref_internal (type
);
7247 MONO_EXIT_GC_UNSAFE
;
7252 * mono_type_get_type:
7253 * \param type the \c MonoType operated on
7254 * \returns the IL type value for \p type. This is one of the \c MonoTypeEnum
7255 * enum members like \c MONO_TYPE_I4 or \c MONO_TYPE_STRING.
7258 mono_type_get_type (MonoType
*type
)
7260 return mono_type_get_type_internal (type
);
7264 * mono_type_get_signature:
7265 * \param type the \c MonoType operated on
7266 * It is only valid to call this function if \p type is a \c MONO_TYPE_FNPTR .
7267 * \returns the \c MonoMethodSignature pointer that describes the signature
7268 * of the function pointer \p type represents.
7270 MonoMethodSignature
*
7271 mono_type_get_signature (MonoType
*type
)
7273 return mono_type_get_signature_internal (type
);
7277 * mono_type_get_class:
7278 * \param type the \c MonoType operated on
7279 * It is only valid to call this function if \p type is a \c MONO_TYPE_CLASS or a
7280 * \c MONO_TYPE_VALUETYPE . For more general functionality, use \c mono_class_from_mono_type_internal,
7282 * \returns the \c MonoClass pointer that describes the class that \p type represents.
7285 mono_type_get_class (MonoType
*type
)
7287 /* FIXME: review the runtime users before adding the assert here */
7288 return mono_type_get_class_internal (type
);
7292 * mono_type_get_array_type:
7293 * \param type the \c MonoType operated on
7294 * It is only valid to call this function if \p type is a \c MONO_TYPE_ARRAY .
7295 * \returns a \c MonoArrayType struct describing the array type that \p type
7296 * represents. The info includes details such as rank, array element type
7297 * and the sizes and bounds of multidimensional arrays.
7300 mono_type_get_array_type (MonoType
*type
)
7302 return mono_type_get_array_type_internal (type
);
7306 * mono_type_get_ptr_type:
7307 * \pararm type the \c MonoType operated on
7308 * It is only valid to call this function if \p type is a \c MONO_TYPE_PTR .
7309 * \returns the \c MonoType pointer that describes the type that \p type
7310 * represents a pointer to.
7313 mono_type_get_ptr_type (MonoType
*type
)
7315 g_assert (type
->type
== MONO_TYPE_PTR
);
7316 return type
->data
.type
;
7320 * mono_type_get_modifiers:
7323 mono_type_get_modifiers (MonoType
*type
, gboolean
*is_required
, gpointer
*iter
)
7325 /* FIXME: implement */
7330 * mono_type_is_struct:
7331 * \param type the \c MonoType operated on
7332 * \returns TRUE if \p type is a struct, that is a \c ValueType but not an enum
7333 * or a basic type like \c System.Int32 . FALSE otherwise.
7336 mono_type_is_struct (MonoType
*type
)
7338 return (!type
->byref
&& ((type
->type
== MONO_TYPE_VALUETYPE
&&
7339 !m_class_is_enumtype (type
->data
.klass
)) || (type
->type
== MONO_TYPE_TYPEDBYREF
) ||
7340 ((type
->type
== MONO_TYPE_GENERICINST
) &&
7341 mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
) &&
7342 !m_class_is_enumtype (type
->data
.generic_class
->container_class
))));
7346 * mono_type_is_void:
7347 * \param type the \c MonoType operated on
7348 * \returns TRUE if \p type is \c System.Void . FALSE otherwise.
7351 mono_type_is_void (MonoType
*type
)
7353 return (type
&& (type
->type
== MONO_TYPE_VOID
) && !type
->byref
);
7357 * mono_type_is_pointer:
7358 * \param type the \c MonoType operated on
7359 * \returns TRUE if \p type is a managed or unmanaged pointer type. FALSE otherwise.
7362 mono_type_is_pointer (MonoType
*type
)
7364 return (type
&& ((type
->byref
|| (type
->type
== MONO_TYPE_I
) || type
->type
== MONO_TYPE_STRING
)
7365 || (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
7366 (type
->type
== MONO_TYPE_U
) || (type
->type
== MONO_TYPE_OBJECT
) ||
7367 (type
->type
== MONO_TYPE_ARRAY
) || (type
->type
== MONO_TYPE_PTR
) ||
7368 (type
->type
== MONO_TYPE_FNPTR
)));
7372 * mono_type_is_reference:
7373 * \param type the \c MonoType operated on
7374 * \returns TRUE if \p type represents an object reference. FALSE otherwise.
7377 mono_type_is_reference (MonoType
*type
)
7379 /* NOTE: changing this function to return TRUE more often may have
7380 * consequences for generic sharing in the AOT compiler. In
7381 * particular, returning TRUE for generic parameters with a 'class'
7382 * constraint may cause crashes.
7384 return (type
&& (((type
->type
== MONO_TYPE_STRING
) ||
7385 (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
7386 (type
->type
== MONO_TYPE_OBJECT
) || (type
->type
== MONO_TYPE_ARRAY
)) ||
7387 ((type
->type
== MONO_TYPE_GENERICINST
) &&
7388 !mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
))));
7392 mono_type_is_generic_parameter (MonoType
*type
)
7394 return !type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
);
7398 * mono_signature_get_return_type:
7399 * \param sig the method signature inspected
7400 * \returns the return type of the method signature \p sig
7403 mono_signature_get_return_type (MonoMethodSignature
*sig
)
7406 MONO_ENTER_GC_UNSAFE
;
7408 MONO_EXIT_GC_UNSAFE
;
7413 * mono_signature_get_params:
7414 * \param sig the method signature inspected
7415 * \param iter pointer to an iterator
7416 * Iterates over the parameters for the method signature \p sig.
7417 * A \c void* pointer must be initialized to NULL to start the iteration
7418 * and its address is passed to this function repeteadly until it returns
7420 * \returns the next parameter type of the method signature \p sig,
7421 * NULL when finished.
7424 mono_signature_get_params (MonoMethodSignature
*sig
, gpointer
*iter
)
7427 MONO_ENTER_GC_UNSAFE
;
7428 result
= mono_signature_get_params_internal (sig
, iter
);
7429 MONO_EXIT_GC_UNSAFE
;
7434 mono_signature_get_params_internal (MonoMethodSignature
*sig
, gpointer
*iter
)
7440 /* start from the first */
7441 if (sig
->param_count
) {
7442 *iter
= &sig
->params
[0];
7443 return sig
->params
[0];
7449 type
= (MonoType
**)*iter
;
7451 if (type
< &sig
->params
[sig
->param_count
]) {
7459 * mono_signature_get_param_count:
7460 * \param sig the method signature inspected
7461 * \returns the number of parameters in the method signature \p sig.
7464 mono_signature_get_param_count (MonoMethodSignature
*sig
)
7466 return sig
->param_count
;
7470 * mono_signature_get_call_conv:
7471 * \param sig the method signature inspected
7472 * \returns the call convention of the method signature \p sig.
7475 mono_signature_get_call_conv (MonoMethodSignature
*sig
)
7477 return sig
->call_convention
;
7481 * mono_signature_vararg_start:
7482 * \param sig the method signature inspected
7483 * \returns the number of the first vararg parameter in the
7484 * method signature \param sig. \c -1 if this is not a vararg signature.
7487 mono_signature_vararg_start (MonoMethodSignature
*sig
)
7489 return sig
->sentinelpos
;
7493 * mono_signature_is_instance:
7494 * \param sig the method signature inspected
7495 * \returns TRUE if this the method signature \p sig has an implicit
7496 * first instance argument. FALSE otherwise.
7499 mono_signature_is_instance (MonoMethodSignature
*sig
)
7501 return sig
->hasthis
;
7505 * mono_signature_param_is_out
7506 * \param sig the method signature inspected
7507 * \param param_num the 0-based index of the inspected parameter
7508 * \returns TRUE if the parameter is an out parameter, FALSE
7512 mono_signature_param_is_out (MonoMethodSignature
*sig
, int param_num
)
7514 g_assert (param_num
>= 0 && param_num
< sig
->param_count
);
7515 return (sig
->params
[param_num
]->attrs
& PARAM_ATTRIBUTE_OUT
) != 0;
7519 * mono_signature_explicit_this:
7520 * \param sig the method signature inspected
7521 * \returns TRUE if this the method signature \p sig has an explicit
7522 * instance argument. FALSE otherwise.
7525 mono_signature_explicit_this (MonoMethodSignature
*sig
)
7527 return sig
->explicit_this
;
7530 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
7532 mono_aligned_addr_hash (gconstpointer ptr
)
7534 /* Same hashing we use for objects */
7535 return (GPOINTER_TO_UINT (ptr
) >> 3) * 2654435761u;
7539 * If @field belongs to an inflated generic class, return the corresponding field of the
7540 * generic type definition class.
7543 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField
*field
)
7548 if (!mono_class_is_ginst (field
->parent
))
7551 gtd
= mono_class_get_generic_class (field
->parent
)->container_class
;
7552 offset
= field
- m_class_get_fields (field
->parent
);
7553 return m_class_get_fields (gtd
) + offset
;
7557 * If @event belongs to an inflated generic class, return the corresponding event of the
7558 * generic type definition class.
7561 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent
*event
)
7566 if (!mono_class_is_ginst (event
->parent
))
7569 gtd
= mono_class_get_generic_class (event
->parent
)->container_class
;
7570 offset
= event
- mono_class_get_event_info (event
->parent
)->events
;
7571 return mono_class_get_event_info (gtd
)->events
+ offset
;
7575 * If @property belongs to an inflated generic class, return the corresponding property of the
7576 * generic type definition class.
7579 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty
*property
)
7581 MonoClassPropertyInfo
*info
;
7585 if (!mono_class_is_ginst (property
->parent
))
7588 info
= mono_class_get_property_info (property
->parent
);
7589 gtd
= mono_class_get_generic_class (property
->parent
)->container_class
;
7590 offset
= property
- info
->properties
;
7591 return mono_class_get_property_info (gtd
)->properties
+ offset
;
7595 mono_method_get_wrapper_cache (MonoMethod
*method
)
7597 if (method
->is_inflated
) {
7598 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
7599 return &imethod
->owner
->wrapper_caches
;
7601 return &m_class_get_image (method
->klass
)->wrapper_caches
;
7605 // 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.
7608 * mono_find_image_set_owner:
7610 * Find the imageset, if any, which a given pointer is located in the memory of.
7613 mono_find_image_set_owner (void *ptr
)
7615 MonoImageSet
*owner
= NULL
;
7622 for (i
= 0; !owner
&& i
< image_sets
->len
; ++i
) {
7623 MonoImageSet
*set
= (MonoImageSet
*)g_ptr_array_index (image_sets
, i
);
7624 if (mono_mempool_contains_addr (set
->mempool
, ptr
))
7629 image_sets_unlock ();
7635 mono_loader_set_strict_assembly_name_check (gboolean enabled
)
7637 check_assembly_names_strictly
= enabled
;
7641 mono_loader_get_strict_assembly_name_check (void)
7643 #if !defined(DISABLE_DESKTOP_LOADER) || defined(ENABLE_NETCORE)
7644 return check_assembly_names_strictly
;
7652 mono_type_is_aggregate_mods (const MonoType
*t
)
7657 MonoTypeWithModifiers
*full
= (MonoTypeWithModifiers
*)t
;
7659 return full
->is_aggregate
;
7662 MonoCustomModContainer
*
7663 mono_type_get_cmods (const MonoType
*t
)
7668 MonoTypeWithModifiers
*full
= (MonoTypeWithModifiers
*)t
;
7670 g_assert (!full
->is_aggregate
);
7671 return &full
->mods
.cmods
;
7674 MonoAggregateModContainer
*
7675 mono_type_get_amods (const MonoType
*t
)
7680 MonoTypeWithModifiers
*full
= (MonoTypeWithModifiers
*)t
;
7682 g_assert (full
->is_aggregate
);
7683 return full
->mods
.amods
;
7687 mono_sizeof_aggregate_modifiers (uint8_t num_mods
)
7690 accum
+= offsetof (MonoAggregateModContainer
, modifiers
);
7691 accum
+= sizeof (MonoSingleCustomMod
) * num_mods
;
7696 mono_sizeof_type_with_mods (uint8_t num_mods
, gboolean is_aggregate
)
7699 return sizeof (MonoType
);
7701 accum
+= offsetof (MonoTypeWithModifiers
, mods
);
7703 if (!is_aggregate
) {
7704 accum
+= offsetof (struct _MonoCustomModContainer
, modifiers
);
7705 accum
+= sizeof (MonoCustomMod
) * num_mods
;
7707 accum
+= offsetof (MonoAggregateModContainer
, modifiers
);
7708 accum
+= sizeof (MonoAggregateModContainer
*);
7714 mono_sizeof_type (const MonoType
*ty
)
7716 if (ty
->has_cmods
) {
7717 if (!mono_type_is_aggregate_mods (ty
)) {
7718 MonoCustomModContainer
*cmods
= mono_type_get_cmods (ty
);
7719 return mono_sizeof_type_with_mods (cmods
->count
, FALSE
);
7721 MonoAggregateModContainer
*amods
= mono_type_get_amods (ty
);
7722 return mono_sizeof_type_with_mods (amods
->count
, TRUE
);
7725 return sizeof (MonoType
);
7729 mono_type_set_amods (MonoType
*t
, MonoAggregateModContainer
*amods
)
7731 g_assert (t
->has_cmods
);
7732 MonoTypeWithModifiers
*t_full
= (MonoTypeWithModifiers
*)t
;
7733 g_assert (t_full
->is_aggregate
);
7734 g_assert (t_full
->mods
.amods
== NULL
);
7735 t_full
->mods
.amods
= amods
;