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 <mono/utils/mono-error-internals.h>
32 #include <mono/utils/bsearch.h>
33 #include <mono/utils/atomic.h>
34 #include <mono/utils/unlocked.h>
35 #include <mono/utils/mono-counters.h>
37 static gint32 img_set_cache_hit, img_set_cache_miss, img_set_count;
40 /* Auxiliary structure used for caching inflated signatures */
42 MonoMethodSignature *sig;
43 MonoGenericContext context;
44 } MonoInflatedMethodSignature;
46 static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, gboolean transient,
47 const char *ptr, const char **rptr, MonoError *error);
49 static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
50 static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
51 static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
52 static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
53 gboolean signature_only);
54 static void free_generic_inst (MonoGenericInst *ginst);
55 static void free_generic_class (MonoGenericClass *ginst);
56 static void free_inflated_method (MonoMethodInflated *method);
57 static void free_inflated_signature (MonoInflatedMethodSignature *sig);
58 static void mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image);
61 * This enumeration is used to describe the data types in the metadata
72 /* Index into Blob heap */
75 /* Index into String heap */
81 /* Pointer into a table */
84 /* HasConstant:Parent pointer (Param, Field or Property) */
87 /* HasCustomAttribute index. Indexes any table except CustomAttribute */
90 /* CustomAttributeType encoded index */
93 /* HasDeclSecurity index: TypeDef Method or Assembly */
96 /* Implementation coded index: File, Export AssemblyRef */
99 /* HasFieldMarshal coded index: Field or Param table */
102 /* MemberForwardedIndex: Field or Method */
105 /* TypeDefOrRef coded index: typedef, typeref, typespec */
108 /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
111 /* MethodDefOrRef coded index: Method or Member Ref table */
114 /* HasSemantic coded index: Event or Property */
117 /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
120 /* CustomDebugInformation parent encoded index */
121 MONO_MT_HASCUSTDEBUG_IDX
124 const static unsigned char TableSchemas [] = {
125 #define ASSEMBLY_SCHEMA_OFFSET 0
126 MONO_MT_UINT32, /* "HashId" }, */
127 MONO_MT_UINT16, /* "Major" }, */
128 MONO_MT_UINT16, /* "Minor" }, */
129 MONO_MT_UINT16, /* "BuildNumber" }, */
130 MONO_MT_UINT16, /* "RevisionNumber" }, */
131 MONO_MT_UINT32, /* "Flags" }, */
132 MONO_MT_BLOB_IDX, /* "PublicKey" }, */
133 MONO_MT_STRING_IDX, /* "Name" }, */
134 MONO_MT_STRING_IDX, /* "Culture" }, */
137 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
138 MONO_MT_UINT32, /* "OSPlatformID" }, */
139 MONO_MT_UINT32, /* "OSMajor" }, */
140 MONO_MT_UINT32, /* "OSMinor" }, */
143 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
144 MONO_MT_UINT32, /* "Processor" }, */
147 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
148 MONO_MT_UINT16, /* "Major" }, */
149 MONO_MT_UINT16, /* "Minor" }, */
150 MONO_MT_UINT16, /* "Build" }, */
151 MONO_MT_UINT16, /* "Revision" }, */
152 MONO_MT_UINT32, /* "Flags" }, */
153 MONO_MT_BLOB_IDX, /* "PublicKeyOrToken" }, */
154 MONO_MT_STRING_IDX, /* "Name" }, */
155 MONO_MT_STRING_IDX, /* "Culture" }, */
156 MONO_MT_BLOB_IDX, /* "HashValue" }, */
159 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
160 MONO_MT_UINT32, /* "OSPlatformID" }, */
161 MONO_MT_UINT32, /* "OSMajorVersion" }, */
162 MONO_MT_UINT32, /* "OSMinorVersion" }, */
163 MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */
166 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
167 MONO_MT_UINT32, /* "Processor" }, */
168 MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */
171 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
172 MONO_MT_UINT16, /* "PackingSize" }, */
173 MONO_MT_UINT32, /* "ClassSize" }, */
174 MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
177 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
178 MONO_MT_UINT8, /* "Type" }, */
179 MONO_MT_UINT8, /* "PaddingZero" }, */
180 MONO_MT_CONST_IDX, /* "Parent" }, */
181 MONO_MT_BLOB_IDX, /* "Value" }, */
184 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
185 MONO_MT_HASCAT_IDX, /* "Parent" }, */
186 MONO_MT_CAT_IDX, /* "Type" }, */
187 MONO_MT_BLOB_IDX, /* "Value" }, */
190 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
191 MONO_MT_UINT16, /* "Action" }, */
192 MONO_MT_HASDEC_IDX, /* "Parent" }, */
193 MONO_MT_BLOB_IDX, /* "PermissionSet" }, */
196 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
197 MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
198 MONO_MT_TABLE_IDX, /* "EventList:Event" }, */
201 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
202 MONO_MT_UINT16, /* "EventFlags#EventAttribute" }, */
203 MONO_MT_STRING_IDX, /* "Name" }, */
204 MONO_MT_TDOR_IDX, /* "EventType" }, TypeDef or TypeRef or TypeSpec */
207 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
208 MONO_MT_TABLE_IDX, /* "Event" }, */
211 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
212 MONO_MT_UINT32, /* "Flags" }, */
213 MONO_MT_TABLE_IDX, /* "TypeDefId" }, */
214 MONO_MT_STRING_IDX, /* "TypeName" }, */
215 MONO_MT_STRING_IDX, /* "TypeNameSpace" }, */
216 MONO_MT_IMPL_IDX, /* "Implementation" }, */
219 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
220 MONO_MT_UINT16, /* "Flags" }, */
221 MONO_MT_STRING_IDX, /* "Name" }, */
222 MONO_MT_BLOB_IDX, /* "Signature" }, */
225 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
226 MONO_MT_UINT32, /* "Offset" }, */
227 MONO_MT_TABLE_IDX, /* "Field:Field" }, */
230 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
231 MONO_MT_HFM_IDX, /* "Parent" }, */
232 MONO_MT_BLOB_IDX, /* "NativeType" }, */
235 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
236 MONO_MT_UINT32, /* "RVA" }, */
237 MONO_MT_TABLE_IDX, /* "Field:Field" }, */
240 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
241 MONO_MT_TABLE_IDX, /* "Field" }, */
244 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
245 MONO_MT_UINT32, /* "Flags" }, */
246 MONO_MT_STRING_IDX, /* "Name" }, */
247 MONO_MT_BLOB_IDX, /* "Value" }, */
250 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
251 MONO_MT_UINT16, /* "MappingFlag" }, */
252 MONO_MT_MF_IDX, /* "MemberForwarded" }, */
253 MONO_MT_STRING_IDX, /* "ImportName" }, */
254 MONO_MT_TABLE_IDX, /* "ImportScope:ModuleRef" }, */
257 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
258 MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */
259 MONO_MT_TDOR_IDX, /* "Interface=TypeDefOrRef" }, */
262 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
263 MONO_MT_UINT32, /* "Offset" }, */
264 MONO_MT_UINT32, /* "Flags" }, */
265 MONO_MT_STRING_IDX, /* "Name" }, */
266 MONO_MT_IMPL_IDX, /* "Implementation" }, */
269 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
270 MONO_MT_MRP_IDX, /* "Class" }, */
271 MONO_MT_STRING_IDX, /* "Name" }, */
272 MONO_MT_BLOB_IDX, /* "Signature" }, */
275 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
276 MONO_MT_UINT32, /* "RVA" }, */
277 MONO_MT_UINT16, /* "ImplFlags#MethodImplAttributes" }, */
278 MONO_MT_UINT16, /* "Flags#MethodAttribute" }, */
279 MONO_MT_STRING_IDX, /* "Name" }, */
280 MONO_MT_BLOB_IDX, /* "Signature" }, */
281 MONO_MT_TABLE_IDX, /* "ParamList:Param" }, */
284 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
285 MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */
286 MONO_MT_MDOR_IDX, /* "MethodBody" }, */
287 MONO_MT_MDOR_IDX, /* "MethodDeclaration" }, */
290 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
291 MONO_MT_UINT16, /* "MethodSemantic" }, */
292 MONO_MT_TABLE_IDX, /* "Method:Method" }, */
293 MONO_MT_HS_IDX, /* "Association" }, */
296 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
297 MONO_MT_TABLE_IDX, /* "Method" }, */
300 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
301 MONO_MT_UINT16, /* "Generation" }, */
302 MONO_MT_STRING_IDX, /* "Name" }, */
303 MONO_MT_GUID_IDX, /* "MVID" }, */
304 MONO_MT_GUID_IDX, /* "EncID" }, */
305 MONO_MT_GUID_IDX, /* "EncBaseID" }, */
308 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
309 MONO_MT_STRING_IDX, /* "Name" }, */
312 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
313 MONO_MT_TABLE_IDX, /* "NestedClass:TypeDef" }, */
314 MONO_MT_TABLE_IDX, /* "EnclosingClass:TypeDef" }, */
317 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
318 MONO_MT_UINT16, /* "Flags" }, */
319 MONO_MT_UINT16, /* "Sequence" }, */
320 MONO_MT_STRING_IDX, /* "Name" }, */
323 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
324 MONO_MT_TABLE_IDX, /* "Param" }, */
327 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
328 MONO_MT_UINT16, /* "Flags" }, */
329 MONO_MT_STRING_IDX, /* "Name" }, */
330 MONO_MT_BLOB_IDX, /* "Type" }, */
333 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
334 MONO_MT_TABLE_IDX, /* "Property" }, */
337 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
338 MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
339 MONO_MT_TABLE_IDX, /* "PropertyList:Property" }, */
342 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
343 MONO_MT_BLOB_IDX, /* "Signature" }, */
346 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
347 MONO_MT_UINT32, /* "Flags" }, */
348 MONO_MT_STRING_IDX, /* "Name" }, */
349 MONO_MT_STRING_IDX, /* "Namespace" }, */
350 MONO_MT_TDOR_IDX, /* "Extends" }, */
351 MONO_MT_TABLE_IDX, /* "FieldList:Field" }, */
352 MONO_MT_TABLE_IDX, /* "MethodList:Method" }, */
355 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
356 MONO_MT_RS_IDX, /* "ResolutionScope=ResolutionScope" }, */
357 MONO_MT_STRING_IDX, /* "Name" }, */
358 MONO_MT_STRING_IDX, /* "Namespace" }, */
361 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
362 MONO_MT_BLOB_IDX, /* "Signature" }, */
365 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
366 MONO_MT_UINT16, /* "Number" }, */
367 MONO_MT_UINT16, /* "Flags" }, */
368 MONO_MT_TABLE_IDX, /* "Owner" }, TypeDef or MethodDef */
369 MONO_MT_STRING_IDX, /* "Name" }, */
372 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
373 MONO_MT_MDOR_IDX, /* "Method" }, */
374 MONO_MT_BLOB_IDX, /* "Signature" }, */
377 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
378 MONO_MT_TABLE_IDX, /* "GenericParam" }, */
379 MONO_MT_TDOR_IDX, /* "Constraint" }, */
382 #define DOCUMENT_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
383 MONO_MT_BLOB_IDX, /* Name */
384 MONO_MT_GUID_IDX, /* HashAlgorithm */
385 MONO_MT_BLOB_IDX, /* Hash */
386 MONO_MT_GUID_IDX, /* Language */
389 #define METHODBODY_SCHEMA_OFFSET DOCUMENT_SCHEMA_OFFSET + 5
390 MONO_MT_TABLE_IDX, /* Document */
391 MONO_MT_BLOB_IDX, /* SequencePoints */
394 #define LOCALSCOPE_SCHEMA_OFFSET METHODBODY_SCHEMA_OFFSET + 3
395 MONO_MT_TABLE_IDX, /* Method */
396 MONO_MT_TABLE_IDX, /* ImportScope */
397 MONO_MT_TABLE_IDX, /* VariableList */
398 MONO_MT_TABLE_IDX, /* ConstantList */
399 MONO_MT_UINT32, /* StartOffset */
400 MONO_MT_UINT32, /* Length */
403 #define LOCALVARIABLE_SCHEMA_OFFSET LOCALSCOPE_SCHEMA_OFFSET + 7
404 MONO_MT_UINT16, /* Attributes */
405 MONO_MT_UINT16, /* Index */
406 MONO_MT_STRING_IDX, /* Name */
409 #define LOCALCONSTANT_SCHEMA_OFFSET LOCALVARIABLE_SCHEMA_OFFSET + 4
410 MONO_MT_STRING_IDX, /* Name (String heap index) */
411 MONO_MT_BLOB_IDX, /* Signature (Blob heap index, LocalConstantSig blob) */
414 #define IMPORTSCOPE_SCHEMA_OFFSET LOCALCONSTANT_SCHEMA_OFFSET + 3
415 MONO_MT_TABLE_IDX, /* Parent (ImportScope row id or nil) */
416 MONO_MT_BLOB_IDX, /* Imports (Blob index, encoding: Imports blob) */
419 #define ASYNCMETHOD_SCHEMA_OFFSET IMPORTSCOPE_SCHEMA_OFFSET + 3
420 MONO_MT_TABLE_IDX, /* MoveNextMethod (MethodDef row id) */
421 MONO_MT_TABLE_IDX, /* KickoffMethod (MethodDef row id) */
424 #define CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET ASYNCMETHOD_SCHEMA_OFFSET + 3
425 MONO_MT_HASCUSTDEBUG_IDX, /* Parent (HasCustomDebugInformation coded index) */
426 MONO_MT_GUID_IDX, /* Kind (Guid heap index) */
427 MONO_MT_BLOB_IDX, /* Value (Blob heap index) */
430 #define NULL_SCHEMA_OFFSET CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET + 4
434 /* Must be the same order as MONO_TABLE_* */
435 const static unsigned char
436 table_description [] = {
437 MODULE_SCHEMA_OFFSET,
438 TYPEREF_SCHEMA_OFFSET,
439 TYPEDEF_SCHEMA_OFFSET,
440 FIELD_POINTER_SCHEMA_OFFSET,
442 METHOD_POINTER_SCHEMA_OFFSET,
443 METHOD_SCHEMA_OFFSET,
444 PARAM_POINTER_SCHEMA_OFFSET,
446 IFACEMAP_SCHEMA_OFFSET,
447 MEMBERREF_SCHEMA_OFFSET, /* 0xa */
448 CONSTANT_SCHEMA_OFFSET,
449 CUSTOM_ATTR_SCHEMA_OFFSET,
450 FIELD_MARSHAL_SCHEMA_OFFSET,
451 DECL_SEC_SCHEMA_OFFSET,
452 CLASS_LAYOUT_SCHEMA_OFFSET,
453 FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
454 STDALON_SIG_SCHEMA_OFFSET,
455 EVENTMAP_SCHEMA_OFFSET,
456 EVENT_POINTER_SCHEMA_OFFSET,
458 PROPERTY_MAP_SCHEMA_OFFSET,
459 PROPERTY_POINTER_SCHEMA_OFFSET,
460 PROPERTY_SCHEMA_OFFSET,
461 METHOD_SEMA_SCHEMA_OFFSET,
462 METHOD_IMPL_SCHEMA_OFFSET,
463 MODULEREF_SCHEMA_OFFSET, /* 0x1a */
464 TYPESPEC_SCHEMA_OFFSET,
465 IMPLMAP_SCHEMA_OFFSET,
466 FIELD_RVA_SCHEMA_OFFSET,
469 ASSEMBLY_SCHEMA_OFFSET, /* 0x20 */
470 ASSEMBLYPROC_SCHEMA_OFFSET,
471 ASSEMBLYOS_SCHEMA_OFFSET,
472 ASSEMBLYREF_SCHEMA_OFFSET,
473 ASSEMBLYREFPROC_SCHEMA_OFFSET,
474 ASSEMBLYREFOS_SCHEMA_OFFSET,
476 EXPORTED_TYPE_SCHEMA_OFFSET,
477 MANIFEST_SCHEMA_OFFSET,
478 NESTED_CLASS_SCHEMA_OFFSET,
479 GENPARAM_SCHEMA_OFFSET, /* 0x2a */
480 METHOD_SPEC_SCHEMA_OFFSET,
481 GEN_CONSTRAINT_SCHEMA_OFFSET,
485 DOCUMENT_SCHEMA_OFFSET, /* 0x30 */
486 METHODBODY_SCHEMA_OFFSET,
487 LOCALSCOPE_SCHEMA_OFFSET,
488 LOCALVARIABLE_SCHEMA_OFFSET,
489 LOCALCONSTANT_SCHEMA_OFFSET,
490 IMPORTSCOPE_SCHEMA_OFFSET,
491 ASYNCMETHOD_SCHEMA_OFFSET,
492 CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET
495 #ifdef HAVE_ARRAY_ELEM_INIT
496 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
497 #define MSGSTRFIELD1(line) str##line
498 static const struct msgstr_t {
499 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
500 #include "mono/cil/tables.def"
503 #define TABLEDEF(a,b) b,
504 #include "mono/cil/tables.def"
507 static const gint16 tableidx [] = {
508 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
509 #include "mono/cil/tables.def"
514 #define TABLEDEF(a,b) b,
515 static const char* const
516 mono_tables_names [] = {
517 #include "mono/cil/tables.def"
523 /* If TRUE (but also see DISABLE_STICT_STRONG_NAMES #define), Mono will check
524 * that the public key token, culture and version of a candidate assembly matches
525 * the requested strong name. If FALSE, as long as the name matches, the candidate
528 static gboolean check_strong_names_strictly = FALSE;
530 // Amount initially reserved in each imageset's mempool.
531 // FIXME: This number is arbitrary, a more practical number should be found
532 #define INITIAL_IMAGE_SET_SIZE 1024
535 * mono_meta_table_name:
536 * \param table table index
538 * Returns the name of the given ECMA metadata logical format table
539 * as described in ECMA 335, Partition II, Section 22.
541 * \returns the name for the \p table index
544 mono_meta_table_name (int table)
546 if ((table < 0) || (table > MONO_TABLE_LAST))
549 #ifdef HAVE_ARRAY_ELEM_INIT
550 return (const char*)&tablestr + tableidx [table];
552 return mono_tables_names [table];
556 /* The guy who wrote the spec for this should not be allowed near a
559 If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
560 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
561 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
562 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
563 inverse of this mapping.
566 #define rtsize(meta,s,b) (((s) < (1 << (b)) ? 2 : 4))
569 idx_size (MonoImage *meta, int tableidx)
571 if (meta->referenced_tables && (meta->referenced_tables & ((guint64)1 << tableidx)))
572 return meta->referenced_table_rows [tableidx] < 65536 ? 2 : 4;
574 return meta->tables [tableidx].rows < 65536 ? 2 : 4;
578 get_nrows (MonoImage *meta, int tableidx)
580 if (meta->referenced_tables && (meta->referenced_tables & ((guint64)1 << tableidx)))
581 return meta->referenced_table_rows [tableidx];
583 return meta->tables [tableidx].rows;
586 /* Reference: Partition II - 23.2.6 */
588 * mono_metadata_compute_size:
589 * \param meta metadata context
590 * \param tableindex metadata table number
591 * \param result_bitfield pointer to \c guint32 where to store additional info
593 * \c mono_metadata_compute_size computes the length in bytes of a single
594 * row in a metadata table. The size of each column is encoded in the
595 * \p result_bitfield return value along with the number of columns in the table.
596 * the resulting bitfield should be handed to the \c mono_metadata_table_size
597 * and \c mono_metadata_table_count macros.
598 * This is a Mono runtime internal only function.
601 mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
603 guint32 bitfield = 0;
604 int size = 0, field_size = 0;
607 const unsigned char *description = TableSchemas + table_description [tableindex];
609 for (i = 0; (code = description [i]) != MONO_MT_END; i++){
612 field_size = 4; break;
615 field_size = 2; break;
618 field_size = 1; break;
620 case MONO_MT_BLOB_IDX:
621 field_size = meta->idx_blob_wide ? 4 : 2; break;
623 case MONO_MT_STRING_IDX:
624 field_size = meta->idx_string_wide ? 4 : 2; break;
626 case MONO_MT_GUID_IDX:
627 field_size = meta->idx_guid_wide ? 4 : 2; break;
629 case MONO_MT_TABLE_IDX:
630 /* Uhm, a table index can point to other tables besides the current one
631 * so, it's not correct to use the rowcount of the current table to
632 * get the size for this column - lupus
634 switch (tableindex) {
635 case MONO_TABLE_ASSEMBLYREFOS:
637 field_size = idx_size (meta, MONO_TABLE_ASSEMBLYREF); break;
638 case MONO_TABLE_ASSEMBLYREFPROCESSOR:
640 field_size = idx_size (meta, MONO_TABLE_ASSEMBLYREF); break;
641 case MONO_TABLE_CLASSLAYOUT:
643 field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
644 case MONO_TABLE_EVENTMAP:
645 g_assert (i == 0 || i == 1);
646 field_size = i ? idx_size (meta, MONO_TABLE_EVENT):
647 idx_size (meta, MONO_TABLE_TYPEDEF);
649 case MONO_TABLE_EVENT_POINTER:
651 field_size = idx_size (meta, MONO_TABLE_EVENT); break;
652 case MONO_TABLE_EXPORTEDTYPE:
654 /* the index is in another metadata file, so it must be 4 */
655 field_size = 4; break;
656 case MONO_TABLE_FIELDLAYOUT:
658 field_size = idx_size (meta, MONO_TABLE_FIELD); break;
659 case MONO_TABLE_FIELDRVA:
661 field_size = idx_size (meta, MONO_TABLE_FIELD); break;
662 case MONO_TABLE_FIELD_POINTER:
664 field_size = idx_size (meta, MONO_TABLE_FIELD); break;
665 case MONO_TABLE_IMPLMAP:
667 field_size = idx_size (meta, MONO_TABLE_MODULEREF); break;
668 case MONO_TABLE_INTERFACEIMPL:
670 field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
671 case MONO_TABLE_METHOD:
673 field_size = idx_size (meta, MONO_TABLE_PARAM); break;
674 case MONO_TABLE_METHODIMPL:
676 field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
677 case MONO_TABLE_METHODSEMANTICS:
679 field_size = idx_size (meta, MONO_TABLE_METHOD); break;
680 case MONO_TABLE_METHOD_POINTER:
682 field_size = idx_size (meta, MONO_TABLE_METHOD); break;
683 case MONO_TABLE_NESTEDCLASS:
684 g_assert (i == 0 || i == 1);
685 field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
686 case MONO_TABLE_PARAM_POINTER:
688 field_size = idx_size (meta, MONO_TABLE_PARAM); break;
689 case MONO_TABLE_PROPERTYMAP:
690 g_assert (i == 0 || i == 1);
691 field_size = i ? idx_size (meta, MONO_TABLE_PROPERTY):
692 idx_size (meta, MONO_TABLE_TYPEDEF);
694 case MONO_TABLE_PROPERTY_POINTER:
696 field_size = idx_size (meta, MONO_TABLE_PROPERTY); break;
697 case MONO_TABLE_TYPEDEF:
698 g_assert (i == 4 || i == 5);
699 field_size = i == 4 ? idx_size (meta, MONO_TABLE_FIELD):
700 idx_size (meta, MONO_TABLE_METHOD);
702 case MONO_TABLE_GENERICPARAM:
704 n = MAX (get_nrows (meta, MONO_TABLE_METHOD), get_nrows (meta, MONO_TABLE_TYPEDEF));
705 /*This is a coded token for 2 tables, so takes 1 bit */
706 field_size = rtsize (meta, n, 16 - MONO_TYPEORMETHOD_BITS);
708 case MONO_TABLE_GENERICPARAMCONSTRAINT:
710 field_size = idx_size (meta, MONO_TABLE_GENERICPARAM);
712 case MONO_TABLE_LOCALSCOPE:
715 // FIXME: This table is in another file
716 field_size = idx_size (meta, MONO_TABLE_METHOD);
719 field_size = idx_size (meta, MONO_TABLE_IMPORTSCOPE);
722 field_size = idx_size (meta, MONO_TABLE_LOCALVARIABLE);
725 field_size = idx_size (meta, MONO_TABLE_LOCALCONSTANT);
728 g_assert_not_reached ();
732 case MONO_TABLE_METHODBODY:
734 field_size = idx_size (meta, MONO_TABLE_DOCUMENT); break;
735 case MONO_TABLE_IMPORTSCOPE:
737 field_size = idx_size (meta, MONO_TABLE_IMPORTSCOPE); break;
738 case MONO_TABLE_STATEMACHINEMETHOD:
739 g_assert(i == 0 || i == 1);
740 field_size = idx_size(meta, MONO_TABLE_METHOD); break;
742 g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex, i);
747 * HasConstant: ParamDef, FieldDef, Property
749 case MONO_MT_CONST_IDX:
750 n = MAX (get_nrows (meta, MONO_TABLE_PARAM),
751 get_nrows (meta, MONO_TABLE_FIELD));
752 n = MAX (n, get_nrows (meta, MONO_TABLE_PROPERTY));
754 /* 2 bits to encode tag */
755 field_size = rtsize (meta, n, 16-2);
759 * HasCustomAttribute: points to any table but
762 case MONO_MT_HASCAT_IDX:
764 * We believe that since the signature and
765 * permission are indexing the Blob heap,
766 * we should consider the blob size first
768 /* I'm not a believer - lupus
769 if (meta->idx_blob_wide){
774 n = MAX (get_nrows (meta, MONO_TABLE_METHOD),
775 get_nrows (meta, MONO_TABLE_FIELD));
776 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPEREF));
777 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPEDEF));
778 n = MAX (n, get_nrows (meta, MONO_TABLE_PARAM));
779 n = MAX (n, get_nrows (meta, MONO_TABLE_INTERFACEIMPL));
780 n = MAX (n, get_nrows (meta, MONO_TABLE_MEMBERREF));
781 n = MAX (n, get_nrows (meta, MONO_TABLE_MODULE));
782 n = MAX (n, get_nrows (meta, MONO_TABLE_DECLSECURITY));
783 n = MAX (n, get_nrows (meta, MONO_TABLE_PROPERTY));
784 n = MAX (n, get_nrows (meta, MONO_TABLE_EVENT));
785 n = MAX (n, get_nrows (meta, MONO_TABLE_STANDALONESIG));
786 n = MAX (n, get_nrows (meta, MONO_TABLE_MODULEREF));
787 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPESPEC));
788 n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLY));
789 n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
790 n = MAX (n, get_nrows (meta, MONO_TABLE_FILE));
791 n = MAX (n, get_nrows (meta, MONO_TABLE_EXPORTEDTYPE));
792 n = MAX (n, get_nrows (meta, MONO_TABLE_MANIFESTRESOURCE));
793 n = MAX (n, get_nrows (meta, MONO_TABLE_GENERICPARAM));
794 n = MAX (n, get_nrows (meta, MONO_TABLE_GENERICPARAMCONSTRAINT));
795 n = MAX (n, get_nrows (meta, MONO_TABLE_METHODSPEC));
797 /* 5 bits to encode */
798 field_size = rtsize (meta, n, 16-5);
802 * HasCustomAttribute: points to any table but
806 case MONO_MT_HASCUSTDEBUG_IDX:
807 n = MAX(get_nrows (meta, MONO_TABLE_METHOD),
808 get_nrows (meta, MONO_TABLE_FIELD));
809 n = MAX(n, get_nrows (meta, MONO_TABLE_TYPEREF));
810 n = MAX(n, get_nrows (meta, MONO_TABLE_TYPEDEF));
811 n = MAX(n, get_nrows (meta, MONO_TABLE_PARAM));
812 n = MAX(n, get_nrows (meta, MONO_TABLE_INTERFACEIMPL));
813 n = MAX(n, get_nrows (meta, MONO_TABLE_MEMBERREF));
814 n = MAX(n, get_nrows (meta, MONO_TABLE_MODULE));
815 n = MAX(n, get_nrows (meta, MONO_TABLE_DECLSECURITY));
816 n = MAX(n, get_nrows (meta, MONO_TABLE_PROPERTY));
817 n = MAX(n, get_nrows (meta, MONO_TABLE_EVENT));
818 n = MAX(n, get_nrows (meta, MONO_TABLE_STANDALONESIG));
819 n = MAX(n, get_nrows (meta, MONO_TABLE_MODULEREF));
820 n = MAX(n, get_nrows (meta, MONO_TABLE_TYPESPEC));
821 n = MAX(n, get_nrows (meta, MONO_TABLE_ASSEMBLY));
822 n = MAX(n, get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
823 n = MAX(n, get_nrows (meta, MONO_TABLE_FILE));
824 n = MAX(n, get_nrows (meta, MONO_TABLE_EXPORTEDTYPE));
825 n = MAX(n, get_nrows (meta, MONO_TABLE_MANIFESTRESOURCE));
826 n = MAX(n, get_nrows (meta, MONO_TABLE_GENERICPARAM));
827 n = MAX(n, get_nrows (meta, MONO_TABLE_GENERICPARAMCONSTRAINT));
828 n = MAX(n, get_nrows (meta, MONO_TABLE_METHODSPEC));
829 n = MAX(n, get_nrows (meta, MONO_TABLE_DOCUMENT));
830 n = MAX(n, get_nrows (meta, MONO_TABLE_LOCALSCOPE));
831 n = MAX(n, get_nrows (meta, MONO_TABLE_LOCALVARIABLE));
832 n = MAX(n, get_nrows (meta, MONO_TABLE_LOCALCONSTANT));
833 n = MAX(n, get_nrows (meta, MONO_TABLE_IMPORTSCOPE));
835 /* 5 bits to encode */
836 field_size = rtsize(meta, n, 16 - 5);
840 * CustomAttributeType: MethodDef, MemberRef.
842 case MONO_MT_CAT_IDX:
843 n = MAX (get_nrows (meta, MONO_TABLE_METHOD),
844 get_nrows (meta, MONO_TABLE_MEMBERREF));
846 /* 3 bits to encode */
847 field_size = rtsize (meta, n, 16-3);
851 * HasDeclSecurity: Typedef, MethodDef, Assembly
853 case MONO_MT_HASDEC_IDX:
854 n = MAX (get_nrows (meta, MONO_TABLE_TYPEDEF),
855 get_nrows (meta, MONO_TABLE_METHOD));
856 n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLY));
858 /* 2 bits to encode */
859 field_size = rtsize (meta, n, 16-2);
863 * Implementation: File, AssemblyRef, ExportedType
865 case MONO_MT_IMPL_IDX:
866 n = MAX (get_nrows (meta, MONO_TABLE_FILE),
867 get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
868 n = MAX (n, get_nrows (meta, MONO_TABLE_EXPORTEDTYPE));
870 /* 2 bits to encode tag */
871 field_size = rtsize (meta, n, 16-2);
875 * HasFieldMarshall: FieldDef, ParamDef
877 case MONO_MT_HFM_IDX:
878 n = MAX (get_nrows (meta, MONO_TABLE_FIELD),
879 get_nrows (meta, MONO_TABLE_PARAM));
881 /* 1 bit used to encode tag */
882 field_size = rtsize (meta, n, 16-1);
886 * MemberForwarded: FieldDef, MethodDef
889 n = MAX (get_nrows (meta, MONO_TABLE_FIELD),
890 get_nrows (meta, MONO_TABLE_METHOD));
892 /* 1 bit used to encode tag */
893 field_size = rtsize (meta, n, 16-1);
897 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
899 * It is TypeDef, _TypeRef_, TypeSpec, instead.
901 case MONO_MT_TDOR_IDX:
902 n = MAX (get_nrows (meta, MONO_TABLE_TYPEDEF),
903 get_nrows (meta, MONO_TABLE_TYPEREF));
904 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPESPEC));
906 /* 2 bits to encode */
907 field_size = rtsize (meta, n, 16-2);
911 * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
913 case MONO_MT_MRP_IDX:
914 n = MAX (get_nrows (meta, MONO_TABLE_TYPEDEF),
915 get_nrows (meta, MONO_TABLE_TYPEREF));
916 n = MAX (n, get_nrows (meta, MONO_TABLE_METHOD));
917 n = MAX (n, get_nrows (meta, MONO_TABLE_MODULEREF));
918 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPESPEC));
920 /* 3 bits to encode */
921 field_size = rtsize (meta, n, 16 - 3);
925 * MethodDefOrRef: MethodDef, MemberRef
927 case MONO_MT_MDOR_IDX:
928 n = MAX (get_nrows (meta, MONO_TABLE_METHOD),
929 get_nrows (meta, MONO_TABLE_MEMBERREF));
931 /* 1 bit used to encode tag */
932 field_size = rtsize (meta, n, 16-1);
936 * HasSemantics: Property, Event
939 n = MAX (get_nrows (meta, MONO_TABLE_PROPERTY),
940 get_nrows (meta, MONO_TABLE_EVENT));
942 /* 1 bit used to encode tag */
943 field_size = rtsize (meta, n, 16-1);
947 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
950 n = MAX (get_nrows (meta, MONO_TABLE_MODULE),
951 get_nrows (meta, MONO_TABLE_MODULEREF));
952 n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
953 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPEREF));
955 /* 2 bits used to encode tag (ECMA spec claims 3) */
956 field_size = rtsize (meta, n, 16 - 2);
961 * encode field size as follows (we just need to
968 bitfield |= (field_size-1) << shift;
971 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
974 *result_bitfield = (i << 24) | bitfield;
979 * mono_metadata_compute_table_bases:
980 * \param meta metadata context to compute table values
982 * Computes the table bases for the metadata structure.
983 * This is an internal function used by the image loader code.
986 mono_metadata_compute_table_bases (MonoImage *meta)
989 const char *base = meta->tables_base;
991 for (i = 0; i < MONO_TABLE_NUM; i++) {
992 MonoTableInfo *table = &meta->tables [i];
993 if (table->rows == 0)
996 table->row_size = mono_metadata_compute_size (meta, i, &table->size_bitfield);
998 base += table->rows * table->row_size;
1003 * mono_metadata_locate:
1004 * \param meta metadata context
1005 * \param table table code.
1006 * \param idx index of element to retrieve from \p table.
1008 * \returns a pointer to the \p idx element in the metadata table
1009 * whose code is \p table.
1012 mono_metadata_locate (MonoImage *meta, int table, int idx)
1014 /* idx == 0 refers always to NULL */
1015 g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, ""); /*FIXME shouldn't we return NULL here?*/
1017 return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
1021 * mono_metadata_locate_token:
1022 * \param meta metadata context
1023 * \param token metadata token
1025 * \returns a pointer to the data in the metadata represented by the
1029 mono_metadata_locate_token (MonoImage *meta, guint32 token)
1031 return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
1035 * mono_metadata_string_heap:
1036 * \param meta metadata context
1037 * \param index index into the string heap.
1038 * \returns an in-memory pointer to the \p index in the string heap.
1041 mono_metadata_string_heap (MonoImage *meta, guint32 index)
1043 g_assert (index < meta->heap_strings.size);
1044 g_return_val_if_fail (index < meta->heap_strings.size, "");
1045 return meta->heap_strings.data + index;
1049 * mono_metadata_user_string:
1050 * \param meta metadata context
1051 * \param index index into the user string heap.
1052 * \returns an in-memory pointer to the \p index in the user string heap (<code>#US</code>).
1055 mono_metadata_user_string (MonoImage *meta, guint32 index)
1057 g_assert (index < meta->heap_us.size);
1058 g_return_val_if_fail (index < meta->heap_us.size, "");
1059 return meta->heap_us.data + index;
1063 * mono_metadata_blob_heap:
1064 * \param meta metadata context
1065 * \param index index into the blob.
1066 * \returns an in-memory pointer to the \p index in the Blob heap.
1069 mono_metadata_blob_heap (MonoImage *meta, guint32 index)
1071 g_assert (index < meta->heap_blob.size);
1072 g_return_val_if_fail (index < meta->heap_blob.size, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
1073 return meta->heap_blob.data + index;
1077 * mono_metadata_guid_heap:
1078 * \param meta metadata context
1079 * \param index index into the guid heap.
1080 * \returns an in-memory pointer to the \p index in the guid heap.
1083 mono_metadata_guid_heap (MonoImage *meta, guint32 index)
1086 index *= 16; /* adjust for guid size and 1-based index */
1087 g_return_val_if_fail (index < meta->heap_guid.size, "");
1088 return meta->heap_guid.data + index;
1091 static const unsigned char *
1092 dword_align (const unsigned char *ptr)
1094 #if SIZEOF_VOID_P == 8
1095 return (const unsigned char *) (((guint64) (ptr + 3)) & ~3);
1097 return (const unsigned char *) (((guint32) (ptr + 3)) & ~3);
1102 * mono_metadata_decode_row:
1103 * \param t table to extract information from.
1104 * \param idx index in table.
1105 * \param res array of \p res_size cols to store the results in
1107 * This decompresses the metadata element \p idx in table \p t
1108 * into the \c guint32 \p res array that has \p res_size elements
1111 mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size)
1113 guint32 bitfield = t->size_bitfield;
1114 int i, count = mono_metadata_table_count (bitfield);
1117 g_assert (idx < t->rows);
1118 g_assert (idx >= 0);
1119 data = t->base + idx * t->row_size;
1121 g_assert (res_size == count);
1123 for (i = 0; i < count; i++) {
1124 int n = mono_metadata_table_size (bitfield, i);
1128 res [i] = *data; break;
1130 res [i] = read16 (data); break;
1132 res [i] = read32 (data); break;
1134 g_assert_not_reached ();
1141 * mono_metadata_decode_row_col:
1142 * \param t table to extract information from.
1143 * \param idx index for row in table.
1144 * \param col column in the row.
1146 * This function returns the value of column \p col from the \p idx
1147 * row in the table \p t .
1150 mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
1152 guint32 bitfield = t->size_bitfield;
1154 register const char *data;
1157 g_assert (idx < t->rows);
1158 g_assert (col < mono_metadata_table_count (bitfield));
1159 data = t->base + idx * t->row_size;
1161 n = mono_metadata_table_size (bitfield, 0);
1162 for (i = 0; i < col; ++i) {
1164 n = mono_metadata_table_size (bitfield, i + 1);
1170 return read16 (data);
1172 return read32 (data);
1174 g_assert_not_reached ();
1180 * mono_metadata_decode_blob_size:
1181 * \param ptr pointer to a blob object
1182 * \param rptr the new position of the pointer
1184 * This decodes a compressed size as described by 24.2.4 (#US and #Blob a blob or user string object)
1186 * \returns the size of the blob object
1189 mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
1191 const unsigned char *ptr = (const unsigned char *)xptr;
1194 if ((*ptr & 0x80) == 0){
1195 size = ptr [0] & 0x7f;
1197 } else if ((*ptr & 0x40) == 0){
1198 size = ((ptr [0] & 0x3f) << 8) + ptr [1];
1201 size = ((ptr [0] & 0x1f) << 24) +
1213 * mono_metadata_decode_value:
1214 * \param ptr pointer to decode from
1215 * \param rptr the new position of the pointer
1217 * This routine decompresses 32-bit values as specified in the "Blob and
1218 * Signature" section (23.2)
1220 * \returns the decoded value
1223 mono_metadata_decode_value (const char *_ptr, const char **rptr)
1225 const unsigned char *ptr = (const unsigned char *) _ptr;
1226 unsigned char b = *ptr;
1229 if ((b & 0x80) == 0){
1232 } else if ((b & 0x40) == 0){
1233 len = ((b & 0x3f) << 8 | ptr [1]);
1236 len = ((b & 0x1f) << 24) |
1249 * mono_metadata_decode_signed_value:
1250 * \param ptr pointer to decode from
1251 * \param rptr the new position of the pointer
1253 * This routine decompresses 32-bit signed values
1254 * (not specified in the spec)
1256 * \returns the decoded value
1259 mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
1261 guint32 uval = mono_metadata_decode_value (ptr, rptr);
1262 gint32 ival = uval >> 1;
1265 /* ival is a truncated 2's complement negative number. */
1267 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1270 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1271 return ival - 0x2000;
1272 if (ival < 0x10000000)
1273 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1274 return ival - 0x10000000;
1275 g_assert (ival < 0x20000000);
1276 g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival, uval);
1277 return ival - 0x20000000;
1281 * mono_metadata_translate_token_index:
1282 * Translates the given 1-based index into the \c Method, \c Field, \c Event, or \c Param tables
1283 * using the \c *Ptr tables in uncompressed metadata, if they are available.
1285 * FIXME: The caller is not forced to call this function, which is error-prone, since
1286 * forgetting to call it would only show up as a bug on uncompressed metadata.
1289 mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
1291 if (!image->uncompressed_metadata)
1295 case MONO_TABLE_METHOD:
1296 if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
1297 return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
1300 case MONO_TABLE_FIELD:
1301 if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
1302 return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
1305 case MONO_TABLE_EVENT:
1306 if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
1307 return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
1310 case MONO_TABLE_PROPERTY:
1311 if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
1312 return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
1315 case MONO_TABLE_PARAM:
1316 if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
1317 return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
1326 * mono_metadata_decode_table_row:
1328 * Same as \c mono_metadata_decode_row, but takes an \p image + \p table ID pair, and takes
1329 * uncompressed metadata into account, so it should be used to access the
1330 * \c Method, \c Field, \c Param and \c Event tables when the access is made from metadata, i.e.
1331 * \p idx is retrieved from a metadata table, like \c MONO_TYPEDEF_FIELD_LIST.
1334 mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
1336 if (image->uncompressed_metadata)
1337 idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1339 mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
1343 * mono_metadata_decode_table_row_col:
1345 * Same as \c mono_metadata_decode_row_col, but takes an \p image + \p table ID pair, and takes
1346 * uncompressed metadata into account, so it should be used to access the
1347 * \c Method, \c Field, \c Param and \c Event tables.
1349 guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
1351 if (image->uncompressed_metadata)
1352 idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1354 return mono_metadata_decode_row_col (&image->tables [table], idx, col);
1358 * mono_metadata_parse_typedef_or_ref:
1359 * \param m a metadata context.
1360 * \param ptr a pointer to an encoded TypedefOrRef in \p m
1361 * \param rptr pointer updated to match the end of the decoded stream
1362 * \returns a token valid in the \p m metadata decoded from
1363 * the compressed representation.
1366 mono_metadata_parse_typedef_or_ref (MonoImage *m, const char *ptr, const char **rptr)
1369 token = mono_metadata_decode_value (ptr, &ptr);
1372 return mono_metadata_token_from_dor (token);
1376 * mono_metadata_parse_custom_mod:
1377 * \param m a metadata context.
1378 * \param dest storage where the info about the custom modifier is stored (may be NULL)
1379 * \param ptr a pointer to (possibly) the start of a custom modifier list
1380 * \param rptr pointer updated to match the end of the decoded stream
1382 * Checks if \p ptr points to a type custom modifier compressed representation.
1384 * \returns TRUE if a custom modifier was found, FALSE if not.
1387 mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
1389 MonoCustomMod local;
1390 if ((*ptr == MONO_TYPE_CMOD_OPT) || (*ptr == MONO_TYPE_CMOD_REQD)) {
1393 dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
1394 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, rptr);
1401 * mono_metadata_parse_array_internal:
1402 * @m: a metadata context.
1403 * @transient: whenever to allocate data from the heap
1404 * @ptr: a pointer to an encoded array description.
1405 * @rptr: pointer updated to match the end of the decoded stream
1407 * Decodes the compressed array description found in the metadata @m at @ptr.
1409 * Returns: a #MonoArrayType structure describing the array type
1410 * and dimensions. Memory is allocated from the heap or from the image mempool, depending
1411 * on the value of @transient.
1413 * LOCKING: Acquires the loader lock
1415 static MonoArrayType *
1416 mono_metadata_parse_array_internal (MonoImage *m, MonoGenericContainer *container,
1417 gboolean transient, const char *ptr, const char **rptr, MonoError *error)
1420 MonoArrayType *array;
1423 etype = mono_metadata_parse_type_checked (m, container, 0, FALSE, ptr, &ptr, error); //FIXME this doesn't respect @transient
1427 array = transient ? (MonoArrayType *)g_malloc0 (sizeof (MonoArrayType)) : (MonoArrayType *)mono_image_alloc0 (m, sizeof (MonoArrayType));
1428 array->eklass = mono_class_from_mono_type (etype);
1429 array->rank = mono_metadata_decode_value (ptr, &ptr);
1431 array->numsizes = mono_metadata_decode_value (ptr, &ptr);
1432 if (array->numsizes)
1433 array->sizes = transient ? (int *)g_malloc0 (sizeof (int) * array->numsizes) : (int *)mono_image_alloc0 (m, sizeof (int) * array->numsizes);
1434 for (i = 0; i < array->numsizes; ++i)
1435 array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
1437 array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
1438 if (array->numlobounds)
1439 array->lobounds = transient ? (int *)g_malloc0 (sizeof (int) * array->numlobounds) : (int *)mono_image_alloc0 (m, sizeof (int) * array->numlobounds);
1440 for (i = 0; i < array->numlobounds; ++i)
1441 array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr);
1449 * mono_metadata_parse_array:
1452 mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
1455 MonoArrayType *ret = mono_metadata_parse_array_internal (m, NULL, FALSE, ptr, rptr, &error);
1456 mono_error_cleanup (&error);
1462 * mono_metadata_free_array:
1463 * \param array array description
1465 * Frees the array description returned from \c mono_metadata_parse_array.
1468 mono_metadata_free_array (MonoArrayType *array)
1470 g_free (array->sizes);
1471 g_free (array->lobounds);
1476 * need to add common field and param attributes combinations:
1479 * public static literal
1482 * private static literal
1484 static const MonoType
1486 /* data, attrs, type, nmods, byref, pinned */
1487 {{NULL}, 0, MONO_TYPE_VOID, 0, 0, 0},
1488 {{NULL}, 0, MONO_TYPE_BOOLEAN, 0, 0, 0},
1489 {{NULL}, 0, MONO_TYPE_BOOLEAN, 0, 1, 0},
1490 {{NULL}, 0, MONO_TYPE_CHAR, 0, 0, 0},
1491 {{NULL}, 0, MONO_TYPE_CHAR, 0, 1, 0},
1492 {{NULL}, 0, MONO_TYPE_I1, 0, 0, 0},
1493 {{NULL}, 0, MONO_TYPE_I1, 0, 1, 0},
1494 {{NULL}, 0, MONO_TYPE_U1, 0, 0, 0},
1495 {{NULL}, 0, MONO_TYPE_U1, 0, 1, 0},
1496 {{NULL}, 0, MONO_TYPE_I2, 0, 0, 0},
1497 {{NULL}, 0, MONO_TYPE_I2, 0, 1, 0},
1498 {{NULL}, 0, MONO_TYPE_U2, 0, 0, 0},
1499 {{NULL}, 0, MONO_TYPE_U2, 0, 1, 0},
1500 {{NULL}, 0, MONO_TYPE_I4, 0, 0, 0},
1501 {{NULL}, 0, MONO_TYPE_I4, 0, 1, 0},
1502 {{NULL}, 0, MONO_TYPE_U4, 0, 0, 0},
1503 {{NULL}, 0, MONO_TYPE_U4, 0, 1, 0},
1504 {{NULL}, 0, MONO_TYPE_I8, 0, 0, 0},
1505 {{NULL}, 0, MONO_TYPE_I8, 0, 1, 0},
1506 {{NULL}, 0, MONO_TYPE_U8, 0, 0, 0},
1507 {{NULL}, 0, MONO_TYPE_U8, 0, 1, 0},
1508 {{NULL}, 0, MONO_TYPE_R4, 0, 0, 0},
1509 {{NULL}, 0, MONO_TYPE_R4, 0, 1, 0},
1510 {{NULL}, 0, MONO_TYPE_R8, 0, 0, 0},
1511 {{NULL}, 0, MONO_TYPE_R8, 0, 1, 0},
1512 {{NULL}, 0, MONO_TYPE_STRING, 0, 0, 0},
1513 {{NULL}, 0, MONO_TYPE_STRING, 0, 1, 0},
1514 {{NULL}, 0, MONO_TYPE_OBJECT, 0, 0, 0},
1515 {{NULL}, 0, MONO_TYPE_OBJECT, 0, 1, 0},
1516 {{NULL}, 0, MONO_TYPE_TYPEDBYREF, 0, 0, 0},
1517 {{NULL}, 0, MONO_TYPE_I, 0, 0, 0},
1518 {{NULL}, 0, MONO_TYPE_I, 0, 1, 0},
1519 {{NULL}, 0, MONO_TYPE_U, 0, 0, 0},
1520 {{NULL}, 0, MONO_TYPE_U, 0, 1, 0},
1523 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1525 static GHashTable *type_cache = NULL;
1526 static gint32 next_generic_inst_id = 0;
1528 /* Protected by image_sets_mutex */
1529 static MonoImageSet *mscorlib_image_set;
1530 /* Protected by image_sets_mutex */
1531 static GPtrArray *image_sets;
1532 static mono_mutex_t image_sets_mutex;
1534 static guint mono_generic_class_hash (gconstpointer data);
1537 * MonoTypes with modifies are never cached, so we never check or use that field.
1540 mono_type_hash (gconstpointer data)
1542 const MonoType *type = (const MonoType *) data;
1543 if (type->type == MONO_TYPE_GENERICINST)
1544 return mono_generic_class_hash (type->data.generic_class);
1546 return type->type | (type->byref << 8) | (type->attrs << 9);
1550 mono_type_equal (gconstpointer ka, gconstpointer kb)
1552 const MonoType *a = (const MonoType *) ka;
1553 const MonoType *b = (const MonoType *) kb;
1555 if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
1557 /* need other checks */
1562 mono_metadata_generic_inst_hash (gconstpointer data)
1564 const MonoGenericInst *ginst = (const MonoGenericInst *) data;
1568 for (i = 0; i < ginst->type_argc; ++i) {
1570 hash += mono_metadata_type_hash (ginst->type_argv [i]);
1573 return hash ^ (ginst->is_open << 8);
1577 mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b, gboolean signature_only)
1581 // An optimization: if the ids of two insts are the same, we know they are the same inst and don't check contents.
1582 // Furthermore, because we perform early de-duping, if the ids differ, we know the contents differ.
1583 #ifndef MONO_SMALL_CONFIG // Optimization does not work in MONO_SMALL_CONFIG: There are no IDs
1584 if (a->id && b->id) { // "id 0" means "object has no id"-- de-duping hasn't been performed yet, must check contents.
1587 // In signature-comparison mode id equality implies object equality, but this is not true for inequality.
1588 // Two separate objects could have signature-equavalent contents.
1589 if (!signature_only)
1594 if (a->is_open != b->is_open || a->type_argc != b->type_argc)
1596 for (i = 0; i < a->type_argc; ++i) {
1597 if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], signature_only))
1604 mono_metadata_generic_inst_equal (gconstpointer ka, gconstpointer kb)
1606 const MonoGenericInst *a = (const MonoGenericInst *) ka;
1607 const MonoGenericInst *b = (const MonoGenericInst *) kb;
1609 return mono_generic_inst_equal_full (a, b, FALSE);
1613 mono_generic_class_hash (gconstpointer data)
1615 const MonoGenericClass *gclass = (const MonoGenericClass *) data;
1616 guint hash = mono_metadata_type_hash (&gclass->container_class->byval_arg);
1619 hash += gclass->is_tb_open;
1620 hash += mono_metadata_generic_context_hash (&gclass->context);
1626 mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
1628 const MonoGenericClass *a = (const MonoGenericClass *) ka;
1629 const MonoGenericClass *b = (const MonoGenericClass *) kb;
1631 return _mono_metadata_generic_class_equal (a, b, FALSE);
1635 * mono_metadata_init:
1637 * Initialize the global variables of this module.
1638 * This is a Mono runtime internal function.
1641 mono_metadata_init (void)
1645 /* We guard against double initialization due to how pedump in verification mode works.
1646 Until runtime initialization is properly factored to work with what it needs we need workarounds like this.
1647 FIXME: https://bugzilla.xamarin.com/show_bug.cgi?id=58793
1649 static gboolean inited;
1655 type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
1657 for (i = 0; i < NBUILTIN_TYPES (); ++i)
1658 g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
1660 mono_os_mutex_init_recursive (&image_sets_mutex);
1662 mono_counters_register ("ImgSet Cache Hit", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_cache_hit);
1663 mono_counters_register ("ImgSet Cache Miss", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_cache_miss);
1664 mono_counters_register ("ImgSet Count", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_count);
1668 * mono_metadata_cleanup:
1670 * Free all resources used by this module.
1671 * This is a Mono runtime internal function.
1674 mono_metadata_cleanup (void)
1676 g_hash_table_destroy (type_cache);
1678 g_ptr_array_free (image_sets, TRUE);
1680 mono_os_mutex_destroy (&image_sets_mutex);
1684 * mono_metadata_parse_type:
1685 * \param m metadata context
1686 * \param mode kind of type that may be found at \p ptr
1687 * \param opt_attrs optional attributes to store in the returned type
1688 * \param ptr pointer to the type representation
1689 * \param rptr pointer updated to match the end of the decoded stream
1690 * \param transient whenever to allocate the result from the heap or from a mempool
1692 * Decode a compressed type description found at \p ptr in \p m .
1693 * \p mode can be one of \c MONO_PARSE_MOD_TYPE, \c MONO_PARSE_PARAM, \c MONO_PARSE_RET,
1694 * \c MONO_PARSE_FIELD, \c MONO_PARSE_LOCAL, \c MONO_PARSE_TYPE.
1695 * This function can be used to decode type descriptions in method signatures,
1696 * field signatures, locals signatures etc.
1698 * To parse a generic type, \c generic_container points to the current class'es
1699 * (the \c generic_container field in the <code>MonoClass</code>) or the current generic method's
1700 * (stored in <code>image->property_hash</code>) generic container.
1701 * When we encounter a \c MONO_TYPE_VAR or \c MONO_TYPE_MVAR, it's looked up in
1702 * this \c MonoGenericContainer.
1704 * LOCKING: Acquires the loader lock.
1706 * \returns a \c MonoType structure representing the decoded type.
1709 mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container,
1710 short opt_attrs, gboolean transient, const char *ptr, const char **rptr, MonoError *error)
1712 MonoType *type, *cached;
1714 gboolean byref = FALSE;
1715 gboolean pinned = FALSE;
1716 const char *tmp_ptr;
1717 int count = 0; // Number of mod arguments
1723 * According to the spec, custom modifiers should come before the byref
1724 * flag, but the IL produced by ilasm from the following signature:
1725 * object modopt(...) &
1726 * starts with a byref flag, followed by the modifiers. (bug #49802)
1727 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1728 * it would be better to treat byref as real type constructor instead of
1730 * Also, pinned should come before anything else, but some MSV++ produced
1731 * assemblies violate this (#bug 61990).
1734 /* Count the modifiers first */
1739 case MONO_TYPE_PINNED:
1740 case MONO_TYPE_BYREF:
1743 case MONO_TYPE_CMOD_REQD:
1744 case MONO_TYPE_CMOD_OPT:
1746 mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
1753 if (count) { // There are mods, so the MonoType will be of nonstandard size.
1756 size = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
1757 type = transient ? (MonoType *)g_malloc0 (size) : (MonoType *)mono_image_alloc0 (m, size);
1758 type->num_mods = count;
1760 mono_error_set_bad_image (error, m, "Invalid type with more than 64 modifiers");
1763 } else { // The type is of standard size, so we can allocate it on the stack.
1765 memset (type, 0, MONO_SIZEOF_TYPE);
1768 /* Iterate again, but now parse pinned, byref and custom modifiers */
1773 case MONO_TYPE_PINNED:
1777 case MONO_TYPE_BYREF:
1781 case MONO_TYPE_CMOD_REQD:
1782 case MONO_TYPE_CMOD_OPT:
1783 mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
1791 type->attrs = opt_attrs;
1792 type->byref = byref;
1793 type->pinned = pinned ? 1 : 0;
1795 if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr, error))
1801 // Possibly we can return an already-allocated type instead of the one we decoded
1802 if (!type->num_mods && !transient) {
1803 /* no need to free type here, because it is on the stack */
1804 if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
1805 MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
1807 /* Consider the case:
1809 class Foo<T> { class Bar {} }
1810 class Test : Foo<Test>.Bar {}
1812 When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
1813 a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1815 We ensure that the MonoClass is in a state that we can canonicalize to:
1817 klass->byval_arg.data.klass == klass
1818 klass->this_arg.data.klass == klass
1820 If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1822 LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1823 of a MonoClass which currently holds the loader lock. 'type' is local.
1825 if (ret->data.klass == type->data.klass) {
1829 /* No need to use locking since nobody is modifying the hash table */
1830 if ((cached = (MonoType *)g_hash_table_lookup (type_cache, type))) {
1835 /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1837 if (type == &stype) { // Type was allocated on the stack, so we need to copy it to safety
1838 type = transient ? (MonoType *)g_malloc (MONO_SIZEOF_TYPE) : (MonoType *)mono_image_alloc (m, MONO_SIZEOF_TYPE);
1839 memcpy (type, &stype, MONO_SIZEOF_TYPE);
1846 mono_metadata_parse_type_checked (MonoImage *m, MonoGenericContainer *container,
1847 short opt_attrs, gboolean transient, const char *ptr, const char **rptr, MonoError *error)
1849 return mono_metadata_parse_type_internal (m, container, opt_attrs, transient, ptr, rptr, error);
1853 * LOCKING: Acquires the loader lock.
1856 mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
1857 const char *ptr, const char **rptr)
1860 MonoType * type = mono_metadata_parse_type_internal (m, NULL, opt_attrs, FALSE, ptr, rptr, &error);
1861 mono_error_cleanup (&error);
1866 mono_metadata_method_has_param_attrs (MonoImage *m, int def)
1868 MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1869 MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1870 guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1872 if (def < methodt->rows)
1873 lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1875 lastp = m->tables [MONO_TABLE_PARAM].rows + 1;
1877 for (i = param_index; i < lastp; ++i) {
1878 guint32 flags = mono_metadata_decode_row_col (paramt, i - 1, MONO_PARAM_FLAGS);
1887 * mono_metadata_get_param_attrs:
1889 * @m The image to loader parameter attributes from
1890 * @def method def token (one based)
1891 * @param_count number of params to decode including the return value
1893 * Return the parameter attributes for the method whose MethodDef index is DEF. The
1894 * returned memory needs to be freed by the caller. If all the param attributes are
1895 * 0, then NULL is returned.
1898 mono_metadata_get_param_attrs (MonoImage *m, int def, int param_count)
1900 MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1901 MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1902 guint32 cols [MONO_PARAM_SIZE];
1903 guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1906 if (def < methodt->rows)
1907 lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1909 lastp = paramt->rows + 1;
1911 for (i = param_index; i < lastp; ++i) {
1912 mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
1913 if (cols [MONO_PARAM_FLAGS]) {
1915 pattrs = g_new0 (int, param_count);
1916 /* at runtime we just ignore this kind of malformed file:
1917 * the verifier can signal the error to the user
1919 if (cols [MONO_PARAM_SEQUENCE] >= param_count)
1921 pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
1930 * mono_metadata_parse_signature:
1931 * \param image metadata context
1932 * \param token metadata token
1934 * Decode a method signature stored in the \c StandAloneSig table
1936 * \returns a \c MonoMethodSignature describing the signature.
1938 MonoMethodSignature*
1939 mono_metadata_parse_signature (MonoImage *image, guint32 token)
1942 MonoMethodSignature *ret;
1943 ret = mono_metadata_parse_signature_checked (image, token, &error);
1944 mono_error_cleanup (&error);
1949 * mono_metadata_parse_signature_checked:
1950 * @image: metadata context
1951 * @token: metadata token
1952 * @error: set on error
1954 * Decode a method signature stored in the STANDALONESIG table
1956 * Returns: a MonoMethodSignature describing the signature. On failure
1957 * returns NULL and sets @error.
1959 MonoMethodSignature*
1960 mono_metadata_parse_signature_checked (MonoImage *image, guint32 token, MonoError *error)
1964 MonoTableInfo *tables = image->tables;
1965 guint32 idx = mono_metadata_token_index (token);
1969 if (image_is_dynamic (image)) {
1970 return (MonoMethodSignature *)mono_lookup_dynamic_token (image, token, NULL, error);
1973 g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
1975 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
1977 ptr = mono_metadata_blob_heap (image, sig);
1978 mono_metadata_decode_blob_size (ptr, &ptr);
1980 return mono_metadata_parse_method_signature_full (image, NULL, 0, ptr, NULL, error);
1984 * mono_metadata_signature_alloc:
1985 * \param image metadata context
1986 * \param nparams number of parameters in the signature
1988 * Allocate a \c MonoMethodSignature structure with the specified number of params.
1989 * The return type and the params types need to be filled later.
1990 * This is a Mono runtime internal function.
1992 * LOCKING: Assumes the loader lock is held.
1994 * \returns the new \c MonoMethodSignature structure.
1996 MonoMethodSignature*
1997 mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
1999 MonoMethodSignature *sig;
2001 sig = (MonoMethodSignature *)mono_image_alloc0 (m, MONO_SIZEOF_METHOD_SIGNATURE + ((gint32)nparams) * sizeof (MonoType*));
2002 sig->param_count = nparams;
2003 sig->sentinelpos = -1;
2008 static MonoMethodSignature*
2009 mono_metadata_signature_dup_internal_with_padding (MonoImage *image, MonoMemPool *mp, MonoMethodSignature *sig, size_t padding)
2011 int sigsize, sig_header_size;
2012 MonoMethodSignature *ret;
2013 sigsize = sig_header_size = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *) + padding;
2015 sigsize += MONO_SIZEOF_TYPE;
2018 ret = (MonoMethodSignature *)mono_image_alloc (image, sigsize);
2020 ret = (MonoMethodSignature *)mono_mempool_alloc (mp, sigsize);
2022 ret = (MonoMethodSignature *)g_malloc (sigsize);
2025 memcpy (ret, sig, sig_header_size - padding);
2027 // Copy return value because of ownership semantics.
2029 // Danger! Do not alter padding use without changing the dup_add_this below
2030 intptr_t end_of_header = (intptr_t)( (char*)(ret) + sig_header_size);
2031 ret->ret = (MonoType *)end_of_header;
2032 memcpy (ret->ret, sig->ret, MONO_SIZEOF_TYPE);
2038 static MonoMethodSignature*
2039 mono_metadata_signature_dup_internal (MonoImage *image, MonoMemPool *mp, MonoMethodSignature *sig)
2041 return mono_metadata_signature_dup_internal_with_padding (image, mp, sig, 0);
2044 * signature_dup_add_this:
2046 * Make a copy of @sig, adding an explicit this argument.
2048 MonoMethodSignature*
2049 mono_metadata_signature_dup_add_this (MonoImage *image, MonoMethodSignature *sig, MonoClass *klass)
2051 MonoMethodSignature *ret;
2052 ret = mono_metadata_signature_dup_internal_with_padding (image, NULL, sig, sizeof (MonoType *));
2054 ret->param_count = sig->param_count + 1;
2055 ret->hasthis = FALSE;
2057 for (int i = sig->param_count - 1; i >= 0; i --)
2058 ret->params [i + 1] = sig->params [i];
2059 ret->params [0] = klass->valuetype ? &klass->this_arg : &klass->byval_arg;
2061 for (int i = sig->param_count - 1; i >= 0; i --)
2062 g_assert(ret->params [i + 1]->type == sig->params [i]->type && ret->params [i+1]->type != MONO_TYPE_END);
2063 g_assert (ret->ret->type == sig->ret->type && ret->ret->type != MONO_TYPE_END);
2070 MonoMethodSignature*
2071 mono_metadata_signature_dup_full (MonoImage *image, MonoMethodSignature *sig)
2073 MonoMethodSignature *ret = mono_metadata_signature_dup_internal (image, NULL, sig);
2075 for (int i = 0 ; i < sig->param_count; i ++)
2076 g_assert(ret->params [i]->type == sig->params [i]->type);
2077 g_assert (ret->ret->type == sig->ret->type);
2082 /*The mempool is accessed without synchronization*/
2083 MonoMethodSignature*
2084 mono_metadata_signature_dup_mempool (MonoMemPool *mp, MonoMethodSignature *sig)
2086 return mono_metadata_signature_dup_internal (NULL, mp, sig);
2090 * mono_metadata_signature_dup:
2091 * \param sig method signature
2093 * Duplicate an existing \c MonoMethodSignature so it can be modified.
2094 * This is a Mono runtime internal function.
2096 * \returns the new \c MonoMethodSignature structure.
2098 MonoMethodSignature*
2099 mono_metadata_signature_dup (MonoMethodSignature *sig)
2101 return mono_metadata_signature_dup_full (NULL, sig);
2105 * mono_metadata_signature_size:
2107 * Return the amount of memory allocated to SIG.
2110 mono_metadata_signature_size (MonoMethodSignature *sig)
2112 return MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
2116 * mono_metadata_parse_method_signature:
2117 * @m: metadata context
2118 * @generic_container: generics container
2119 * @def: the MethodDef index or 0 for Ref signatures.
2120 * @ptr: pointer to the signature metadata representation
2121 * @rptr: pointer updated to match the end of the decoded stream
2123 * Decode a method signature stored at @ptr.
2124 * This is a Mono runtime internal function.
2126 * LOCKING: Assumes the loader lock is held.
2128 * Returns: a MonoMethodSignature describing the signature.
2130 MonoMethodSignature *
2131 mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container,
2132 int def, const char *ptr, const char **rptr, MonoError *error)
2134 MonoMethodSignature *method;
2135 int i, *pattrs = NULL;
2136 guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
2137 guint32 gen_param_count = 0;
2138 gboolean is_open = FALSE;
2143 gen_param_count = 1;
2148 call_convention = *ptr & 0x0F;
2150 if (gen_param_count)
2151 gen_param_count = mono_metadata_decode_value (ptr, &ptr);
2152 param_count = mono_metadata_decode_value (ptr, &ptr);
2155 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 */
2157 method = mono_metadata_signature_alloc (m, param_count);
2158 method->hasthis = hasthis;
2159 method->explicit_this = explicit_this;
2160 method->call_convention = call_convention;
2161 method->generic_param_count = gen_param_count;
2163 if (call_convention != 0xa) {
2164 method->ret = mono_metadata_parse_type_checked (m, container, pattrs ? pattrs [0] : 0, FALSE, ptr, &ptr, error);
2166 mono_metadata_free_method_signature (method);
2170 is_open = mono_class_is_open_constructed_type (method->ret);
2173 for (i = 0; i < method->param_count; ++i) {
2174 if (*ptr == MONO_TYPE_SENTINEL) {
2175 if (method->call_convention != MONO_CALL_VARARG || def) {
2176 mono_error_set_bad_image (error, m, "Found sentinel for methoddef or no vararg");
2180 if (method->sentinelpos >= 0) {
2181 mono_error_set_bad_image (error, m, "Found sentinel twice in the same signature.");
2185 method->sentinelpos = i;
2188 method->params [i] = mono_metadata_parse_type_checked (m, container, pattrs ? pattrs [i+1] : 0, FALSE, ptr, &ptr, error);
2189 if (!method->params [i]) {
2190 mono_metadata_free_method_signature (method);
2195 is_open = mono_class_is_open_constructed_type (method->params [i]);
2198 /* The sentinel could be missing if the caller does not pass any additional arguments */
2199 if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0)
2200 method->sentinelpos = method->param_count;
2202 method->has_type_parameters = is_open;
2204 if (def && (method->call_convention == MONO_CALL_VARARG))
2205 method->sentinelpos = method->param_count;
2212 * Add signature to a cache and increase ref count...
2219 * mono_metadata_parse_method_signature:
2220 * \param m metadata context
2221 * \param def the \c MethodDef index or 0 for \c Ref signatures.
2222 * \param ptr pointer to the signature metadata representation
2223 * \param rptr pointer updated to match the end of the decoded stream
2225 * Decode a method signature stored at \p ptr.
2226 * This is a Mono runtime internal function.
2228 * LOCKING: Assumes the loader lock is held.
2230 * \returns a \c MonoMethodSignature describing the signature.
2232 MonoMethodSignature *
2233 mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
2236 * This function MUST NOT be called by runtime code as it does error handling incorrectly.
2237 * Use mono_metadata_parse_method_signature_full instead.
2238 * It's ok to asser on failure as we no longer use it.
2241 MonoMethodSignature *ret;
2242 ret = mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr, &error);
2243 g_assert (mono_error_ok (&error));
2249 * mono_metadata_free_method_signature:
2250 * \param sig signature to destroy
2252 * Free the memory allocated in the signature \p sig.
2253 * This method needs to be robust and work also on partially-built
2254 * signatures, so it does extra checks.
2257 mono_metadata_free_method_signature (MonoMethodSignature *sig)
2259 /* Everything is allocated from mempools */
2263 mono_metadata_free_type (sig->ret);
2264 for (i = 0; i < sig->param_count; ++i) {
2265 if (sig->params [i])
2266 mono_metadata_free_type (sig->params [i]);
2272 mono_metadata_free_inflated_signature (MonoMethodSignature *sig)
2276 /* Allocated in inflate_generic_signature () */
2278 mono_metadata_free_type (sig->ret);
2279 for (i = 0; i < sig->param_count; ++i) {
2280 if (sig->params [i])
2281 mono_metadata_free_type (sig->params [i]);
2287 inflated_method_equal (gconstpointer a, gconstpointer b)
2289 const MonoMethodInflated *ma = (const MonoMethodInflated *)a;
2290 const MonoMethodInflated *mb = (const MonoMethodInflated *)b;
2291 if (ma->declaring != mb->declaring)
2293 return mono_metadata_generic_context_equal (&ma->context, &mb->context);
2297 inflated_method_hash (gconstpointer a)
2299 const MonoMethodInflated *ma = (const MonoMethodInflated *)a;
2300 return (mono_metadata_generic_context_hash (&ma->context) ^ mono_aligned_addr_hash (ma->declaring));
2304 inflated_signature_equal (gconstpointer a, gconstpointer b)
2306 const MonoInflatedMethodSignature *sig1 = (const MonoInflatedMethodSignature *)a;
2307 const MonoInflatedMethodSignature *sig2 = (const MonoInflatedMethodSignature *)b;
2309 /* sig->sig is assumed to be canonized */
2310 if (sig1->sig != sig2->sig)
2312 /* The generic instances are canonized */
2313 return mono_metadata_generic_context_equal (&sig1->context, &sig2->context);
2317 inflated_signature_hash (gconstpointer a)
2319 const MonoInflatedMethodSignature *sig = (const MonoInflatedMethodSignature *)a;
2321 /* sig->sig is assumed to be canonized */
2322 return mono_metadata_generic_context_hash (&sig->context) ^ mono_aligned_addr_hash (sig->sig);
2326 dump_ginst (MonoGenericInst *ginst)
2331 g_print ("Ginst: <");
2332 for (i = 0; i < ginst->type_argc; ++i) {
2335 name = mono_type_get_name (ginst->type_argv [i]);
2336 g_print ("%s", name);
2342 static gboolean type_in_image (MonoType *type, MonoImage *image);
2345 signature_in_image (MonoMethodSignature *sig, MonoImage *image)
2347 gpointer iter = NULL;
2350 while ((p = mono_signature_get_params (sig, &iter)) != NULL)
2351 if (type_in_image (p, image))
2354 return type_in_image (mono_signature_get_return_type (sig), image);
2358 ginst_in_image (MonoGenericInst *ginst, MonoImage *image)
2362 for (i = 0; i < ginst->type_argc; ++i) {
2363 if (type_in_image (ginst->type_argv [i], image))
2371 gclass_in_image (MonoGenericClass *gclass, MonoImage *image)
2373 return gclass->container_class->image == image ||
2374 ginst_in_image (gclass->context.class_inst, image);
2378 type_in_image (MonoType *type, MonoImage *image)
2381 switch (type->type) {
2382 case MONO_TYPE_GENERICINST:
2383 return gclass_in_image (type->data.generic_class, image);
2385 type = type->data.type;
2387 case MONO_TYPE_SZARRAY:
2388 type = &type->data.klass->byval_arg;
2390 case MONO_TYPE_ARRAY:
2391 type = &type->data.array->eklass->byval_arg;
2393 case MONO_TYPE_FNPTR:
2394 return signature_in_image (type->data.method, image);
2396 case MONO_TYPE_MVAR:
2397 return image == get_image_for_generic_param (type->data.generic_param);
2399 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2400 return image == mono_class_from_mono_type (type)->image;
2405 image_sets_lock (void)
2407 mono_os_mutex_lock (&image_sets_mutex);
2411 image_sets_unlock (void)
2413 mono_os_mutex_unlock (&image_sets_mutex);
2417 compare_pointers (const void *a, const void *b)
2419 return (size_t)a - (size_t)b;
2423 #define HASH_TABLE_SIZE 1103
2424 static MonoImageSet *img_set_cache [HASH_TABLE_SIZE];
2427 mix_hash (uintptr_t source)
2429 unsigned int hash = source;
2432 hash = (((hash * 215497) >> 16) ^ ((hash * 1823231) + hash));
2434 // Mix in highest bits on 64-bit systems only
2435 if (sizeof (source) > 4)
2436 hash = hash ^ (source >> 32);
2442 hash_images (MonoImage **images, int nimages)
2446 for (i = 0; i < nimages; ++i)
2447 res += mix_hash ((size_t)images [i]);
2453 compare_img_set (MonoImageSet *set, MonoImage **images, int nimages)
2457 if (set->nimages != nimages)
2460 for (j = 0; j < nimages; ++j) {
2461 for (k = 0; k < nimages; ++k)
2462 if (set->images [k] == images [j])
2463 break; // Break on match
2465 // If we iterated all the way through set->images, images[j] was *not* found.
2467 break; // Break on "image not found"
2470 // If we iterated all the way through images without breaking, all items in images were found in set->images
2471 return j == nimages;
2475 static MonoImageSet*
2476 img_set_cache_get (MonoImage **images, int nimages)
2478 guint32 hash_code = hash_images (images, nimages);
2479 int index = hash_code % HASH_TABLE_SIZE;
2480 MonoImageSet *img = img_set_cache [index];
2481 if (!img || !compare_img_set (img, images, nimages)) {
2482 UnlockedIncrement (&img_set_cache_miss);
2485 UnlockedIncrement (&img_set_cache_hit);
2490 img_set_cache_add (MonoImageSet *set)
2492 guint32 hash_code = hash_images (set->images, set->nimages);
2493 int index = hash_code % HASH_TABLE_SIZE;
2494 img_set_cache [index] = set;
2498 img_set_cache_remove (MonoImageSet *is)
2500 guint32 hash_code = hash_images (is->images, is->nimages);
2501 int index = hash_code % HASH_TABLE_SIZE;
2502 if (img_set_cache [index] == is)
2503 img_set_cache [index] = NULL;
2508 * Return a MonoImageSet representing the set of images in IMAGES.
2510 static MonoImageSet*
2511 get_image_set (MonoImage **images, int nimages)
2517 /* Common case: Image set contains corlib only. If we've seen that case before, we cached the set. */
2518 if (nimages == 1 && images [0] == mono_defaults.corlib && mscorlib_image_set)
2519 return mscorlib_image_set;
2521 /* Happens with empty generic instances */
2522 // 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.
2524 return mscorlib_image_set;
2526 set = img_set_cache_get (images, nimages);
2533 image_sets = g_ptr_array_new ();
2535 // Before we go on, we should check to see whether a MonoImageSet with these images already exists.
2536 // We can search the referred-by imagesets of any one of our images to do this. Arbitrarily pick one here:
2537 if (images [0] == mono_defaults.corlib && nimages > 1)
2538 l = images [1]->image_sets; // Prefer not to search the imagesets of corlib-- that will be a long list.
2540 l = images [0]->image_sets;
2543 while (l) // Iterate over selected list, looking for an imageset with members equal to our target one
2545 set = (MonoImageSet *)l->data;
2547 if (set->nimages == nimages) { // Member count differs, this can't be it
2548 // Compare all members to all members-- order might be different
2549 for (j = 0; j < nimages; ++j) {
2550 for (k = 0; k < nimages; ++k)
2551 if (set->images [k] == images [j])
2552 break; // Break on match
2554 // If we iterated all the way through set->images, images[j] was *not* found.
2556 break; // Break on "image not found"
2559 // If we iterated all the way through images without breaking, all items in images were found in set->images
2561 // Break on "found a set with equal members".
2562 // This happens in case of a hash collision with a previously cached set.
2570 // If we iterated all the way through l without breaking, the imageset does not already exist and we should create it
2572 set = g_new0 (MonoImageSet, 1);
2573 set->nimages = nimages;
2574 set->images = g_new0 (MonoImage*, nimages);
2575 mono_os_mutex_init_recursive (&set->lock);
2576 for (i = 0; i < nimages; ++i)
2577 set->images [i] = images [i];
2578 set->gclass_cache = mono_conc_hashtable_new_full (mono_generic_class_hash, mono_generic_class_equal, NULL, (GDestroyNotify)free_generic_class);
2579 set->ginst_cache = g_hash_table_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst);
2580 set->gmethod_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method);
2581 set->gsignature_cache = g_hash_table_new_full (inflated_signature_hash, inflated_signature_equal, NULL, (GDestroyNotify)free_inflated_signature);
2583 for (i = 0; i < nimages; ++i)
2584 set->images [i]->image_sets = g_slist_prepend (set->images [i]->image_sets, set);
2586 g_ptr_array_add (image_sets, set);
2587 UnlockedIncrement (&img_set_count); /* locked by image_sets_lock () */
2590 /* Cache the set. If there was a cache collision, the previously cached value will be replaced. */
2591 img_set_cache_add (set);
2593 if (nimages == 1 && images [0] == mono_defaults.corlib) {
2594 mono_memory_barrier ();
2595 mscorlib_image_set = set;
2598 image_sets_unlock ();
2604 delete_image_set (MonoImageSet *set)
2608 mono_conc_hashtable_destroy (set->gclass_cache);
2609 g_hash_table_destroy (set->ginst_cache);
2610 g_hash_table_destroy (set->gmethod_cache);
2611 g_hash_table_destroy (set->gsignature_cache);
2613 mono_wrapper_caches_free (&set->wrapper_caches);
2617 for (i = 0; i < set->nimages; ++i)
2618 set->images [i]->image_sets = g_slist_remove (set->images [i]->image_sets, set);
2620 g_ptr_array_remove (image_sets, set);
2622 image_sets_unlock ();
2624 img_set_cache_remove (set);
2627 mono_mempool_destroy (set->mempool);
2628 g_free (set->images);
2629 mono_os_mutex_destroy (&set->lock);
2634 mono_image_set_lock (MonoImageSet *set)
2636 mono_os_mutex_lock (&set->lock);
2640 mono_image_set_unlock (MonoImageSet *set)
2642 mono_os_mutex_unlock (&set->lock);
2646 mono_image_set_alloc (MonoImageSet *set, guint size)
2650 mono_image_set_lock (set);
2652 set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE);
2653 res = mono_mempool_alloc (set->mempool, size);
2654 mono_image_set_unlock (set);
2660 mono_image_set_alloc0 (MonoImageSet *set, guint size)
2664 mono_image_set_lock (set);
2666 set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE);
2667 res = mono_mempool_alloc0 (set->mempool, size);
2668 mono_image_set_unlock (set);
2674 mono_image_set_strdup (MonoImageSet *set, const char *s)
2678 mono_image_set_lock (set);
2680 set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE);
2681 res = mono_mempool_strdup (set->mempool, s);
2682 mono_image_set_unlock (set);
2687 // Get a descriptive string for a MonoImageSet
2688 // Callers are obligated to free buffer with g_free after use
2690 mono_image_set_description (MonoImageSet *set)
2692 GString *result = g_string_new (NULL);
2694 g_string_append (result, "[");
2695 for (img = 0; img < set->nimages; img++)
2698 g_string_append (result, ", ");
2699 g_string_append (result, set->images[img]->name);
2701 g_string_append (result, "]");
2702 return g_string_free (result, FALSE);
2706 * Structure used by the collect_..._images functions to store the image list.
2709 MonoImage *image_buf [64];
2711 int nimages, images_len;
2715 collect_data_init (CollectData *data)
2717 data->images = data->image_buf;
2718 data->images_len = 64;
2723 collect_data_free (CollectData *data)
2725 if (data->images != data->image_buf)
2726 g_free (data->images);
2730 enlarge_data (CollectData *data)
2732 int new_len = data->images_len < 16 ? 16 : data->images_len * 2;
2733 MonoImage **d = g_new (MonoImage *, new_len);
2736 g_assert_not_reached ();
2737 memcpy (d, data->images, data->images_len);
2738 if (data->images != data->image_buf)
2739 g_free (data->images);
2741 data->images_len = new_len;
2745 add_image (MonoImage *image, CollectData *data)
2749 /* The arrays are small, so use a linear search instead of a hash table */
2750 for (i = 0; i < data->nimages; ++i)
2751 if (data->images [i] == image)
2754 if (data->nimages == data->images_len)
2755 enlarge_data (data);
2757 data->images [data->nimages ++] = image;
2761 collect_type_images (MonoType *type, CollectData *data);
2764 collect_ginst_images (MonoGenericInst *ginst, CollectData *data)
2768 for (i = 0; i < ginst->type_argc; ++i) {
2769 collect_type_images (ginst->type_argv [i], data);
2774 collect_gclass_images (MonoGenericClass *gclass, CollectData *data)
2776 add_image (gclass->container_class->image, data);
2777 if (gclass->context.class_inst)
2778 collect_ginst_images (gclass->context.class_inst, data);
2782 collect_signature_images (MonoMethodSignature *sig, CollectData *data)
2784 gpointer iter = NULL;
2787 collect_type_images (mono_signature_get_return_type (sig), data);
2788 while ((p = mono_signature_get_params (sig, &iter)) != NULL)
2789 collect_type_images (p, data);
2793 collect_inflated_signature_images (MonoInflatedMethodSignature *sig, CollectData *data)
2795 collect_signature_images (sig->sig, data);
2796 if (sig->context.class_inst)
2797 collect_ginst_images (sig->context.class_inst, data);
2798 if (sig->context.method_inst)
2799 collect_ginst_images (sig->context.method_inst, data);
2803 collect_method_images (MonoMethodInflated *method, CollectData *data)
2805 MonoMethod *m = method->declaring;
2807 add_image (method->declaring->klass->image, data);
2808 if (method->context.class_inst)
2809 collect_ginst_images (method->context.class_inst, data);
2810 if (method->context.method_inst)
2811 collect_ginst_images (method->context.method_inst, data);
2813 * Dynamic assemblies have no references, so the images they depend on can be unloaded before them.
2815 if (image_is_dynamic (m->klass->image))
2816 collect_signature_images (mono_method_signature (m), data);
2820 collect_type_images (MonoType *type, CollectData *data)
2823 switch (type->type) {
2824 case MONO_TYPE_GENERICINST:
2825 collect_gclass_images (type->data.generic_class, data);
2828 type = type->data.type;
2830 case MONO_TYPE_SZARRAY:
2831 type = &type->data.klass->byval_arg;
2833 case MONO_TYPE_ARRAY:
2834 type = &type->data.array->eklass->byval_arg;
2836 case MONO_TYPE_FNPTR:
2837 //return signature_in_image (type->data.method, image);
2838 g_assert_not_reached ();
2840 case MONO_TYPE_MVAR:
2842 MonoImage *image = get_image_for_generic_param (type->data.generic_param);
2843 add_image (image, data);
2846 case MONO_TYPE_CLASS:
2847 case MONO_TYPE_VALUETYPE:
2848 add_image (mono_class_from_mono_type (type)->image, data);
2851 add_image (mono_defaults.corlib, data);
2858 } CleanForImageUserData;
2861 steal_gclass_in_image (gpointer key, gpointer value, gpointer data)
2863 MonoGenericClass *gclass = (MonoGenericClass *)key;
2864 CleanForImageUserData *user_data = (CleanForImageUserData *)data;
2866 g_assert (gclass_in_image (gclass, user_data->image));
2868 user_data->list = g_slist_prepend (user_data->list, gclass);
2873 steal_ginst_in_image (gpointer key, gpointer value, gpointer data)
2875 MonoGenericInst *ginst = (MonoGenericInst *)key;
2876 CleanForImageUserData *user_data = (CleanForImageUserData *)data;
2878 // This doesn't work during corlib compilation
2879 //g_assert (ginst_in_image (ginst, user_data->image));
2881 user_data->list = g_slist_prepend (user_data->list, ginst);
2886 inflated_method_in_image (gpointer key, gpointer value, gpointer data)
2888 MonoImage *image = (MonoImage *)data;
2889 MonoMethodInflated *method = (MonoMethodInflated *)key;
2892 // https://bugzilla.novell.com/show_bug.cgi?id=458168
2893 g_assert (method->declaring->klass->image == image ||
2894 (method->context.class_inst && ginst_in_image (method->context.class_inst, image)) ||
2895 (method->context.method_inst && ginst_in_image (method->context.method_inst, image)) || (((MonoMethod*)method)->signature && signature_in_image (mono_method_signature ((MonoMethod*)method), image)));
2901 inflated_signature_in_image (gpointer key, gpointer value, gpointer data)
2903 MonoImage *image = (MonoImage *)data;
2904 MonoInflatedMethodSignature *sig = (MonoInflatedMethodSignature *)key;
2906 return signature_in_image (sig->sig, image) ||
2907 (sig->context.class_inst && ginst_in_image (sig->context.class_inst, image)) ||
2908 (sig->context.method_inst && ginst_in_image (sig->context.method_inst, image));
2912 check_gmethod (gpointer key, gpointer value, gpointer data)
2914 MonoMethodInflated *method = (MonoMethodInflated *)key;
2915 MonoImage *image = (MonoImage *)data;
2917 if (method->context.class_inst)
2918 g_assert (!ginst_in_image (method->context.class_inst, image));
2919 if (method->context.method_inst)
2920 g_assert (!ginst_in_image (method->context.method_inst, image));
2921 if (((MonoMethod*)method)->signature)
2922 g_assert (!signature_in_image (mono_method_signature ((MonoMethod*)method), image));
2928 * Run a consistency check on the image set data structures.
2930 static G_GNUC_UNUSED void
2931 check_image_sets (MonoImage *image)
2934 GSList *l = image->image_sets;
2939 for (i = 0; i < image_sets->len; ++i) {
2940 MonoImageSet *set = (MonoImageSet *)g_ptr_array_index (image_sets, i);
2942 if (!g_slist_find (l, set)) {
2943 g_hash_table_foreach (set->gmethod_cache, check_gmethod, image);
2949 mono_metadata_clean_for_image (MonoImage *image)
2951 CleanForImageUserData ginst_data, gclass_data;
2952 GSList *l, *set_list;
2954 //check_image_sets (image);
2957 * The data structures could reference each other so we delete them in two phases.
2958 * This is required because of the hashing functions in gclass/ginst_cache.
2960 ginst_data.image = gclass_data.image = image;
2961 ginst_data.list = gclass_data.list = NULL;
2963 /* Collect the items to delete */
2964 /* delete_image_set () modifies the lists so make a copy */
2965 for (l = image->image_sets; l; l = l->next) {
2966 MonoImageSet *set = (MonoImageSet *)l->data;
2968 mono_image_set_lock (set);
2969 mono_conc_hashtable_foreach_steal (set->gclass_cache, steal_gclass_in_image, &gclass_data);
2970 g_hash_table_foreach_steal (set->ginst_cache, steal_ginst_in_image, &ginst_data);
2971 g_hash_table_foreach_remove (set->gmethod_cache, inflated_method_in_image, image);
2972 g_hash_table_foreach_remove (set->gsignature_cache, inflated_signature_in_image, image);
2973 mono_image_set_unlock (set);
2976 /* Delete the removed items */
2977 for (l = ginst_data.list; l; l = l->next)
2978 free_generic_inst ((MonoGenericInst *)l->data);
2979 for (l = gclass_data.list; l; l = l->next)
2980 free_generic_class ((MonoGenericClass *)l->data);
2981 g_slist_free (ginst_data.list);
2982 g_slist_free (gclass_data.list);
2983 /* delete_image_set () modifies the lists so make a copy */
2984 set_list = g_slist_copy (image->image_sets);
2985 for (l = set_list; l; l = l->next) {
2986 MonoImageSet *set = (MonoImageSet *)l->data;
2988 delete_image_set (set);
2990 g_slist_free (set_list);
2994 free_inflated_method (MonoMethodInflated *imethod)
2996 MonoMethod *method = (MonoMethod*)imethod;
2998 if (method->signature)
2999 mono_metadata_free_inflated_signature (method->signature);
3001 if (method->wrapper_type)
3002 g_free (((MonoMethodWrapper*)method)->method_data);
3008 free_generic_inst (MonoGenericInst *ginst)
3012 /* The ginst itself is allocated from the image set mempool */
3013 for (i = 0; i < ginst->type_argc; ++i)
3014 mono_metadata_free_type (ginst->type_argv [i]);
3018 free_generic_class (MonoGenericClass *gclass)
3020 /* The gclass itself is allocated from the image set mempool */
3021 if (gclass->cached_class && gclass->cached_class->interface_id)
3022 mono_unload_interface_id (gclass->cached_class);
3026 free_inflated_signature (MonoInflatedMethodSignature *sig)
3028 mono_metadata_free_inflated_signature (sig->sig);
3033 * mono_metadata_get_inflated_signature:
3035 * Given an inflated signature and a generic context, return a canonical copy of the
3036 * signature. The returned signature might be equal to SIG or it might be a cached copy.
3038 MonoMethodSignature *
3039 mono_metadata_get_inflated_signature (MonoMethodSignature *sig, MonoGenericContext *context)
3041 MonoInflatedMethodSignature helper;
3042 MonoInflatedMethodSignature *res;
3047 helper.context.class_inst = context->class_inst;
3048 helper.context.method_inst = context->method_inst;
3050 collect_data_init (&data);
3052 collect_inflated_signature_images (&helper, &data);
3054 set = get_image_set (data.images, data.nimages);
3056 collect_data_free (&data);
3058 mono_image_set_lock (set);
3060 res = (MonoInflatedMethodSignature *)g_hash_table_lookup (set->gsignature_cache, &helper);
3062 res = g_new0 (MonoInflatedMethodSignature, 1);
3064 res->context.class_inst = context->class_inst;
3065 res->context.method_inst = context->method_inst;
3066 g_hash_table_insert (set->gsignature_cache, res, res);
3069 mono_image_set_unlock (set);
3075 mono_metadata_get_image_set_for_method (MonoMethodInflated *method)
3078 CollectData image_set_data;
3080 collect_data_init (&image_set_data);
3081 collect_method_images (method, &image_set_data);
3082 set = get_image_set (image_set_data.images, image_set_data.nimages);
3083 collect_data_free (&image_set_data);
3089 type_is_gtd (MonoType *type)
3091 switch (type->type) {
3092 case MONO_TYPE_CLASS:
3093 case MONO_TYPE_VALUETYPE:
3094 return mono_class_is_gtd (type->data.klass);
3101 * mono_metadata_get_generic_inst:
3103 * Given a list of types, return a MonoGenericInst that represents that list.
3104 * The returned MonoGenericInst has its own copy of the list of types. The list
3105 * passed in the argument can be freed, modified or disposed of.
3109 mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
3111 MonoGenericInst *ginst;
3114 int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
3116 for (i = 0; i < type_argc; ++i)
3117 if (mono_class_is_open_constructed_type (type_argv [i]))
3119 is_open = (i < type_argc);
3121 ginst = (MonoGenericInst *)g_alloca (size);
3122 memset (ginst, 0, sizeof (MonoGenericInst));
3123 ginst->is_open = is_open;
3124 ginst->type_argc = type_argc;
3125 memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
3127 for (i = 0; i < type_argc; ++i) {
3128 MonoType *t = ginst->type_argv [i];
3129 if (type_is_gtd (t)) {
3130 ginst->type_argv [i] = mono_class_gtd_get_canonical_inst (t->data.klass);
3134 return mono_metadata_get_canonical_generic_inst (ginst);
3139 * mono_metadata_get_canonical_generic_inst:
3140 * \param candidate an arbitrary generic instantiation
3142 * \returns the canonical generic instantiation that represents the given
3143 * candidate by identifying the image set for the candidate instantiation and
3144 * finding the instance in the image set or adding a copy of the given instance
3147 * The returned MonoGenericInst has its own copy of the list of types. The list
3148 * passed in the argument can be freed, modified or disposed of.
3152 mono_metadata_get_canonical_generic_inst (MonoGenericInst *candidate)
3155 int type_argc = candidate->type_argc;
3156 gboolean is_open = candidate->is_open;
3159 collect_data_init (&data);
3161 collect_ginst_images (candidate, &data);
3163 set = get_image_set (data.images, data.nimages);
3165 collect_data_free (&data);
3167 mono_image_set_lock (set);
3169 MonoGenericInst *ginst = (MonoGenericInst *)g_hash_table_lookup (set->ginst_cache, candidate);
3171 int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
3172 ginst = (MonoGenericInst *)mono_image_set_alloc0 (set, size);
3173 #ifndef MONO_SMALL_CONFIG
3174 ginst->id = InterlockedIncrement (&next_generic_inst_id);
3176 ginst->is_open = is_open;
3177 ginst->type_argc = type_argc;
3179 for (int i = 0; i < type_argc; ++i)
3180 ginst->type_argv [i] = mono_metadata_type_dup (NULL, candidate->type_argv [i]);
3182 g_hash_table_insert (set->ginst_cache, ginst, ginst);
3185 mono_image_set_unlock (set);
3190 mono_metadata_is_type_builder_generic_type_definition (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
3192 MonoGenericContainer *container = mono_class_get_generic_container (container_class);
3194 if (!is_dynamic || container_class->wastypebuilder || container->type_argc != inst->type_argc)
3196 return inst == container->context.class_inst;
3200 * mono_metadata_lookup_generic_class:
3202 * Returns a MonoGenericClass with the given properties.
3206 mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
3208 MonoGenericClass *gclass;
3209 MonoGenericClass helper;
3210 gboolean is_tb_open = mono_metadata_is_type_builder_generic_type_definition (container_class, inst, is_dynamic);
3214 g_assert (mono_class_get_generic_container (container_class)->type_argc == inst->type_argc);
3216 memset (&helper, 0, sizeof(helper)); // act like g_new0
3217 helper.container_class = container_class;
3218 helper.context.class_inst = inst;
3219 helper.is_dynamic = is_dynamic; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
3220 helper.is_tb_open = is_tb_open;
3222 collect_data_init (&data);
3224 collect_gclass_images (&helper, &data);
3226 set = get_image_set (data.images, data.nimages);
3228 collect_data_free (&data);
3230 gclass = (MonoGenericClass *)mono_conc_hashtable_lookup (set->gclass_cache, &helper);
3232 /* A tripwire just to keep us honest */
3233 g_assert (!helper.cached_class);
3238 gclass = mono_image_set_new0 (set, MonoGenericClass, 1);
3240 gclass->is_dynamic = 1;
3242 gclass->is_tb_open = is_tb_open;
3243 gclass->container_class = container_class;
3244 gclass->context.class_inst = inst;
3245 gclass->context.method_inst = NULL;
3246 gclass->owner = set;
3247 if (inst == mono_class_get_generic_container (container_class)->context.class_inst && !is_tb_open)
3248 gclass->cached_class = container_class;
3250 mono_image_set_lock (set);
3252 MonoGenericClass *gclass2 = mono_conc_hashtable_insert (set->gclass_cache, gclass, gclass);
3256 // g_hash_table_insert (set->gclass_cache, gclass, gclass);
3258 mono_image_set_unlock (set);
3264 * mono_metadata_inflate_generic_inst:
3266 * Instantiate the generic instance @ginst with the context @context.
3267 * Check @error for success.
3271 mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context, MonoError *error)
3273 MonoType **type_argv;
3274 MonoGenericInst *nginst = NULL;
3279 if (!ginst->is_open)
3282 type_argv = g_new0 (MonoType*, ginst->type_argc);
3284 for (i = 0; i < ginst->type_argc; i++) {
3285 type_argv [i] = mono_class_inflate_generic_type_checked (ginst->type_argv [i], context, error);
3286 if (!mono_error_ok (error))
3291 nginst = mono_metadata_get_generic_inst (ginst->type_argc, type_argv);
3294 for (i = 0; i < count; i++)
3295 mono_metadata_free_type (type_argv [i]);
3302 mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container,
3303 int count, const char *ptr, const char **rptr, MonoError *error)
3305 MonoType **type_argv;
3306 MonoGenericInst *ginst;
3310 type_argv = g_new0 (MonoType*, count);
3312 for (i = 0; i < count; i++) {
3313 MonoType *t = mono_metadata_parse_type_checked (m, container, 0, FALSE, ptr, &ptr, error);
3324 ginst = mono_metadata_get_generic_inst (count, type_argv);
3332 do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
3333 const char *ptr, const char **rptr, MonoError *error)
3335 MonoGenericInst *inst;
3342 // XXX how about transient?
3343 gtype = mono_metadata_parse_type_checked (m, NULL, 0, FALSE, ptr, &ptr, error);
3347 gklass = mono_class_from_mono_type (gtype);
3348 if (!mono_class_is_gtd (gklass)) {
3349 mono_error_set_bad_image (error, m, "Generic instance with non-generic definition");
3353 count = mono_metadata_decode_value (ptr, &ptr);
3354 inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr, error);
3361 type->data.generic_class = mono_metadata_lookup_generic_class (gklass, inst, FALSE);
3367 * @gc: The generic container to normalize
3368 * @type: The kind of generic parameters the resulting generic-container should contain
3371 static MonoGenericContainer *
3372 select_container (MonoGenericContainer *gc, MonoTypeEnum type)
3374 gboolean is_var = (type == MONO_TYPE_VAR);
3378 g_assert (is_var || type == MONO_TYPE_MVAR);
3381 if (gc->is_method || gc->parent)
3383 * The current MonoGenericContainer is a generic method -> its `parent'
3384 * points to the containing class'es container.
3392 MonoGenericContainer *
3393 get_anonymous_container_for_image (MonoImage *image, gboolean is_mvar)
3395 MonoGenericContainer **container_pointer;
3397 container_pointer = &image->anonymous_generic_method_container;
3399 container_pointer = &image->anonymous_generic_class_container;
3400 MonoGenericContainer *result = *container_pointer;
3402 // This container has never been created; make it now.
3405 // Note this is never deallocated anywhere-- it exists for the lifetime of the image it's allocated from
3406 result = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
3407 result->owner.image = image;
3408 result->is_anonymous = TRUE;
3409 result->is_small_param = TRUE;
3410 result->is_method = is_mvar;
3412 // If another thread already made a container, use that and leak this new one.
3413 // (Technically it would currently be safe to just assign instead of CASing.)
3414 MonoGenericContainer *exchange = (MonoGenericContainer *)InterlockedCompareExchangePointer ((volatile gpointer *)container_pointer, result, NULL);
3422 * mono_metadata_parse_generic_param:
3423 * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3424 * see mono_metadata_parse_type_checked() for details.
3425 * Internal routine to parse a generic type parameter.
3426 * LOCKING: Acquires the loader lock
3428 static MonoGenericParam *
3429 mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
3430 MonoTypeEnum type, const char *ptr, const char **rptr, MonoError *error)
3432 int index = mono_metadata_decode_value (ptr, &ptr);
3438 generic_container = select_container (generic_container, type);
3439 if (!generic_container) {
3440 gboolean is_mvar = FALSE;
3445 case MONO_TYPE_MVAR:
3449 g_error ("Cerating generic param object with invalid MonoType"); // This is not a generic param
3452 /* Create dummy MonoGenericParam */
3453 MonoGenericParam *param;
3455 param = (MonoGenericParam *)mono_image_alloc0 (m, sizeof (MonoGenericParam));
3457 param->owner = get_anonymous_container_for_image (m, is_mvar);
3462 if (index >= generic_container->type_argc) {
3463 mono_error_set_bad_image (error, m, "Invalid generic %s parameter index %d, max index is %d",
3464 generic_container->is_method ? "method" : "type",
3465 index, generic_container->type_argc);
3469 //This can't return NULL
3470 return mono_generic_container_get_param (generic_container, index);
3474 * mono_metadata_get_shared_type:
3476 * Return a shared instance of TYPE, if available, NULL otherwise.
3477 * Shared MonoType instances help save memory. Their contents should not be modified
3478 * by the caller. They do not need to be freed as their lifetime is bound by either
3479 * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3480 * instance they are embedded in. If they are freed, they should be freed using
3481 * mono_metadata_free_type () instead of g_free ().
3484 mono_metadata_get_shared_type (MonoType *type)
3488 /* No need to use locking since nobody is modifying the hash table */
3489 if ((cached = (MonoType *)g_hash_table_lookup (type_cache, type)))
3492 switch (type->type){
3493 case MONO_TYPE_CLASS:
3494 case MONO_TYPE_VALUETYPE:
3495 if (type == &type->data.klass->byval_arg)
3497 if (type == &type->data.klass->this_arg)
3508 compare_type_literals (MonoImage *image, int class_type, int type_type, MonoError *error)
3512 /* byval_arg.type can be zero if we're decoding a type that references a class been loading.
3513 * See mcs/test/gtest-440. and #650936.
3514 * FIXME This better be moved to the metadata verifier as it can catch more cases.
3518 /* NET 1.1 assemblies might encode string and object in a denormalized way.
3521 if (class_type == type_type)
3524 if (type_type == MONO_TYPE_CLASS) {
3525 if (class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT)
3527 //XXX stringify this argument
3528 mono_error_set_bad_image (error, image, "Expected reference type but got type kind %d", class_type);
3532 g_assert (type_type == MONO_TYPE_VALUETYPE);
3533 switch (class_type) {
3534 case MONO_TYPE_BOOLEAN:
3535 case MONO_TYPE_CHAR:
3548 case MONO_TYPE_CLASS:
3551 //XXX stringify this argument
3552 mono_error_set_bad_image (error, image, "Expected value type but got type kind %d", class_type);
3558 verify_var_type_and_container (MonoImage *image, int var_type, MonoGenericContainer *container, MonoError *error)
3561 if (var_type == MONO_TYPE_MVAR) {
3562 if (!container->is_method) { //MVAR and a method container
3563 mono_error_set_bad_image (error, image, "MVAR parsed in a context without a method container");
3567 if (!(!container->is_method || //VAR and class container
3568 (container->is_method && container->parent))) { //VAR and method container with parent
3569 mono_error_set_bad_image (error, image, "VAR parsed in a context without a class container");
3577 * do_mono_metadata_parse_type:
3578 * @type: MonoType to be filled in with the return value
3580 * @generic_context: generics_context
3581 * @transient: whenever to allocate data from the heap
3582 * @ptr: pointer to the encoded type
3583 * @rptr: pointer where the end of the encoded type is saved
3585 * Internal routine used to "fill" the contents of @type from an
3586 * allocated pointer. This is done this way to avoid doing too
3587 * many mini-allocations (particularly for the MonoFieldType which
3588 * most of the time is just a MonoType, but sometimes might be augmented).
3590 * This routine is used by mono_metadata_parse_type and
3591 * mono_metadata_parse_field_type
3593 * This extracts a Type as specified in Partition II (22.2.12)
3595 * Returns: FALSE if the type could not be loaded
3598 do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
3599 gboolean transient, const char *ptr, const char **rptr, MonoError *error)
3603 type->type = (MonoTypeEnum)mono_metadata_decode_value (ptr, &ptr);
3605 switch (type->type){
3606 case MONO_TYPE_VOID:
3607 case MONO_TYPE_BOOLEAN:
3608 case MONO_TYPE_CHAR:
3621 case MONO_TYPE_STRING:
3622 case MONO_TYPE_OBJECT:
3623 case MONO_TYPE_TYPEDBYREF:
3625 case MONO_TYPE_VALUETYPE:
3626 case MONO_TYPE_CLASS: {
3629 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
3630 klass = mono_class_get_checked (m, token, error);
3631 type->data.klass = klass;
3635 if (!compare_type_literals (m, klass->byval_arg.type, type->type, error))
3640 case MONO_TYPE_SZARRAY: {
3641 MonoType *etype = mono_metadata_parse_type_checked (m, container, 0, transient, ptr, &ptr, error);
3645 type->data.klass = mono_class_from_mono_type (etype);
3648 mono_metadata_free_type (etype);
3650 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.
3653 case MONO_TYPE_PTR: {
3654 type->data.type = mono_metadata_parse_type_checked (m, container, 0, transient, ptr, &ptr, error);
3655 if (!type->data.type)
3659 case MONO_TYPE_FNPTR: {
3660 type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr, error);
3661 if (!type->data.method)
3665 case MONO_TYPE_ARRAY: {
3666 type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr, error);
3667 if (!type->data.array)
3671 case MONO_TYPE_MVAR:
3672 case MONO_TYPE_VAR: {
3673 if (container && !verify_var_type_and_container (m, type->type, container, error))
3676 type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr, error);
3677 if (!type->data.generic_param)
3682 case MONO_TYPE_GENERICINST: {
3683 if (!do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr, error))
3688 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);
3698 * mono_metadata_free_type:
3699 * \param type type to free
3701 * Free the memory allocated for type \p type which is allocated on the heap.
3704 mono_metadata_free_type (MonoType *type)
3706 if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
3709 switch (type->type){
3710 case MONO_TYPE_OBJECT:
3711 case MONO_TYPE_STRING:
3712 if (!type->data.klass)
3715 case MONO_TYPE_CLASS:
3716 case MONO_TYPE_VALUETYPE:
3717 if (type == &type->data.klass->byval_arg || type == &type->data.klass->this_arg)
3721 mono_metadata_free_type (type->data.type);
3723 case MONO_TYPE_FNPTR:
3724 mono_metadata_free_method_signature (type->data.method);
3726 case MONO_TYPE_ARRAY:
3727 mono_metadata_free_array (type->data.array);
3738 hex_dump (const char *buffer, int base, int count)
3740 int show_header = 1;
3748 for (i = 0; i < count; i++){
3751 printf ("\n0x%08x: ", (unsigned char) base + i);
3753 printf ("%02x ", (unsigned char) (buffer [i]));
3760 * @ptr: Points to the beginning of the Section Data (25.3)
3762 static MonoExceptionClause*
3763 parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr, MonoError *error)
3765 unsigned char sect_data_flags;
3767 guint32 sect_data_len;
3768 MonoExceptionClause* clauses = NULL;
3773 /* align on 32-bit boundary */
3774 ptr = dword_align (ptr);
3775 sect_data_flags = *ptr;
3778 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
3780 sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
3783 sect_data_len = ptr [0];
3787 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
3788 const unsigned char *p = dword_align (ptr);
3790 *num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
3791 /* we could just store a pointer if we don't need to byteswap */
3792 clauses = (MonoExceptionClause *)g_malloc0 (sizeof (MonoExceptionClause) * (*num_clauses));
3793 for (i = 0; i < *num_clauses; ++i) {
3794 MonoExceptionClause *ec = &clauses [i];
3797 ec->flags = read32 (p);
3798 ec->try_offset = read32 (p + 4);
3799 ec->try_len = read32 (p + 8);
3800 ec->handler_offset = read32 (p + 12);
3801 ec->handler_len = read32 (p + 16);
3802 tof_value = read32 (p + 20);
3805 ec->flags = read16 (p);
3806 ec->try_offset = read16 (p + 2);
3807 ec->try_len = *(p + 4);
3808 ec->handler_offset = read16 (p + 5);
3809 ec->handler_len = *(p + 7);
3810 tof_value = read32 (p + 8);
3813 if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
3814 ec->data.filter_offset = tof_value;
3815 } else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) {
3816 ec->data.catch_class = NULL;
3818 ec->data.catch_class = mono_class_get_checked (m, tof_value, error);
3819 if (!is_ok (error)) {
3825 ec->data.catch_class = NULL;
3827 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
3831 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
3832 ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
3839 * mono_method_get_header_summary:
3840 * @method: The method to get the header.
3841 * @summary: Where to store the header
3844 * Returns: TRUE if the header was properly decoded.
3847 mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *summary)
3853 unsigned char flags, format;
3856 /*Only the GMD has a pointer to the metadata.*/
3857 while (method->is_inflated)
3858 method = ((MonoMethodInflated*)method)->declaring;
3860 summary->code_size = 0;
3861 summary->has_clauses = FALSE;
3863 /*FIXME extract this into a MACRO and share it with mono_method_get_header*/
3864 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))
3867 if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) {
3868 MonoMethodHeader *header = ((MonoMethodWrapper *)method)->header;
3871 summary->code_size = header->code_size;
3872 summary->has_clauses = header->num_clauses > 0;
3877 idx = mono_metadata_token_index (method->token);
3878 img = method->klass->image;
3879 rva = mono_metadata_decode_row_col (&img->tables [MONO_TABLE_METHOD], idx - 1, MONO_METHOD_RVA);
3881 /*We must run the verifier since we'll be decoding it.*/
3882 if (!mono_verifier_verify_method_header (img, rva, NULL))
3885 ptr = mono_image_rva_map (img, rva);
3889 flags = *(const unsigned char *)ptr;
3890 format = flags & METHOD_HEADER_FORMAT_MASK;
3893 case METHOD_HEADER_TINY_FORMAT:
3895 summary->code_size = flags >> 2;
3897 case METHOD_HEADER_FAT_FORMAT:
3898 fat_flags = read16 (ptr);
3900 summary->code_size = read32 (ptr);
3901 if (fat_flags & METHOD_HEADER_MORE_SECTS)
3902 summary->has_clauses = TRUE;
3911 * mono_metadata_parse_mh_full:
3912 * @m: metadata context
3913 * @generic_context: generics context
3914 * @ptr: pointer to the method header.
3916 * Decode the method header at @ptr, including pointer to the IL code,
3917 * info about local variables and optional exception tables.
3918 * This is a Mono runtime internal function.
3920 * LOCKING: Acquires the loader lock.
3922 * Returns: a transient MonoMethodHeader allocated from the heap.
3925 mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr, MonoError *error)
3927 MonoMethodHeader *mh = NULL;
3928 unsigned char flags = *(const unsigned char *) ptr;
3929 unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
3931 guint32 local_var_sig_tok, max_stack, code_size, init_locals;
3932 const unsigned char *code;
3933 MonoExceptionClause* clauses = NULL;
3934 int num_clauses = 0;
3935 MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
3936 guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
3941 mono_error_set_bad_image (error, m, "Method header with null pointer");
3946 case METHOD_HEADER_TINY_FORMAT:
3947 mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER);
3950 mh->is_transient = TRUE;
3951 local_var_sig_tok = 0;
3952 mh->code_size = flags >> 2;
3953 mh->code = (unsigned char*)ptr;
3955 case METHOD_HEADER_FAT_FORMAT:
3956 fat_flags = read16 (ptr);
3958 max_stack = read16 (ptr);
3960 code_size = read32 (ptr);
3962 local_var_sig_tok = read32 (ptr);
3965 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
3970 code = (unsigned char*)ptr;
3972 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
3976 * There are more sections
3978 ptr = (char*)code + code_size;
3981 mono_error_set_bad_image (error, m, "Invalid method header format %d", format);
3985 if (local_var_sig_tok) {
3986 int idx = (local_var_sig_tok & 0xffffff)-1;
3987 if (idx >= t->rows || idx < 0) {
3988 mono_error_set_bad_image (error, m, "Invalid method header local vars signature token 0x%8x", idx);
3991 mono_metadata_decode_row (t, idx, cols, 1);
3993 if (!mono_verifier_verify_standalone_signature (m, cols [MONO_STAND_ALONE_SIGNATURE], NULL)) {
3994 mono_error_set_bad_image (error, m, "Method header locals signature 0x%8x verification failed", idx);
3998 if (fat_flags & METHOD_HEADER_MORE_SECTS) {
3999 clauses = parse_section_data (m, &num_clauses, (const unsigned char*)ptr, error);
4003 if (local_var_sig_tok) {
4004 const char *locals_ptr;
4007 locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
4008 mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
4009 if (*locals_ptr != 0x07)
4010 g_warning ("wrong signature for locals blob");
4012 len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
4013 mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*) + num_clauses * sizeof (MonoExceptionClause));
4014 mh->num_locals = len;
4015 for (i = 0; i < len; ++i) {
4016 mh->locals [i] = mono_metadata_parse_type_internal (m, container, 0, TRUE, locals_ptr, &locals_ptr, error);
4021 mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause));
4024 mh->code_size = code_size;
4025 mh->max_stack = max_stack;
4026 mh->is_transient = TRUE;
4027 mh->init_locals = init_locals;
4029 MonoExceptionClause* clausesp = (MonoExceptionClause*)&mh->locals [mh->num_locals];
4030 memcpy (clausesp, clauses, num_clauses * sizeof (MonoExceptionClause));
4032 mh->clauses = clausesp;
4033 mh->num_clauses = num_clauses;
4044 * mono_metadata_parse_mh:
4045 * \param generic_context generics context
4046 * \param ptr pointer to the method header.
4048 * Decode the method header at \p ptr, including pointer to the IL code,
4049 * info about local variables and optional exception tables.
4051 * \returns a transient \c MonoMethodHeader allocated from the heap.
4054 mono_metadata_parse_mh (MonoImage *m, const char *ptr)
4057 MonoMethodHeader *header = mono_metadata_parse_mh_full (m, NULL, ptr, &error);
4058 mono_error_cleanup (&error);
4063 * mono_metadata_free_mh:
4064 * \param mh a method header
4066 * Free the memory allocated for the method header.
4069 mono_metadata_free_mh (MonoMethodHeader *mh)
4073 /* If it is not transient it means it's part of a wrapper method,
4074 * or a SRE-generated method, so the lifetime in that case is
4075 * dictated by the method's own lifetime
4077 if (mh->is_transient) {
4078 for (i = 0; i < mh->num_locals; ++i)
4079 mono_metadata_free_type (mh->locals [i]);
4085 * mono_method_header_get_code:
4086 * \param header a \c MonoMethodHeader pointer
4087 * \param code_size memory location for returning the code size
4088 * \param max_stack memory location for returning the max stack
4090 * Method header accessor to retreive info about the IL code properties:
4091 * a pointer to the IL code itself, the size of the code and the max number
4092 * of stack slots used by the code.
4094 * \returns pointer to the IL code represented by the method header.
4096 const unsigned char*
4097 mono_method_header_get_code (MonoMethodHeader *header, guint32* code_size, guint32* max_stack)
4100 *code_size = header->code_size;
4102 *max_stack = header->max_stack;
4103 return header->code;
4107 * mono_method_header_get_locals:
4108 * \param header a \c MonoMethodHeader pointer
4109 * \param num_locals memory location for returning the number of local variables
4110 * \param init_locals memory location for returning the init_locals flag
4112 * Method header accessor to retreive info about the local variables:
4113 * an array of local types, the number of locals and whether the locals
4114 * are supposed to be initialized to 0 on method entry
4116 * \returns pointer to an array of types of the local variables
4119 mono_method_header_get_locals (MonoMethodHeader *header, guint32* num_locals, gboolean *init_locals)
4122 *num_locals = header->num_locals;
4124 *init_locals = header->init_locals;
4125 return header->locals;
4129 * mono_method_header_get_num_clauses:
4130 * @header: a MonoMethodHeader pointer
4132 * Method header accessor to retreive the number of exception clauses.
4134 * Returns: the number of exception clauses present
4137 mono_method_header_get_num_clauses (MonoMethodHeader *header)
4139 return header->num_clauses;
4143 * mono_method_header_get_clauses:
4144 * \param header a \c MonoMethodHeader pointer
4145 * \param method \c MonoMethod the header belongs to
4146 * \param iter pointer to a iterator
4147 * \param clause pointer to a \c MonoExceptionClause structure which will be filled with the info
4149 * Get the info about the exception clauses in the method. Set \c *iter to NULL to
4150 * initiate the iteration, then call the method repeatedly until it returns FALSE.
4151 * At each iteration, the structure pointed to by clause if filled with the
4152 * exception clause information.
4154 * \returns TRUE if clause was filled with info, FALSE if there are no more exception
4158 mono_method_header_get_clauses (MonoMethodHeader *header, MonoMethod *method, gpointer *iter, MonoExceptionClause *clause)
4160 MonoExceptionClause *sc;
4161 /* later we'll be able to use this interface to parse the clause info on demand,
4162 * without allocating anything.
4164 if (!iter || !header->num_clauses)
4167 *iter = sc = header->clauses;
4171 sc = (MonoExceptionClause *)*iter;
4173 if (sc < header->clauses + header->num_clauses) {
4182 * mono_metadata_parse_field_type:
4183 * \param m metadata context to extract information from
4184 * \param ptr pointer to the field signature
4185 * \param rptr pointer updated to match the end of the decoded stream
4187 * Parses the field signature, and returns the type information for it.
4189 * \returns The \c MonoType that was extracted from \p ptr .
4192 mono_metadata_parse_field_type (MonoImage *m, short field_flags, const char *ptr, const char **rptr)
4195 MonoType * type = mono_metadata_parse_type_internal (m, NULL, field_flags, FALSE, ptr, rptr, &error);
4196 mono_error_cleanup (&error);
4201 * mono_metadata_parse_param:
4202 * \param m metadata context to extract information from
4203 * \param ptr pointer to the param signature
4204 * \param rptr pointer updated to match the end of the decoded stream
4206 * Parses the param signature, and returns the type information for it.
4208 * \returns The \c MonoType that was extracted from \p ptr .
4211 mono_metadata_parse_param (MonoImage *m, const char *ptr, const char **rptr)
4214 MonoType * type = mono_metadata_parse_type_internal (m, NULL, 0, FALSE, ptr, rptr, &error);
4215 mono_error_cleanup (&error);
4220 * mono_metadata_token_from_dor:
4221 * \param dor_token A \c TypeDefOrRef coded index
4223 * \p dor_token is a \c TypeDefOrRef coded index: it contains either
4224 * a \c TypeDef, \c TypeRef or \c TypeSpec in the lower bits, and the upper
4225 * bits contain an index into the table.
4227 * \returns an expanded token
4230 mono_metadata_token_from_dor (guint32 dor_index)
4234 table = dor_index & 0x03;
4235 idx = dor_index >> 2;
4238 case 0: /* TypeDef */
4239 return MONO_TOKEN_TYPE_DEF | idx;
4240 case 1: /* TypeRef */
4241 return MONO_TOKEN_TYPE_REF | idx;
4242 case 2: /* TypeSpec */
4243 return MONO_TOKEN_TYPE_SPEC | idx;
4245 g_assert_not_reached ();
4252 * We use this to pass context information to the row locator
4255 int idx; /* The index that we are trying to locate */
4256 int col_idx; /* The index in the row where idx may be stored */
4257 MonoTableInfo *t; /* pointer to the table */
4262 * How the row locator works.
4267 * ___|___------> _______
4270 * A column in the rows of table A references an index in table B.
4271 * For example A may be the TYPEDEF table and B the METHODDEF table.
4273 * Given an index in table B we want to get the row in table A
4274 * where the column n references our index in B.
4276 * In the locator_t structure:
4278 * col_idx is the column number
4279 * index is the index in table B
4280 * result will be the index in table A
4283 * Table A Table B column (in table A)
4284 * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
4285 * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
4286 * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
4287 * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
4288 * METHODSEM PROPERTY ASSOCIATION (encoded index)
4290 * Note that we still don't support encoded indexes.
4294 typedef_locator (const void *a, const void *b)
4296 locator_t *loc = (locator_t *) a;
4297 const char *bb = (const char *) b;
4298 int typedef_index = (bb - loc->t->base) / loc->t->row_size;
4299 guint32 col, col_next;
4301 col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx);
4307 * Need to check that the next row is valid.
4309 if (typedef_index + 1 < loc->t->rows) {
4310 col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx);
4311 if (loc->idx >= col_next)
4314 if (col == col_next)
4318 loc->result = typedef_index;
4324 table_locator (const void *a, const void *b)
4326 locator_t *loc = (locator_t *) a;
4327 const char *bb = (const char *) b;
4328 guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
4331 col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
4333 if (loc->idx == col) {
4334 loc->result = table_index;
4344 declsec_locator (const void *a, const void *b)
4346 locator_t *loc = (locator_t *) a;
4347 const char *bb = (const char *) b;
4348 guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
4351 col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
4353 if (loc->idx == col) {
4354 loc->result = table_index;
4366 * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
4367 * which contains IDX.
4370 search_ptr_table (MonoImage *image, int table, int idx)
4372 MonoTableInfo *ptrdef = &image->tables [table];
4375 /* Use a linear search to find our index in the table */
4376 for (i = 0; i < ptrdef->rows; i ++)
4377 /* All the Ptr tables have the same structure */
4378 if (mono_metadata_decode_row_col (ptrdef, i, 0) == idx)
4381 if (i < ptrdef->rows)
4388 * mono_metadata_typedef_from_field:
4389 * \param meta metadata context
4390 * \param index FieldDef token
4392 * \returns the 1-based index into the \c TypeDef table of the type that
4393 * declared the field described by \p index, or 0 if not found.
4396 mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
4398 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
4404 loc.idx = mono_metadata_token_index (index);
4405 loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
4408 if (meta->uncompressed_metadata)
4409 loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
4411 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
4414 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4415 return loc.result + 1;
4419 * mono_metadata_typedef_from_method:
4420 * \param meta metadata context
4421 * \param index \c MethodDef token
4422 * \returns the 1-based index into the \c TypeDef table of the type that
4423 * declared the method described by \p index. 0 if not found.
4426 mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
4428 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
4434 loc.idx = mono_metadata_token_index (index);
4435 loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
4438 if (meta->uncompressed_metadata)
4439 loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx);
4441 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
4444 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4445 return loc.result + 1;
4449 * mono_metadata_interfaces_from_typedef_full:
4450 * @meta: metadata context
4451 * @index: typedef token
4452 * @interfaces: Out parameter used to store the interface array
4453 * @count: Out parameter used to store the number of interfaces
4454 * @heap_alloc_result: if TRUE the result array will be g_malloc'd
4455 * @context: The generic context
4457 * The array of interfaces that the @index typedef token implements is returned in
4458 * @interfaces. The number of elements in the array is returned in @count.
4461 * Returns: TRUE on success, FALSE on failure.
4464 mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context, MonoError *error)
4466 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
4469 guint32 cols [MONO_INTERFACEIMPL_SIZE];
4480 loc.idx = mono_metadata_token_index (index);
4481 loc.col_idx = MONO_INTERFACEIMPL_CLASS;
4484 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4489 * We may end up in the middle of the rows...
4492 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_INTERFACEIMPL_CLASS))
4498 while (pos < tdef->rows) {
4499 mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
4500 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
4505 if (heap_alloc_result)
4506 result = g_new0 (MonoClass*, pos - start);
4508 result = (MonoClass **)mono_image_alloc0 (meta, sizeof (MonoClass*) * (pos - start));
4511 while (pos < tdef->rows) {
4514 mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
4515 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
4517 iface = mono_class_get_and_inflate_typespec_checked (
4518 meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context, error);
4521 result [pos - start] = iface;
4524 *count = pos - start;
4525 *interfaces = result;
4530 * mono_metadata_interfaces_from_typedef:
4531 * \param meta metadata context
4532 * \param index typedef token
4533 * \param count Out parameter used to store the number of interfaces
4535 * The array of interfaces that the \p index typedef token implements is returned in
4536 * \p interfaces. The number of elements in the array is returned in \p count. The returned
4537 * array is allocated with \c g_malloc and the caller must free it.
4539 * LOCKING: Acquires the loader lock .
4541 * \returns the interface array on success, NULL on failure.
4544 mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
4547 MonoClass **interfaces = NULL;
4550 rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, TRUE, NULL, &error);
4551 g_assert (mono_error_ok (&error)); /* FIXME dont swallow the error */
4559 * mono_metadata_nested_in_typedef:
4560 * \param meta metadata context
4561 * \param index typedef token
4562 * \returns the 1-based index into the TypeDef table of the type
4563 * where the type described by \p index is nested.
4564 * Returns 0 if \p index describes a non-nested type.
4567 mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
4569 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
4575 loc.idx = mono_metadata_token_index (index);
4576 loc.col_idx = MONO_NESTED_CLASS_NESTED;
4579 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4582 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4583 return mono_metadata_decode_row_col (tdef, loc.result, MONO_NESTED_CLASS_ENCLOSING) | MONO_TOKEN_TYPE_DEF;
4587 * mono_metadata_nesting_typedef:
4588 * \param meta metadata context
4589 * \param index typedef token
4590 * \returns the 1-based index into the \c TypeDef table of the first type
4591 * that is nested inside the type described by \p index. The search starts at
4592 * \p start_index. Returns 0 if no such type is found.
4595 mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
4597 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
4599 guint32 class_index = mono_metadata_token_index (index);
4604 start = start_index;
4606 while (start <= tdef->rows) {
4607 if (class_index == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
4613 if (start > tdef->rows)
4620 * mono_metadata_packing_from_typedef:
4621 * \param meta metadata context
4622 * \param index token representing a type
4623 * \returns the info stored in the \c ClassLayout table for the given typedef token
4624 * into the \p packing and \p size pointers.
4625 * Returns 0 if the info is not found.
4628 mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *packing, guint32 *size)
4630 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CLASSLAYOUT];
4632 guint32 cols [MONO_CLASS_LAYOUT_SIZE];
4637 loc.idx = mono_metadata_token_index (index);
4638 loc.col_idx = MONO_CLASS_LAYOUT_PARENT;
4641 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4644 mono_metadata_decode_row (tdef, loc.result, cols, MONO_CLASS_LAYOUT_SIZE);
4646 *packing = cols [MONO_CLASS_LAYOUT_PACKING_SIZE];
4648 *size = cols [MONO_CLASS_LAYOUT_CLASS_SIZE];
4650 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4651 return loc.result + 1;
4655 * mono_metadata_custom_attrs_from_index:
4656 * \param meta metadata context
4657 * \param index token representing the parent
4658 * \returns: the 1-based index into the \c CustomAttribute table of the first
4659 * attribute which belongs to the metadata object described by \p index.
4660 * Returns 0 if no such attribute is found.
4663 mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
4665 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4672 loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
4675 /* FIXME: Index translation */
4677 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4680 /* Find the first entry by searching backwards */
4681 while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_CUSTOM_ATTR_PARENT) == index))
4684 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4685 return loc.result + 1;
4689 * mono_metadata_declsec_from_index:
4690 * \param meta metadata context
4691 * \param index token representing the parent
4692 * \returns the 0-based index into the \c DeclarativeSecurity table of the first
4693 * attribute which belongs to the metadata object described by \p index.
4694 * Returns \c -1 if no such attribute is found.
4697 mono_metadata_declsec_from_index (MonoImage *meta, guint32 index)
4699 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_DECLSECURITY];
4706 loc.col_idx = MONO_DECL_SECURITY_PARENT;
4709 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
4712 /* Find the first entry by searching backwards */
4713 while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_DECL_SECURITY_PARENT) == index))
4720 * mono_metadata_localscope_from_methoddef:
4721 * @meta: metadata context
4722 * @index: methoddef index
4724 * Returns: the 1-based index into the LocalScope table of the first
4725 * scope which belongs to the method described by @index.
4726 * Returns 0 if no such row is found.
4729 mono_metadata_localscope_from_methoddef (MonoImage *meta, guint32 index)
4731 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_LOCALSCOPE];
4738 loc.col_idx = MONO_LOCALSCOPE_METHOD;
4741 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4744 /* Find the first entry by searching backwards */
4745 while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_LOCALSCOPE_METHOD) == index))
4748 return loc.result + 1;
4753 mono_backtrace (int limit)
4758 backtrace (array, limit);
4759 names = backtrace_symbols (array, limit);
4760 for (i =0; i < limit; ++i) {
4761 g_print ("\t%s\n", names [i]);
4767 static int i8_align;
4770 * mono_type_set_alignment:
4772 * Set the alignment used by runtime to layout fields etc. of type TYPE to ALIGN.
4773 * This should only be used in AOT mode since the resulting layout will not match the
4777 mono_type_set_alignment (MonoTypeEnum type, int align)
4779 /* Support only a few types whose alignment is abi dependent */
4785 g_assert_not_reached ();
4792 * \param t the type to return the size of
4793 * \returns The number of bytes required to hold an instance of this
4797 mono_type_size (MonoType *t, int *align)
4799 MonoTypeEnum simple_type;
4806 *align = MONO_ABI_ALIGNOF (gpointer);
4807 return MONO_ABI_SIZEOF (gpointer);
4810 simple_type = t->type;
4812 switch (simple_type) {
4813 case MONO_TYPE_VOID:
4816 case MONO_TYPE_BOOLEAN:
4817 *align = MONO_ABI_ALIGNOF (gint8);
4821 *align = MONO_ABI_ALIGNOF (gint8);
4823 case MONO_TYPE_CHAR:
4826 *align = MONO_ABI_ALIGNOF (gint16);
4830 *align = MONO_ABI_ALIGNOF (gint32);
4833 *align = MONO_ABI_ALIGNOF (float);
4837 *align = MONO_ABI_ALIGNOF (gint64);
4840 *align = MONO_ABI_ALIGNOF (double);
4844 *align = MONO_ABI_ALIGNOF (gpointer);
4845 return MONO_ABI_SIZEOF (gpointer);
4846 case MONO_TYPE_VALUETYPE: {
4847 if (t->data.klass->enumtype)
4848 return mono_type_size (mono_class_enum_basetype (t->data.klass), align);
4850 return mono_class_value_size (t->data.klass, (guint32*)align);
4852 case MONO_TYPE_STRING:
4853 case MONO_TYPE_OBJECT:
4854 case MONO_TYPE_CLASS:
4855 case MONO_TYPE_SZARRAY:
4857 case MONO_TYPE_FNPTR:
4858 case MONO_TYPE_ARRAY:
4859 *align = MONO_ABI_ALIGNOF (gpointer);
4860 return MONO_ABI_SIZEOF (gpointer);
4861 case MONO_TYPE_TYPEDBYREF:
4862 return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align);
4863 case MONO_TYPE_GENERICINST: {
4864 MonoGenericClass *gclass = t->data.generic_class;
4865 MonoClass *container_class = gclass->container_class;
4867 // g_assert (!gclass->inst->is_open);
4869 if (container_class->valuetype) {
4870 if (container_class->enumtype)
4871 return mono_type_size (mono_class_enum_basetype (container_class), align);
4873 return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
4875 *align = MONO_ABI_ALIGNOF (gpointer);
4876 return MONO_ABI_SIZEOF (gpointer);
4880 case MONO_TYPE_MVAR:
4881 if (!t->data.generic_param->gshared_constraint || t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE) {
4882 *align = MONO_ABI_ALIGNOF (gpointer);
4883 return MONO_ABI_SIZEOF (gpointer);
4885 /* The gparam can only match types given by gshared_constraint */
4886 return mono_type_size (t->data.generic_param->gshared_constraint, align);
4890 g_error ("mono_type_size: type 0x%02x unknown", t->type);
4896 * mono_type_stack_size:
4897 * \param t the type to return the size it uses on the stack
4898 * \returns The number of bytes required to hold an instance of this
4899 * type on the runtime stack
4902 mono_type_stack_size (MonoType *t, int *align)
4904 return mono_type_stack_size_internal (t, align, FALSE);
4908 mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
4911 MonoTypeEnum simple_type;
4912 #if SIZEOF_VOID_P == SIZEOF_REGISTER
4913 int stack_slot_size = MONO_ABI_SIZEOF (gpointer);
4914 int stack_slot_align = MONO_ABI_ALIGNOF (gpointer);
4915 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
4916 int stack_slot_size = SIZEOF_REGISTER;
4917 int stack_slot_align = SIZEOF_REGISTER;
4920 g_assert (t != NULL);
4926 *align = stack_slot_align;
4927 return stack_slot_size;
4930 simple_type = t->type;
4931 switch (simple_type) {
4932 case MONO_TYPE_BOOLEAN:
4933 case MONO_TYPE_CHAR:
4942 case MONO_TYPE_STRING:
4943 case MONO_TYPE_OBJECT:
4944 case MONO_TYPE_CLASS:
4945 case MONO_TYPE_SZARRAY:
4947 case MONO_TYPE_FNPTR:
4948 case MONO_TYPE_ARRAY:
4949 *align = stack_slot_align;
4950 return stack_slot_size;
4952 case MONO_TYPE_MVAR:
4953 g_assert (allow_open);
4954 if (!t->data.generic_param->gshared_constraint || t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE) {
4955 *align = stack_slot_align;
4956 return stack_slot_size;
4958 /* The gparam can only match types given by gshared_constraint */
4959 return mono_type_stack_size_internal (t->data.generic_param->gshared_constraint, align, allow_open);
4961 case MONO_TYPE_TYPEDBYREF:
4962 *align = stack_slot_align;
4963 return stack_slot_size * 3;
4965 *align = MONO_ABI_ALIGNOF (float);
4966 return sizeof (float);
4969 *align = MONO_ABI_ALIGNOF (gint64);
4970 return sizeof (gint64);
4972 *align = MONO_ABI_ALIGNOF (double);
4973 return sizeof (double);
4974 case MONO_TYPE_VALUETYPE: {
4977 if (t->data.klass->enumtype)
4978 return mono_type_stack_size_internal (mono_class_enum_basetype (t->data.klass), align, allow_open);
4980 size = mono_class_value_size (t->data.klass, (guint32*)align);
4982 *align = *align + stack_slot_align - 1;
4983 *align &= ~(stack_slot_align - 1);
4985 size += stack_slot_size - 1;
4986 size &= ~(stack_slot_size - 1);
4991 case MONO_TYPE_GENERICINST: {
4992 MonoGenericClass *gclass = t->data.generic_class;
4993 MonoClass *container_class = gclass->container_class;
4996 g_assert (!gclass->context.class_inst->is_open);
4998 if (container_class->valuetype) {
4999 if (container_class->enumtype)
5000 return mono_type_stack_size_internal (mono_class_enum_basetype (container_class), align, allow_open);
5002 guint32 size = mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
5004 *align = *align + stack_slot_align - 1;
5005 *align &= ~(stack_slot_align - 1);
5007 size += stack_slot_size - 1;
5008 size &= ~(stack_slot_size - 1);
5013 *align = stack_slot_align;
5014 return stack_slot_size;
5018 g_error ("type 0x%02x unknown", t->type);
5024 mono_type_generic_inst_is_valuetype (MonoType *type)
5026 g_assert (type->type == MONO_TYPE_GENERICINST);
5027 return type->data.generic_class->container_class->valuetype;
5031 * mono_metadata_generic_class_is_valuetype:
5034 mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
5036 return gclass->container_class->valuetype;
5040 _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
5042 MonoGenericInst *i1 = g1->context.class_inst;
5043 MonoGenericInst *i2 = g2->context.class_inst;
5045 if (g1->is_dynamic != g2->is_dynamic)
5047 if (!mono_metadata_class_equal (g1->container_class, g2->container_class, signature_only))
5049 if (!mono_generic_inst_equal_full (i1, i2, signature_only))
5051 return g1->is_tb_open == g2->is_tb_open;
5055 _mono_metadata_generic_class_container_equal (const MonoGenericClass *g1, MonoClass *c2, gboolean signature_only)
5057 MonoGenericInst *i1 = g1->context.class_inst;
5058 MonoGenericInst *i2 = mono_class_get_generic_container (c2)->context.class_inst;
5060 if (!mono_metadata_class_equal (g1->container_class, c2, signature_only))
5062 if (!mono_generic_inst_equal_full (i1, i2, signature_only))
5064 return !g1->is_tb_open;
5068 mono_metadata_generic_context_hash (const MonoGenericContext *context)
5070 /* FIXME: check if this seed is good enough */
5071 guint hash = 0xc01dfee7;
5072 if (context->class_inst)
5073 hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->class_inst);
5074 if (context->method_inst)
5075 hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->method_inst);
5080 mono_metadata_generic_context_equal (const MonoGenericContext *g1, const MonoGenericContext *g2)
5082 return g1->class_inst == g2->class_inst && g1->method_inst == g2->method_inst;
5086 * mono_metadata_str_hash:
5088 * This should be used instead of g_str_hash for computing hash codes visible
5089 * outside this module, since g_str_hash () is not guaranteed to be stable
5090 * (its not the same in eglib for example).
5093 mono_metadata_str_hash (gconstpointer v1)
5095 /* Same as g_str_hash () in glib */
5096 char *p = (char *) v1;
5101 hash = (hash << 5) - hash + *p;
5108 * mono_metadata_type_hash:
5110 * Computes a hash value for \p t1 to be used in \c GHashTable.
5111 * The returned hash is guaranteed to be the same across executions.
5114 mono_metadata_type_hash (MonoType *t1)
5116 guint hash = t1->type;
5118 hash |= t1->byref << 6; /* do not collide with t1->type values */
5120 case MONO_TYPE_VALUETYPE:
5121 case MONO_TYPE_CLASS:
5122 case MONO_TYPE_SZARRAY: {
5123 MonoClass *klass = t1->data.klass;
5125 * Dynamic classes must not be hashed on their type since it can change
5126 * during runtime. For example, if we hash a reference type that is
5127 * later made into a valuetype.
5129 * This is specially problematic with generic instances since they are
5130 * inserted in a bunch of hash tables before been finished.
5132 if (image_is_dynamic (klass->image))
5133 return (t1->byref << 6) | mono_metadata_str_hash (klass->name);
5134 return ((hash << 5) - hash) ^ mono_metadata_str_hash (klass->name);
5137 return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
5138 case MONO_TYPE_ARRAY:
5139 return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
5140 case MONO_TYPE_GENERICINST:
5141 return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
5143 case MONO_TYPE_MVAR:
5144 return ((hash << 5) - hash) ^ mono_metadata_generic_param_hash (t1->data.generic_param);
5151 mono_metadata_generic_param_hash (MonoGenericParam *p)
5154 MonoGenericParamInfo *info;
5156 hash = (mono_generic_param_num (p) << 2);
5157 if (p->gshared_constraint)
5158 hash = ((hash << 5) - hash) ^ mono_metadata_type_hash (p->gshared_constraint);
5159 info = mono_generic_param_info (p);
5160 /* Can't hash on the owner klass/method, since those might not be set when this is called */
5162 hash = ((hash << 5) - hash) ^ info->token;
5167 mono_metadata_generic_param_equal_internal (MonoGenericParam *p1, MonoGenericParam *p2, gboolean signature_only)
5171 if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
5173 if (p1->gshared_constraint && p2->gshared_constraint) {
5174 if (!mono_metadata_type_equal (p1->gshared_constraint, p2->gshared_constraint))
5177 if (p1->gshared_constraint != p2->gshared_constraint)
5182 * We have to compare the image as well because if we didn't,
5183 * the generic_inst_cache lookup wouldn't care about the image
5184 * of generic params, so what could happen is that a generic
5185 * inst with params from image A is put into the cache, then
5186 * image B gets that generic inst from the cache, image A is
5187 * unloaded, so the inst is deleted, but image B still retains
5190 if (mono_generic_param_owner (p1) == mono_generic_param_owner (p2))
5194 * If `signature_only' is true, we're comparing two (method) signatures.
5195 * In this case, the owner of two type parameters doesn't need to match.
5198 return signature_only;
5202 mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2)
5204 return mono_metadata_generic_param_equal_internal (p1, p2, TRUE);
5208 mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only)
5212 if (mono_class_is_ginst (c1) && mono_class_is_ginst (c2))
5213 return _mono_metadata_generic_class_equal (mono_class_get_generic_class (c1), mono_class_get_generic_class (c2), signature_only);
5214 if (mono_class_is_ginst (c1) && mono_class_is_gtd (c2))
5215 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c1), c2, signature_only);
5216 if (mono_class_is_gtd (c1) && mono_class_is_ginst (c2))
5217 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c2), c1, signature_only);
5218 if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
5219 return mono_metadata_generic_param_equal_internal (
5220 c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
5221 if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR))
5222 return mono_metadata_generic_param_equal_internal (
5223 c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
5224 if (signature_only &&
5225 (c1->byval_arg.type == MONO_TYPE_SZARRAY) && (c2->byval_arg.type == MONO_TYPE_SZARRAY))
5226 return mono_metadata_class_equal (c1->byval_arg.data.klass, c2->byval_arg.data.klass, signature_only);
5227 if (signature_only &&
5228 (c1->byval_arg.type == MONO_TYPE_ARRAY) && (c2->byval_arg.type == MONO_TYPE_ARRAY))
5229 return do_mono_metadata_type_equal (&c1->byval_arg, &c2->byval_arg, signature_only);
5234 mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only)
5236 gpointer iter1 = 0, iter2 = 0;
5240 if (s1->call_convention != s2->call_convention)
5242 if (s1->sentinelpos != s2->sentinelpos)
5244 if (s1->hasthis != s2->hasthis)
5246 if (s1->explicit_this != s2->explicit_this)
5248 if (! do_mono_metadata_type_equal (s1->ret, s2->ret, signature_only))
5250 if (s1->param_count != s2->param_count)
5254 MonoType *t1 = mono_signature_get_params (s1, &iter1);
5255 MonoType *t2 = mono_signature_get_params (s2, &iter2);
5257 if (t1 == NULL || t2 == NULL)
5259 if (! do_mono_metadata_type_equal (t1, t2, signature_only))
5265 * mono_metadata_type_equal:
5268 * @signature_only: If true, treat ginsts as equal which are instantiated separately but have equal positional value
5270 * Determine if @t1 and @t2 represent the same type.
5271 * Returns: #TRUE if @t1 and @t2 are equal.
5274 do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only)
5276 if (t1->type != t2->type || t1->byref != t2->byref)
5280 case MONO_TYPE_VOID:
5281 case MONO_TYPE_BOOLEAN:
5282 case MONO_TYPE_CHAR:
5293 case MONO_TYPE_STRING:
5296 case MONO_TYPE_OBJECT:
5297 case MONO_TYPE_TYPEDBYREF:
5299 case MONO_TYPE_VALUETYPE:
5300 case MONO_TYPE_CLASS:
5301 case MONO_TYPE_SZARRAY:
5302 return mono_metadata_class_equal (t1->data.klass, t2->data.klass, signature_only);
5304 return do_mono_metadata_type_equal (t1->data.type, t2->data.type, signature_only);
5305 case MONO_TYPE_ARRAY:
5306 if (t1->data.array->rank != t2->data.array->rank)
5308 return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass, signature_only);
5309 case MONO_TYPE_GENERICINST:
5310 return _mono_metadata_generic_class_equal (
5311 t1->data.generic_class, t2->data.generic_class, signature_only);
5313 return mono_metadata_generic_param_equal_internal (
5314 t1->data.generic_param, t2->data.generic_param, signature_only);
5315 case MONO_TYPE_MVAR:
5316 return mono_metadata_generic_param_equal_internal (
5317 t1->data.generic_param, t2->data.generic_param, signature_only);
5318 case MONO_TYPE_FNPTR:
5319 return mono_metadata_fnptr_equal (t1->data.method, t2->data.method, signature_only);
5321 g_error ("implement type compare for %0x!", t1->type);
5329 * mono_metadata_type_equal:
5332 mono_metadata_type_equal (MonoType *t1, MonoType *t2)
5334 return do_mono_metadata_type_equal (t1, t2, FALSE);
5338 * mono_metadata_type_equal_full:
5340 * \param t2 another type
5341 * \param signature_only if signature only comparison should be made
5343 * Determine if \p t1 and \p t2 are signature compatible if \p signature_only is TRUE, otherwise
5344 * behaves the same way as mono_metadata_type_equal.
5345 * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
5346 * \returns TRUE if \p t1 and \p t2 are equal taking \p signature_only into account.
5349 mono_metadata_type_equal_full (MonoType *t1, MonoType *t2, gboolean signature_only)
5351 return do_mono_metadata_type_equal (t1, t2, signature_only);
5355 * mono_metadata_signature_equal:
5356 * \param sig1 a signature
5357 * \param sig2 another signature
5359 * Determine if \p sig1 and \p sig2 represent the same signature, with the
5360 * same number of arguments and the same types.
5361 * \returns TRUE if \p sig1 and \p sig2 are equal.
5364 mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
5368 if (sig1->hasthis != sig2->hasthis || sig1->param_count != sig2->param_count)
5371 if (sig1->generic_param_count != sig2->generic_param_count)
5375 * We're just comparing the signatures of two methods here:
5377 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
5378 * U and V are equal here.
5380 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
5383 for (i = 0; i < sig1->param_count; i++) {
5384 MonoType *p1 = sig1->params[i];
5385 MonoType *p2 = sig2->params[i];
5387 /* if (p1->attrs != p2->attrs)
5390 if (!do_mono_metadata_type_equal (p1, p2, TRUE))
5394 if (!do_mono_metadata_type_equal (sig1->ret, sig2->ret, TRUE))
5400 * mono_metadata_type_dup:
5401 * \param image image to alloc memory from
5402 * \param original type to duplicate
5403 * \returns copy of type allocated from the image's mempool (or from the heap, if \p image is null).
5406 mono_metadata_type_dup (MonoImage *image, const MonoType *o)
5409 int sizeof_o = MONO_SIZEOF_TYPE;
5411 sizeof_o += o->num_mods * sizeof (MonoCustomMod);
5413 r = image ? (MonoType *)mono_image_alloc0 (image, sizeof_o) : (MonoType *)g_malloc (sizeof_o);
5415 memcpy (r, o, sizeof_o);
5417 if (o->type == MONO_TYPE_PTR) {
5418 r->data.type = mono_metadata_type_dup (image, o->data.type);
5419 } else if (o->type == MONO_TYPE_ARRAY) {
5420 r->data.array = mono_dup_array_type (image, o->data.array);
5421 } else if (o->type == MONO_TYPE_FNPTR) {
5422 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
5423 r->data.method = mono_metadata_signature_deep_dup (image, o->data.method);
5429 * mono_signature_hash:
5432 mono_signature_hash (MonoMethodSignature *sig)
5434 guint i, res = sig->ret->type;
5436 for (i = 0; i < sig->param_count; i++)
5437 res = (res << 5) - res + mono_type_hash (sig->params[i]);
5443 * mono_metadata_encode_value:
5444 * @value: value to encode
5445 * @buf: buffer where to write the compressed representation
5446 * @endbuf: pointer updated to point at the end of the encoded output
5448 * Encodes the value @value in the compressed representation used
5449 * in metadata and stores the result in @buf. @buf needs to be big
5450 * enough to hold the data (4 bytes).
5453 mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
5459 else if (value < 0x4000) {
5460 p [0] = 0x80 | (value >> 8);
5461 p [1] = value & 0xff;
5464 p [0] = (value >> 24) | 0xc0;
5465 p [1] = (value >> 16) & 0xff;
5466 p [2] = (value >> 8) & 0xff;
5467 p [3] = value & 0xff;
5475 * mono_metadata_field_info:
5476 * \param meta the Image the field is defined in
5477 * \param index the index in the field table representing the field
5478 * \param offset a pointer to an integer where to store the offset that may have been specified for the field in a FieldLayout table
5479 * \param rva a pointer to the RVA of the field data in the image that may have been defined in a \c FieldRVA table
5480 * \param marshal_spec a pointer to the marshal spec that may have been defined for the field in a \c FieldMarshal table.
5482 * Gather info for field \p index that may have been defined in the \c FieldLayout,
5483 * \c FieldRVA and \c FieldMarshal tables.
5484 * Either of \p offset, \p rva and \p marshal_spec can be NULL if you're not interested
5488 mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
5489 MonoMarshalSpec **marshal_spec)
5491 mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, FALSE);
5495 mono_metadata_field_info_with_mempool (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
5496 MonoMarshalSpec **marshal_spec)
5498 mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, TRUE);
5502 mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
5503 MonoMarshalSpec **marshal_spec, gboolean alloc_from_image)
5505 MonoTableInfo *tdef;
5508 loc.idx = index + 1;
5509 if (meta->uncompressed_metadata)
5510 loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
5513 tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
5515 loc.col_idx = MONO_FIELD_LAYOUT_FIELD;
5518 if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
5519 *offset = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_LAYOUT_OFFSET);
5521 *offset = (guint32)-1;
5525 tdef = &meta->tables [MONO_TABLE_FIELDRVA];
5527 loc.col_idx = MONO_FIELD_RVA_FIELD;
5530 if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
5532 * LAMESPEC: There is no signature, no nothing, just the raw data.
5534 *rva = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_RVA_RVA);
5542 if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
5543 *marshal_spec = mono_metadata_parse_marshal_spec_full (alloc_from_image ? meta : NULL, meta, p);
5550 * mono_metadata_get_constant_index:
5551 * \param meta the Image the field is defined in
5552 * \param index the token that may have a row defined in the constants table
5553 * \param hint possible position for the row
5555 * \p token must be a \c FieldDef, \c ParamDef or \c PropertyDef token.
5557 * \returns the index into the \c Constants table or 0 if not found.
5560 mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
5562 MonoTableInfo *tdef;
5564 guint32 index = mono_metadata_token_index (token);
5566 tdef = &meta->tables [MONO_TABLE_CONSTANT];
5567 index <<= MONO_HASCONSTANT_BITS;
5568 switch (mono_metadata_token_table (token)) {
5569 case MONO_TABLE_FIELD:
5570 index |= MONO_HASCONSTANT_FIEDDEF;
5572 case MONO_TABLE_PARAM:
5573 index |= MONO_HASCONSTANT_PARAM;
5575 case MONO_TABLE_PROPERTY:
5576 index |= MONO_HASCONSTANT_PROPERTY;
5579 g_warning ("Not a valid token for the constant table: 0x%08x", token);
5583 loc.col_idx = MONO_CONSTANT_PARENT;
5586 /* FIXME: Index translation */
5588 if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
5591 if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
5592 return loc.result + 1;
5598 * mono_metadata_events_from_typedef:
5599 * \param meta metadata context
5600 * \param index 0-based index (in the \c TypeDef table) describing a type
5601 * \returns the 0-based index in the \c Event table for the events in the
5602 * type. The last event that belongs to the type (plus 1) is stored
5603 * in the \p end_idx pointer.
5606 mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
5610 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_EVENTMAP];
5618 loc.col_idx = MONO_EVENT_MAP_PARENT;
5619 loc.idx = index + 1;
5621 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5624 start = mono_metadata_decode_row_col (tdef, loc.result, MONO_EVENT_MAP_EVENTLIST);
5625 if (loc.result + 1 < tdef->rows) {
5626 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_EVENT_MAP_EVENTLIST) - 1;
5628 end = meta->tables [MONO_TABLE_EVENT].rows;
5636 * mono_metadata_methods_from_event:
5637 * \param meta metadata context
5638 * \param index 0-based index (in the \c Event table) describing a event
5639 * \returns the 0-based index in the \c MethodDef table for the methods in the
5640 * event. The last method that belongs to the event (plus 1) is stored
5641 * in the \p end_idx pointer.
5644 mono_metadata_methods_from_event (MonoImage *meta, guint32 index, guint *end_idx)
5648 guint32 cols [MONO_METHOD_SEMA_SIZE];
5649 MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
5655 if (meta->uncompressed_metadata)
5656 index = search_ptr_table (meta, MONO_TABLE_EVENT_POINTER, index + 1) - 1;
5659 loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
5660 loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
5662 if (!mono_binary_search (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
5667 * We may end up in the middle of the rows...
5670 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
5676 while (end < msemt->rows) {
5677 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
5678 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
5687 * mono_metadata_properties_from_typedef:
5688 * \param meta metadata context
5689 * \param index 0-based index (in the \c TypeDef table) describing a type
5690 * \returns the 0-based index in the \c Property table for the properties in the
5691 * type. The last property that belongs to the type (plus 1) is stored
5692 * in the \p end_idx pointer.
5695 mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
5699 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_PROPERTYMAP];
5707 loc.col_idx = MONO_PROPERTY_MAP_PARENT;
5708 loc.idx = index + 1;
5710 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5713 start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST);
5714 if (loc.result + 1 < tdef->rows) {
5715 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_PROPERTY_MAP_PROPERTY_LIST) - 1;
5717 end = meta->tables [MONO_TABLE_PROPERTY].rows;
5725 * mono_metadata_methods_from_property:
5726 * \param meta metadata context
5727 * \param index 0-based index (in the \c PropertyDef table) describing a property
5728 * \returns the 0-based index in the \c MethodDef table for the methods in the
5729 * property. The last method that belongs to the property (plus 1) is stored
5730 * in the \p end_idx pointer.
5733 mono_metadata_methods_from_property (MonoImage *meta, guint32 index, guint *end_idx)
5737 guint32 cols [MONO_METHOD_SEMA_SIZE];
5738 MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
5744 if (meta->uncompressed_metadata)
5745 index = search_ptr_table (meta, MONO_TABLE_PROPERTY_POINTER, index + 1) - 1;
5748 loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
5749 loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
5751 if (!mono_binary_search (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
5756 * We may end up in the middle of the rows...
5759 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
5765 while (end < msemt->rows) {
5766 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
5767 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
5776 * mono_metadata_implmap_from_method:
5779 mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
5782 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_IMPLMAP];
5787 /* No index translation seems to be needed */
5790 loc.col_idx = MONO_IMPLMAP_MEMBER;
5791 loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
5793 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5796 return loc.result + 1;
5800 * mono_type_create_from_typespec:
5801 * \param image context where the image is created
5802 * \param type_spec typespec token
5803 * \deprecated use \c mono_type_create_from_typespec_checked that has proper error handling
5805 * Creates a \c MonoType representing the \c TypeSpec indexed by the \p type_spec
5809 mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
5812 MonoType *type = mono_type_create_from_typespec_checked (image, type_spec, &error);
5814 g_error ("Could not create typespec %x due to %s", type_spec, mono_error_get_message (&error));
5819 mono_type_create_from_typespec_checked (MonoImage *image, guint32 type_spec, MonoError *error)
5822 guint32 idx = mono_metadata_token_index (type_spec);
5824 guint32 cols [MONO_TYPESPEC_SIZE];
5826 MonoType *type, *type2;
5830 type = (MonoType *)mono_conc_hashtable_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
5834 t = &image->tables [MONO_TABLE_TYPESPEC];
5836 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
5837 ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
5839 if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], type_spec, NULL)) {
5840 mono_error_set_bad_image (error, image, "Could not verify type spec %08x.", type_spec);
5844 mono_metadata_decode_value (ptr, &ptr);
5846 type = mono_metadata_parse_type_checked (image, NULL, 0, TRUE, ptr, &ptr, error);
5850 type2 = mono_metadata_type_dup (image, type);
5851 mono_metadata_free_type (type);
5853 mono_image_lock (image);
5855 /* We might leak some data in the image mempool if found */
5856 type = mono_conc_hashtable_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
5860 mono_image_unlock (image);
5867 mono_image_strndup (MonoImage *image, const char *data, guint len)
5871 return g_strndup (data, len);
5872 res = (char *)mono_image_alloc (image, len + 1);
5873 memcpy (res, data, len);
5879 * mono_metadata_parse_marshal_spec:
5882 mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
5884 return mono_metadata_parse_marshal_spec_full (NULL, image, ptr);
5888 * If IMAGE is non-null, memory will be allocated from its mempool, otherwise it will be allocated using malloc.
5889 * PARENT_IMAGE is the image containing the marshal spec.
5892 mono_metadata_parse_marshal_spec_full (MonoImage *image, MonoImage *parent_image, const char *ptr)
5894 MonoMarshalSpec *res;
5896 const char *start = ptr;
5898 /* fixme: this is incomplete, but I cant find more infos in the specs */
5901 res = (MonoMarshalSpec *)mono_image_alloc0 (image, sizeof (MonoMarshalSpec));
5903 res = g_new0 (MonoMarshalSpec, 1);
5905 len = mono_metadata_decode_value (ptr, &ptr);
5906 res->native = (MonoMarshalNative)*ptr++;
5908 if (res->native == MONO_NATIVE_LPARRAY) {
5909 res->data.array_data.param_num = -1;
5910 res->data.array_data.num_elem = -1;
5911 res->data.array_data.elem_mult = -1;
5913 if (ptr - start <= len)
5914 res->data.array_data.elem_type = (MonoMarshalNative)*ptr++;
5915 if (ptr - start <= len)
5916 res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr);
5917 if (ptr - start <= len)
5918 res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5919 if (ptr - start <= len) {
5921 * LAMESPEC: Older spec versions say this parameter comes before
5922 * num_elem. Never spec versions don't talk about elem_mult at
5923 * all, but csc still emits it, and it is used to distinguish
5924 * between param_num being 0, and param_num being omitted.
5925 * So if (param_num == 0) && (num_elem > 0), then
5926 * elem_mult == 0 -> the array size is num_elem
5927 * elem_mult == 1 -> the array size is @param_num + num_elem
5929 res->data.array_data.elem_mult = mono_metadata_decode_value (ptr, &ptr);
5933 if (res->native == MONO_NATIVE_BYVALTSTR) {
5934 if (ptr - start <= len)
5935 res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5938 if (res->native == MONO_NATIVE_BYVALARRAY) {
5939 if (ptr - start <= len)
5940 res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5943 if (res->native == MONO_NATIVE_CUSTOM) {
5944 /* skip unused type guid */
5945 len = mono_metadata_decode_value (ptr, &ptr);
5947 /* skip unused native type name */
5948 len = mono_metadata_decode_value (ptr, &ptr);
5950 /* read custom marshaler type name */
5951 len = mono_metadata_decode_value (ptr, &ptr);
5952 res->data.custom_data.custom_name = mono_image_strndup (image, ptr, len);
5954 /* read cookie string */
5955 len = mono_metadata_decode_value (ptr, &ptr);
5956 res->data.custom_data.cookie = mono_image_strndup (image, ptr, len);
5957 res->data.custom_data.image = parent_image;
5960 if (res->native == MONO_NATIVE_SAFEARRAY) {
5961 res->data.safearray_data.elem_type = (MonoMarshalVariant)0;
5962 res->data.safearray_data.num_elem = 0;
5963 if (ptr - start <= len)
5964 res->data.safearray_data.elem_type = (MonoMarshalVariant)*ptr++;
5965 if (ptr - start <= len)
5966 res->data.safearray_data.num_elem = *ptr++;
5972 * mono_metadata_free_marshal_spec:
5975 mono_metadata_free_marshal_spec (MonoMarshalSpec *spec)
5977 if (spec->native == MONO_NATIVE_CUSTOM) {
5978 g_free (spec->data.custom_data.custom_name);
5979 g_free (spec->data.custom_data.cookie);
5985 * mono_type_to_unmanaged:
5986 * The value pointed to by \p conv will contain the kind of marshalling required for this
5987 * particular type one of the \c MONO_MARSHAL_CONV_ enumeration values.
5988 * \returns A \c MonoMarshalNative enumeration value (<code>MONO_NATIVE_</code>) value
5989 * describing the underlying native reprensetation of the type.
5992 mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_field,
5993 gboolean unicode, MonoMarshalConv *conv)
5995 MonoMarshalConv dummy_conv;
6001 *conv = MONO_MARSHAL_CONV_NONE;
6004 return MONO_NATIVE_UINT;
6008 case MONO_TYPE_BOOLEAN:
6010 switch (mspec->native) {
6011 case MONO_NATIVE_VARIANTBOOL:
6012 *conv = MONO_MARSHAL_CONV_BOOL_VARIANTBOOL;
6013 return MONO_NATIVE_VARIANTBOOL;
6014 case MONO_NATIVE_BOOLEAN:
6015 *conv = MONO_MARSHAL_CONV_BOOL_I4;
6016 return MONO_NATIVE_BOOLEAN;
6017 case MONO_NATIVE_I1:
6018 case MONO_NATIVE_U1:
6019 return mspec->native;
6021 g_error ("cant marshal bool to native type %02x", mspec->native);
6024 *conv = MONO_MARSHAL_CONV_BOOL_I4;
6025 return MONO_NATIVE_BOOLEAN;
6026 case MONO_TYPE_CHAR:
6028 switch (mspec->native) {
6029 case MONO_NATIVE_U2:
6030 case MONO_NATIVE_U1:
6031 return mspec->native;
6033 g_error ("cant marshal char to native type %02x", mspec->native);
6036 return unicode ? MONO_NATIVE_U2 : MONO_NATIVE_U1;
6037 case MONO_TYPE_I1: return MONO_NATIVE_I1;
6038 case MONO_TYPE_U1: return MONO_NATIVE_U1;
6039 case MONO_TYPE_I2: return MONO_NATIVE_I2;
6040 case MONO_TYPE_U2: return MONO_NATIVE_U2;
6041 case MONO_TYPE_I4: return MONO_NATIVE_I4;
6042 case MONO_TYPE_U4: return MONO_NATIVE_U4;
6043 case MONO_TYPE_I8: return MONO_NATIVE_I8;
6044 case MONO_TYPE_U8: return MONO_NATIVE_U8;
6045 case MONO_TYPE_R4: return MONO_NATIVE_R4;
6046 case MONO_TYPE_R8: return MONO_NATIVE_R8;
6047 case MONO_TYPE_STRING:
6049 switch (mspec->native) {
6050 case MONO_NATIVE_BSTR:
6051 *conv = MONO_MARSHAL_CONV_STR_BSTR;
6052 return MONO_NATIVE_BSTR;
6053 case MONO_NATIVE_LPSTR:
6054 *conv = MONO_MARSHAL_CONV_STR_LPSTR;
6055 return MONO_NATIVE_LPSTR;
6056 case MONO_NATIVE_LPWSTR:
6057 *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
6058 return MONO_NATIVE_LPWSTR;
6059 case MONO_NATIVE_LPTSTR:
6060 *conv = MONO_MARSHAL_CONV_STR_LPTSTR;
6061 return MONO_NATIVE_LPTSTR;
6062 case MONO_NATIVE_ANSIBSTR:
6063 *conv = MONO_MARSHAL_CONV_STR_ANSIBSTR;
6064 return MONO_NATIVE_ANSIBSTR;
6065 case MONO_NATIVE_TBSTR:
6066 *conv = MONO_MARSHAL_CONV_STR_TBSTR;
6067 return MONO_NATIVE_TBSTR;
6068 case MONO_NATIVE_UTF8STR:
6069 *conv = MONO_MARSHAL_CONV_STR_UTF8STR;
6070 return MONO_NATIVE_UTF8STR;
6071 case MONO_NATIVE_BYVALTSTR:
6073 *conv = MONO_MARSHAL_CONV_STR_BYVALWSTR;
6075 *conv = MONO_MARSHAL_CONV_STR_BYVALSTR;
6076 return MONO_NATIVE_BYVALTSTR;
6078 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);
6082 *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
6083 return MONO_NATIVE_LPWSTR;
6086 *conv = MONO_MARSHAL_CONV_STR_LPSTR;
6087 return MONO_NATIVE_LPSTR;
6089 case MONO_TYPE_PTR: return MONO_NATIVE_UINT;
6090 case MONO_TYPE_VALUETYPE: /*FIXME*/
6091 if (type->data.klass->enumtype) {
6092 t = mono_class_enum_basetype (type->data.klass)->type;
6095 if (type->data.klass == mono_defaults.handleref_class){
6096 *conv = MONO_MARSHAL_CONV_HANDLEREF;
6097 return MONO_NATIVE_INT;
6099 return MONO_NATIVE_STRUCT;
6100 case MONO_TYPE_SZARRAY:
6101 case MONO_TYPE_ARRAY:
6103 switch (mspec->native) {
6104 case MONO_NATIVE_BYVALARRAY:
6105 if ((type->data.klass->element_class == mono_defaults.char_class) && !unicode)
6106 *conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY;
6108 *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
6109 return MONO_NATIVE_BYVALARRAY;
6110 case MONO_NATIVE_SAFEARRAY:
6111 *conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY;
6112 return MONO_NATIVE_SAFEARRAY;
6113 case MONO_NATIVE_LPARRAY:
6114 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
6115 return MONO_NATIVE_LPARRAY;
6117 g_error ("cant marshal array as native type %02x", mspec->native);
6121 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
6122 return MONO_NATIVE_LPARRAY;
6123 case MONO_TYPE_I: return MONO_NATIVE_INT;
6124 case MONO_TYPE_U: return MONO_NATIVE_UINT;
6125 case MONO_TYPE_CLASS:
6126 case MONO_TYPE_OBJECT: {
6127 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
6129 switch (mspec->native) {
6130 case MONO_NATIVE_STRUCT:
6131 return MONO_NATIVE_STRUCT;
6132 case MONO_NATIVE_CUSTOM:
6133 return MONO_NATIVE_CUSTOM;
6134 case MONO_NATIVE_INTERFACE:
6135 *conv = MONO_MARSHAL_CONV_OBJECT_INTERFACE;
6136 return MONO_NATIVE_INTERFACE;
6137 case MONO_NATIVE_IDISPATCH:
6138 *conv = MONO_MARSHAL_CONV_OBJECT_IDISPATCH;
6139 return MONO_NATIVE_IDISPATCH;
6140 case MONO_NATIVE_IUNKNOWN:
6141 *conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN;
6142 return MONO_NATIVE_IUNKNOWN;
6143 case MONO_NATIVE_FUNC:
6144 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
6145 type->data.klass == mono_defaults.delegate_class ||
6146 type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
6147 *conv = MONO_MARSHAL_CONV_DEL_FTN;
6148 return MONO_NATIVE_FUNC;
6152 g_error ("cant marshal object as native type %02x", mspec->native);
6155 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
6156 type->data.klass == mono_defaults.delegate_class ||
6157 type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
6158 *conv = MONO_MARSHAL_CONV_DEL_FTN;
6159 return MONO_NATIVE_FUNC;
6161 if (mono_class_try_get_safehandle_class () && type->data.klass == mono_class_try_get_safehandle_class ()){
6162 *conv = MONO_MARSHAL_CONV_SAFEHANDLE;
6163 return MONO_NATIVE_INT;
6165 *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT;
6166 return MONO_NATIVE_STRUCT;
6168 case MONO_TYPE_FNPTR: return MONO_NATIVE_FUNC;
6169 case MONO_TYPE_GENERICINST:
6170 type = &type->data.generic_class->container_class->byval_arg;
6173 case MONO_TYPE_TYPEDBYREF:
6175 g_error ("type 0x%02x not handled in marshal", t);
6177 return MONO_NATIVE_MAX;
6181 * mono_metadata_get_marshal_info:
6184 mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
6187 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_FIELDMARSHAL];
6193 loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
6194 loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
6196 /* FIXME: Index translation */
6198 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
6201 return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
6205 method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context, MonoError *error)
6207 MonoMethod *result = NULL;
6208 guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
6212 switch (tok & MONO_METHODDEFORREF_MASK) {
6213 case MONO_METHODDEFORREF_METHODDEF:
6214 result = mono_get_method_checked (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context, error);
6216 case MONO_METHODDEFORREF_METHODREF:
6217 result = mono_get_method_checked (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context, error);
6220 mono_error_set_bad_image (error, m, "Invalid MethodDefOfRef token %x", tok);
6227 * mono_class_get_overrides_full:
6229 * Return the method overrides belonging to class @type_token in @overrides, and
6230 * the number of overrides in @num_overrides.
6232 * Returns: TRUE on success, FALSE on failure.
6235 mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides,
6236 MonoGenericContext *generic_context)
6240 MonoTableInfo *tdef = &image->tables [MONO_TABLE_METHODIMPL];
6243 guint32 cols [MONO_METHODIMPL_SIZE];
6244 MonoMethod **result;
6255 loc.col_idx = MONO_METHODIMPL_CLASS;
6256 loc.idx = mono_metadata_token_index (type_token);
6258 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
6264 * We may end up in the middle of the rows...
6267 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_METHODIMPL_CLASS))
6272 while (end < tdef->rows) {
6273 if (loc.idx == mono_metadata_decode_row_col (tdef, end, MONO_METHODIMPL_CLASS))
6279 result = g_new (MonoMethod*, num * 2);
6280 for (i = 0; i < num; ++i) {
6283 if (!mono_verifier_verify_methodimpl_row (image, start + i, &error)) {
6284 mono_error_cleanup (&error); /* FIXME don't swallow the error */
6289 mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
6290 method = method_from_method_def_or_ref (
6291 image, cols [MONO_METHODIMPL_DECLARATION], generic_context, &error);
6292 if (method == NULL) {
6293 mono_error_cleanup (&error); /* FIXME don't swallow the error */
6296 result [i * 2] = method;
6297 method = method_from_method_def_or_ref (
6298 image, cols [MONO_METHODIMPL_BODY], generic_context, &error);
6299 if (method == NULL) {
6300 mono_error_cleanup (&error); /* FIXME don't swallow the error */
6303 result [i * 2 + 1] = method;
6306 *overrides = result;
6308 *num_overrides = num;
6313 * mono_guid_to_string:
6315 * Converts a 16 byte Microsoft GUID to the standard string representation.
6318 mono_guid_to_string (const guint8 *guid)
6320 return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
6321 guid[3], guid[2], guid[1], guid[0],
6325 guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
6329 * mono_guid_to_string_minimal:
6331 * Converts a 16 byte Microsoft GUID to lower case no '-' representation..
6334 mono_guid_to_string_minimal (const guint8 *guid)
6336 return g_strdup_printf ("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
6337 guid[3], guid[2], guid[1], guid[0],
6341 guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
6344 get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container, MonoError *error)
6346 MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
6347 guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
6348 guint32 i, token, found;
6349 MonoClass *klass, **res;
6350 GSList *cons = NULL, *tmp;
6351 MonoGenericContext *context = &container->context;
6355 *constraints = NULL;
6357 for (i = 0; i < tdef->rows; ++i) {
6358 mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
6359 if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
6360 token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
6361 klass = mono_class_get_and_inflate_typespec_checked (image, token, context, error);
6363 g_slist_free (cons);
6366 cons = g_slist_append (cons, klass);
6369 /* contiguous list finished */
6376 res = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * (found + 1));
6377 for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
6378 res [i] = (MonoClass *)tmp->data;
6380 g_slist_free (cons);
6386 * mono_metadata_get_generic_param_row:
6389 * @token: TypeOrMethodDef token, owner for GenericParam
6390 * @owner: coded token, set on return
6392 * Returns: 1-based row-id in the GenericParam table whose
6393 * owner is @token. 0 if not found.
6396 mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *owner)
6398 MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM];
6405 if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
6406 *owner = MONO_TYPEORMETHOD_TYPE;
6407 else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
6408 *owner = MONO_TYPEORMETHOD_METHOD;
6410 g_error ("wrong token %x to get_generic_param_row", token);
6413 *owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
6416 loc.col_idx = MONO_GENERICPARAM_OWNER;
6419 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
6422 /* Find the first entry by searching backwards */
6423 while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_GENERICPARAM_OWNER) == loc.idx))
6426 return loc.result + 1;
6430 mono_metadata_has_generic_params (MonoImage *image, guint32 token)
6433 return mono_metadata_get_generic_param_row (image, token, &owner);
6437 * Memory is allocated from IMAGE's mempool.
6440 mono_metadata_load_generic_param_constraints_checked (MonoImage *image, guint32 token,
6441 MonoGenericContainer *container, MonoError *error)
6444 guint32 start_row, i, owner;
6447 if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
6449 for (i = 0; i < container->type_argc; i++) {
6450 if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container, error)) {
6458 * mono_metadata_load_generic_params:
6460 * Load the type parameters from the type or method definition @token.
6462 * Use this method after parsing a type or method definition to figure out whether it's a generic
6463 * type / method. When parsing a method definition, @parent_container points to the generic container
6464 * of the current class, if any.
6466 * Note: This method does not load the constraints: for typedefs, this has to be done after fully
6467 * creating the type.
6469 * Returns: NULL if @token is not a generic type or method definition or the new generic container.
6471 * LOCKING: Acquires the loader lock
6474 MonoGenericContainer *
6475 mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
6477 MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM];
6478 guint32 cols [MONO_GENERICPARAM_SIZE];
6479 guint32 i, owner = 0, n;
6480 MonoGenericContainer *container;
6481 MonoGenericParamFull *params;
6482 MonoGenericContext *context;
6484 if (!(i = mono_metadata_get_generic_param_row (image, token, &owner)))
6486 mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
6489 container = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
6490 container->owner.image = image; // Temporarily mark as anonymous, but this will be overriden by caller
6491 container->is_anonymous = TRUE;
6494 params = (MonoGenericParamFull *)g_realloc (params, sizeof (MonoGenericParamFull) * n);
6495 memset (¶ms [n - 1], 0, sizeof (MonoGenericParamFull));
6496 params [n - 1].param.owner = container;
6497 params [n - 1].param.num = cols [MONO_GENERICPARAM_NUMBER];
6498 params [n - 1].info.token = i | MONO_TOKEN_GENERIC_PARAM;
6499 params [n - 1].info.flags = cols [MONO_GENERICPARAM_FLAGS];
6500 params [n - 1].info.name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
6501 if (params [n - 1].param.num != n - 1)
6502 g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i);
6503 if (++i > tdef->rows)
6505 mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
6506 } while (cols [MONO_GENERICPARAM_OWNER] == owner);
6508 container->type_argc = n;
6509 container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (image, sizeof (MonoGenericParamFull) * n);
6510 memcpy (container->type_params, params, sizeof (MonoGenericParamFull) * n);
6512 container->parent = parent_container;
6514 if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
6515 container->is_method = 1;
6517 g_assert (container->parent == NULL || container->is_method);
6519 context = &container->context;
6520 if (container->is_method) {
6521 context->class_inst = container->parent ? container->parent->context.class_inst : NULL;
6522 context->method_inst = mono_get_shared_generic_inst (container);
6524 context->class_inst = mono_get_shared_generic_inst (container);
6531 mono_get_shared_generic_inst (MonoGenericContainer *container)
6533 MonoType **type_argv;
6535 MonoGenericInst *nginst;
6538 type_argv = g_new0 (MonoType *, container->type_argc);
6539 helper = g_new0 (MonoType, container->type_argc);
6541 for (i = 0; i < container->type_argc; i++) {
6542 MonoType *t = &helper [i];
6544 t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6545 t->data.generic_param = mono_generic_container_get_param (container, i);
6550 nginst = mono_metadata_get_generic_inst (container->type_argc, type_argv);
6559 * mono_type_is_byref:
6560 * \param type the \c MonoType operated on
6561 * \returns TRUE if \p type represents a type passed by reference,
6565 mono_type_is_byref (MonoType *type)
6571 * mono_type_get_type:
6572 * \param type the \c MonoType operated on
6573 * \returns the IL type value for \p type. This is one of the \c MonoTypeEnum
6574 * enum members like \c MONO_TYPE_I4 or \c MONO_TYPE_STRING.
6577 mono_type_get_type (MonoType *type)
6583 * mono_type_get_signature:
6584 * \param type the \c MonoType operated on
6585 * It is only valid to call this function if \p type is a \c MONO_TYPE_FNPTR .
6586 * \returns the \c MonoMethodSignature pointer that describes the signature
6587 * of the function pointer \p type represents.
6589 MonoMethodSignature*
6590 mono_type_get_signature (MonoType *type)
6592 g_assert (type->type == MONO_TYPE_FNPTR);
6593 return type->data.method;
6597 * mono_type_get_class:
6598 * \param type the \c MonoType operated on
6599 * It is only valid to call this function if \p type is a \c MONO_TYPE_CLASS or a
6600 * \c MONO_TYPE_VALUETYPE . For more general functionality, use \c mono_class_from_mono_type,
6602 * \returns the \c MonoClass pointer that describes the class that \p type represents.
6605 mono_type_get_class (MonoType *type)
6607 /* FIXME: review the runtime users before adding the assert here */
6608 return type->data.klass;
6612 * mono_type_get_array_type:
6613 * \param type the \c MonoType operated on
6614 * It is only valid to call this function if \p type is a \c MONO_TYPE_ARRAY .
6615 * \returns a \c MonoArrayType struct describing the array type that \p type
6616 * represents. The info includes details such as rank, array element type
6617 * and the sizes and bounds of multidimensional arrays.
6620 mono_type_get_array_type (MonoType *type)
6622 return type->data.array;
6626 * mono_type_get_ptr_type:
6627 * \pararm type the \c MonoType operated on
6628 * It is only valid to call this function if \p type is a \c MONO_TYPE_PTR .
6629 * \returns the \c MonoType pointer that describes the type that \p type
6630 * represents a pointer to.
6633 mono_type_get_ptr_type (MonoType *type)
6635 g_assert (type->type == MONO_TYPE_PTR);
6636 return type->data.type;
6640 * mono_type_get_modifiers:
6643 mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
6645 /* FIXME: implement */
6650 * mono_type_is_struct:
6651 * \param type the \c MonoType operated on
6652 * \returns TRUE if \p type is a struct, that is a \c ValueType but not an enum
6653 * or a basic type like \c System.Int32 . FALSE otherwise.
6656 mono_type_is_struct (MonoType *type)
6658 return (!type->byref && ((type->type == MONO_TYPE_VALUETYPE &&
6659 !type->data.klass->enumtype) || (type->type == MONO_TYPE_TYPEDBYREF) ||
6660 ((type->type == MONO_TYPE_GENERICINST) &&
6661 mono_metadata_generic_class_is_valuetype (type->data.generic_class) &&
6662 !type->data.generic_class->container_class->enumtype)));
6666 * mono_type_is_void:
6667 * \param type the \c MonoType operated on
6668 * \returns TRUE if \p type is \c System.Void . FALSE otherwise.
6671 mono_type_is_void (MonoType *type)
6673 return (type && (type->type == MONO_TYPE_VOID) && !type->byref);
6677 * mono_type_is_pointer:
6678 * \param type the \c MonoType operated on
6679 * \returns TRUE if \p type is a managed or unmanaged pointer type. FALSE otherwise.
6682 mono_type_is_pointer (MonoType *type)
6684 return (type && ((type->byref || (type->type == MONO_TYPE_I) || type->type == MONO_TYPE_STRING)
6685 || (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
6686 (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_OBJECT) ||
6687 (type->type == MONO_TYPE_ARRAY) || (type->type == MONO_TYPE_PTR) ||
6688 (type->type == MONO_TYPE_FNPTR)));
6692 * mono_type_is_reference:
6693 * \param type the \c MonoType operated on
6694 * \returns TRUE if \p type represents an object reference. FALSE otherwise.
6697 mono_type_is_reference (MonoType *type)
6699 return (type && (((type->type == MONO_TYPE_STRING) ||
6700 (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
6701 (type->type == MONO_TYPE_OBJECT) || (type->type == MONO_TYPE_ARRAY)) ||
6702 ((type->type == MONO_TYPE_GENERICINST) &&
6703 !mono_metadata_generic_class_is_valuetype (type->data.generic_class))));
6707 mono_type_is_generic_parameter (MonoType *type)
6709 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
6713 * mono_signature_get_return_type:
6714 * \param sig the method signature inspected
6715 * \returns the return type of the method signature \p sig
6718 mono_signature_get_return_type (MonoMethodSignature *sig)
6724 * mono_signature_get_params:
6725 * \param sig the method signature inspected
6726 * \param iter pointer to an iterator
6727 * Iterates over the parameters for the method signature \p sig.
6728 * A \c void* pointer must be initialized to NULL to start the iteration
6729 * and its address is passed to this function repeteadly until it returns
6731 * \returns the next parameter type of the method signature \p sig,
6732 * NULL when finished.
6735 mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
6741 /* start from the first */
6742 if (sig->param_count) {
6743 *iter = &sig->params [0];
6744 return sig->params [0];
6750 type = (MonoType **)*iter;
6752 if (type < &sig->params [sig->param_count]) {
6760 * mono_signature_get_param_count:
6761 * \param sig the method signature inspected
6762 * \returns the number of parameters in the method signature \p sig.
6765 mono_signature_get_param_count (MonoMethodSignature *sig)
6767 return sig->param_count;
6771 * mono_signature_get_call_conv:
6772 * \param sig the method signature inspected
6773 * \returns the call convention of the method signature \p sig.
6776 mono_signature_get_call_conv (MonoMethodSignature *sig)
6778 return sig->call_convention;
6782 * mono_signature_vararg_start:
6783 * \param sig the method signature inspected
6784 * \returns the number of the first vararg parameter in the
6785 * method signature \param sig. \c -1 if this is not a vararg signature.
6788 mono_signature_vararg_start (MonoMethodSignature *sig)
6790 return sig->sentinelpos;
6794 * mono_signature_is_instance:
6795 * \param sig the method signature inspected
6796 * \returns TRUE if this the method signature \p sig has an implicit
6797 * first instance argument. FALSE otherwise.
6800 mono_signature_is_instance (MonoMethodSignature *sig)
6802 return sig->hasthis;
6806 * mono_signature_param_is_out
6807 * \param sig the method signature inspected
6808 * \param param_num the 0-based index of the inspected parameter
6809 * \returns TRUE if the parameter is an out parameter, FALSE
6813 mono_signature_param_is_out (MonoMethodSignature *sig, int param_num)
6815 g_assert (param_num >= 0 && param_num < sig->param_count);
6816 return (sig->params [param_num]->attrs & PARAM_ATTRIBUTE_OUT) != 0;
6820 * mono_signature_explicit_this:
6821 * \param sig the method signature inspected
6822 * \returns TRUE if this the method signature \p sig has an explicit
6823 * instance argument. FALSE otherwise.
6826 mono_signature_explicit_this (MonoMethodSignature *sig)
6828 return sig->explicit_this;
6831 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
6833 mono_aligned_addr_hash (gconstpointer ptr)
6835 /* Same hashing we use for objects */
6836 return (GPOINTER_TO_UINT (ptr) >> 3) * 2654435761u;
6840 * If @field belongs to an inflated generic class, return the corresponding field of the
6841 * generic type definition class.
6844 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField *field)
6849 if (!mono_class_is_ginst (field->parent))
6852 gtd = mono_class_get_generic_class (field->parent)->container_class;
6853 offset = field - field->parent->fields;
6854 return gtd->fields + offset;
6858 * If @event belongs to an inflated generic class, return the corresponding event of the
6859 * generic type definition class.
6862 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent *event)
6867 if (!mono_class_is_ginst (event->parent))
6870 gtd = mono_class_get_generic_class (event->parent)->container_class;
6871 offset = event - mono_class_get_event_info (event->parent)->events;
6872 return mono_class_get_event_info (gtd)->events + offset;
6876 * If @property belongs to an inflated generic class, return the corresponding property of the
6877 * generic type definition class.
6880 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty *property)
6882 MonoClassPropertyInfo *info;
6886 if (!mono_class_is_ginst (property->parent))
6889 info = mono_class_get_property_info (property->parent);
6890 gtd = mono_class_get_generic_class (property->parent)->container_class;
6891 offset = property - info->properties;
6892 return mono_class_get_property_info (gtd)->properties + offset;
6896 mono_method_get_wrapper_cache (MonoMethod *method)
6898 if (method->is_inflated) {
6899 MonoMethodInflated *imethod = (MonoMethodInflated *)method;
6900 return &imethod->owner->wrapper_caches;
6902 return &method->klass->image->wrapper_caches;
6906 // 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.
6909 * mono_find_image_set_owner:
6911 * Find the imageset, if any, which a given pointer is located in the memory of.
6914 mono_find_image_set_owner (void *ptr)
6916 MonoImageSet *owner = NULL;
6923 for (i = 0; !owner && i < image_sets->len; ++i) {
6924 MonoImageSet *set = (MonoImageSet *)g_ptr_array_index (image_sets, i);
6925 if (mono_mempool_contains_addr (set->mempool, ptr))
6930 image_sets_unlock ();
6936 mono_loader_set_strict_strong_names (gboolean enabled)
6938 check_strong_names_strictly = enabled;
6942 mono_loader_get_strict_strong_names (void)
6944 return check_strong_names_strictly;