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/mono-counters.h>
36 static int img_set_cache_hit, img_set_cache_miss, img_set_count;
39 /* Auxiliary structure used for caching inflated signatures */
41 MonoMethodSignature *sig;
42 MonoGenericContext context;
43 } MonoInflatedMethodSignature;
45 static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, gboolean transient,
46 const char *ptr, const char **rptr, MonoError *error);
48 static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
49 static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
50 static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
51 static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
52 gboolean signature_only);
53 static void free_generic_inst (MonoGenericInst *ginst);
54 static void free_generic_class (MonoGenericClass *ginst);
55 static void free_inflated_method (MonoMethodInflated *method);
56 static void free_inflated_signature (MonoInflatedMethodSignature *sig);
57 static void mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image);
60 * This enumeration is used to describe the data types in the metadata
71 /* Index into Blob heap */
74 /* Index into String heap */
80 /* Pointer into a table */
83 /* HasConstant:Parent pointer (Param, Field or Property) */
86 /* HasCustomAttribute index. Indexes any table except CustomAttribute */
89 /* CustomAttributeType encoded index */
92 /* HasDeclSecurity index: TypeDef Method or Assembly */
95 /* Implementation coded index: File, Export AssemblyRef */
98 /* HasFieldMarshal coded index: Field or Param table */
101 /* MemberForwardedIndex: Field or Method */
104 /* TypeDefOrRef coded index: typedef, typeref, typespec */
107 /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
110 /* MethodDefOrRef coded index: Method or Member Ref table */
113 /* HasSemantic coded index: Event or Property */
116 /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
119 /* CustomDebugInformation parent encoded index */
120 MONO_MT_HASCUSTDEBUG_IDX
123 const static unsigned char TableSchemas [] = {
124 #define ASSEMBLY_SCHEMA_OFFSET 0
125 MONO_MT_UINT32, /* "HashId" }, */
126 MONO_MT_UINT16, /* "Major" }, */
127 MONO_MT_UINT16, /* "Minor" }, */
128 MONO_MT_UINT16, /* "BuildNumber" }, */
129 MONO_MT_UINT16, /* "RevisionNumber" }, */
130 MONO_MT_UINT32, /* "Flags" }, */
131 MONO_MT_BLOB_IDX, /* "PublicKey" }, */
132 MONO_MT_STRING_IDX, /* "Name" }, */
133 MONO_MT_STRING_IDX, /* "Culture" }, */
136 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
137 MONO_MT_UINT32, /* "OSPlatformID" }, */
138 MONO_MT_UINT32, /* "OSMajor" }, */
139 MONO_MT_UINT32, /* "OSMinor" }, */
142 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
143 MONO_MT_UINT32, /* "Processor" }, */
146 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
147 MONO_MT_UINT16, /* "Major" }, */
148 MONO_MT_UINT16, /* "Minor" }, */
149 MONO_MT_UINT16, /* "Build" }, */
150 MONO_MT_UINT16, /* "Revision" }, */
151 MONO_MT_UINT32, /* "Flags" }, */
152 MONO_MT_BLOB_IDX, /* "PublicKeyOrToken" }, */
153 MONO_MT_STRING_IDX, /* "Name" }, */
154 MONO_MT_STRING_IDX, /* "Culture" }, */
155 MONO_MT_BLOB_IDX, /* "HashValue" }, */
158 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
159 MONO_MT_UINT32, /* "OSPlatformID" }, */
160 MONO_MT_UINT32, /* "OSMajorVersion" }, */
161 MONO_MT_UINT32, /* "OSMinorVersion" }, */
162 MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */
165 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
166 MONO_MT_UINT32, /* "Processor" }, */
167 MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */
170 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
171 MONO_MT_UINT16, /* "PackingSize" }, */
172 MONO_MT_UINT32, /* "ClassSize" }, */
173 MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
176 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
177 MONO_MT_UINT8, /* "Type" }, */
178 MONO_MT_UINT8, /* "PaddingZero" }, */
179 MONO_MT_CONST_IDX, /* "Parent" }, */
180 MONO_MT_BLOB_IDX, /* "Value" }, */
183 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
184 MONO_MT_HASCAT_IDX, /* "Parent" }, */
185 MONO_MT_CAT_IDX, /* "Type" }, */
186 MONO_MT_BLOB_IDX, /* "Value" }, */
189 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
190 MONO_MT_UINT16, /* "Action" }, */
191 MONO_MT_HASDEC_IDX, /* "Parent" }, */
192 MONO_MT_BLOB_IDX, /* "PermissionSet" }, */
195 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
196 MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
197 MONO_MT_TABLE_IDX, /* "EventList:Event" }, */
200 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
201 MONO_MT_UINT16, /* "EventFlags#EventAttribute" }, */
202 MONO_MT_STRING_IDX, /* "Name" }, */
203 MONO_MT_TDOR_IDX, /* "EventType" }, TypeDef or TypeRef or TypeSpec */
206 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
207 MONO_MT_TABLE_IDX, /* "Event" }, */
210 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
211 MONO_MT_UINT32, /* "Flags" }, */
212 MONO_MT_TABLE_IDX, /* "TypeDefId" }, */
213 MONO_MT_STRING_IDX, /* "TypeName" }, */
214 MONO_MT_STRING_IDX, /* "TypeNameSpace" }, */
215 MONO_MT_IMPL_IDX, /* "Implementation" }, */
218 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
219 MONO_MT_UINT16, /* "Flags" }, */
220 MONO_MT_STRING_IDX, /* "Name" }, */
221 MONO_MT_BLOB_IDX, /* "Signature" }, */
224 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
225 MONO_MT_UINT32, /* "Offset" }, */
226 MONO_MT_TABLE_IDX, /* "Field:Field" }, */
229 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
230 MONO_MT_HFM_IDX, /* "Parent" }, */
231 MONO_MT_BLOB_IDX, /* "NativeType" }, */
234 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
235 MONO_MT_UINT32, /* "RVA" }, */
236 MONO_MT_TABLE_IDX, /* "Field:Field" }, */
239 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
240 MONO_MT_TABLE_IDX, /* "Field" }, */
243 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
244 MONO_MT_UINT32, /* "Flags" }, */
245 MONO_MT_STRING_IDX, /* "Name" }, */
246 MONO_MT_BLOB_IDX, /* "Value" }, */
249 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
250 MONO_MT_UINT16, /* "MappingFlag" }, */
251 MONO_MT_MF_IDX, /* "MemberForwarded" }, */
252 MONO_MT_STRING_IDX, /* "ImportName" }, */
253 MONO_MT_TABLE_IDX, /* "ImportScope:ModuleRef" }, */
256 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
257 MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */
258 MONO_MT_TDOR_IDX, /* "Interface=TypeDefOrRef" }, */
261 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
262 MONO_MT_UINT32, /* "Offset" }, */
263 MONO_MT_UINT32, /* "Flags" }, */
264 MONO_MT_STRING_IDX, /* "Name" }, */
265 MONO_MT_IMPL_IDX, /* "Implementation" }, */
268 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
269 MONO_MT_MRP_IDX, /* "Class" }, */
270 MONO_MT_STRING_IDX, /* "Name" }, */
271 MONO_MT_BLOB_IDX, /* "Signature" }, */
274 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
275 MONO_MT_UINT32, /* "RVA" }, */
276 MONO_MT_UINT16, /* "ImplFlags#MethodImplAttributes" }, */
277 MONO_MT_UINT16, /* "Flags#MethodAttribute" }, */
278 MONO_MT_STRING_IDX, /* "Name" }, */
279 MONO_MT_BLOB_IDX, /* "Signature" }, */
280 MONO_MT_TABLE_IDX, /* "ParamList:Param" }, */
283 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
284 MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */
285 MONO_MT_MDOR_IDX, /* "MethodBody" }, */
286 MONO_MT_MDOR_IDX, /* "MethodDeclaration" }, */
289 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
290 MONO_MT_UINT16, /* "MethodSemantic" }, */
291 MONO_MT_TABLE_IDX, /* "Method:Method" }, */
292 MONO_MT_HS_IDX, /* "Association" }, */
295 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
296 MONO_MT_TABLE_IDX, /* "Method" }, */
299 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
300 MONO_MT_UINT16, /* "Generation" }, */
301 MONO_MT_STRING_IDX, /* "Name" }, */
302 MONO_MT_GUID_IDX, /* "MVID" }, */
303 MONO_MT_GUID_IDX, /* "EncID" }, */
304 MONO_MT_GUID_IDX, /* "EncBaseID" }, */
307 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
308 MONO_MT_STRING_IDX, /* "Name" }, */
311 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
312 MONO_MT_TABLE_IDX, /* "NestedClass:TypeDef" }, */
313 MONO_MT_TABLE_IDX, /* "EnclosingClass:TypeDef" }, */
316 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
317 MONO_MT_UINT16, /* "Flags" }, */
318 MONO_MT_UINT16, /* "Sequence" }, */
319 MONO_MT_STRING_IDX, /* "Name" }, */
322 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
323 MONO_MT_TABLE_IDX, /* "Param" }, */
326 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
327 MONO_MT_UINT16, /* "Flags" }, */
328 MONO_MT_STRING_IDX, /* "Name" }, */
329 MONO_MT_BLOB_IDX, /* "Type" }, */
332 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
333 MONO_MT_TABLE_IDX, /* "Property" }, */
336 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
337 MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
338 MONO_MT_TABLE_IDX, /* "PropertyList:Property" }, */
341 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
342 MONO_MT_BLOB_IDX, /* "Signature" }, */
345 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
346 MONO_MT_UINT32, /* "Flags" }, */
347 MONO_MT_STRING_IDX, /* "Name" }, */
348 MONO_MT_STRING_IDX, /* "Namespace" }, */
349 MONO_MT_TDOR_IDX, /* "Extends" }, */
350 MONO_MT_TABLE_IDX, /* "FieldList:Field" }, */
351 MONO_MT_TABLE_IDX, /* "MethodList:Method" }, */
354 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
355 MONO_MT_RS_IDX, /* "ResolutionScope=ResolutionScope" }, */
356 MONO_MT_STRING_IDX, /* "Name" }, */
357 MONO_MT_STRING_IDX, /* "Namespace" }, */
360 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
361 MONO_MT_BLOB_IDX, /* "Signature" }, */
364 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
365 MONO_MT_UINT16, /* "Number" }, */
366 MONO_MT_UINT16, /* "Flags" }, */
367 MONO_MT_TABLE_IDX, /* "Owner" }, TypeDef or MethodDef */
368 MONO_MT_STRING_IDX, /* "Name" }, */
371 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
372 MONO_MT_MDOR_IDX, /* "Method" }, */
373 MONO_MT_BLOB_IDX, /* "Signature" }, */
376 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
377 MONO_MT_TABLE_IDX, /* "GenericParam" }, */
378 MONO_MT_TDOR_IDX, /* "Constraint" }, */
381 #define DOCUMENT_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
382 MONO_MT_BLOB_IDX, /* Name */
383 MONO_MT_GUID_IDX, /* HashAlgorithm */
384 MONO_MT_BLOB_IDX, /* Hash */
385 MONO_MT_GUID_IDX, /* Language */
388 #define METHODBODY_SCHEMA_OFFSET DOCUMENT_SCHEMA_OFFSET + 5
389 MONO_MT_TABLE_IDX, /* Document */
390 MONO_MT_BLOB_IDX, /* SequencePoints */
393 #define LOCALSCOPE_SCHEMA_OFFSET METHODBODY_SCHEMA_OFFSET + 3
394 MONO_MT_TABLE_IDX, /* Method */
395 MONO_MT_TABLE_IDX, /* ImportScope */
396 MONO_MT_TABLE_IDX, /* VariableList */
397 MONO_MT_TABLE_IDX, /* ConstantList */
398 MONO_MT_UINT32, /* StartOffset */
399 MONO_MT_UINT32, /* Length */
402 #define LOCALVARIABLE_SCHEMA_OFFSET LOCALSCOPE_SCHEMA_OFFSET + 7
403 MONO_MT_UINT16, /* Attributes */
404 MONO_MT_UINT16, /* Index */
405 MONO_MT_STRING_IDX, /* Name */
408 #define LOCALCONSTANT_SCHEMA_OFFSET LOCALVARIABLE_SCHEMA_OFFSET + 4
409 MONO_MT_STRING_IDX, /* Name (String heap index) */
410 MONO_MT_BLOB_IDX, /* Signature (Blob heap index, LocalConstantSig blob) */
413 #define IMPORTSCOPE_SCHEMA_OFFSET LOCALCONSTANT_SCHEMA_OFFSET + 3
414 MONO_MT_TABLE_IDX, /* Parent (ImportScope row id or nil) */
415 MONO_MT_BLOB_IDX, /* Imports (Blob index, encoding: Imports blob) */
418 #define ASYNCMETHOD_SCHEMA_OFFSET IMPORTSCOPE_SCHEMA_OFFSET + 3
419 MONO_MT_TABLE_IDX, /* MoveNextMethod (MethodDef row id) */
420 MONO_MT_TABLE_IDX, /* KickoffMethod (MethodDef row id) */
423 #define CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET ASYNCMETHOD_SCHEMA_OFFSET + 3
424 MONO_MT_HASCUSTDEBUG_IDX, /* Parent (HasCustomDebugInformation coded index) */
425 MONO_MT_GUID_IDX, /* Kind (Guid heap index) */
426 MONO_MT_BLOB_IDX, /* Value (Blob heap index) */
429 #define NULL_SCHEMA_OFFSET CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET + 4
433 /* Must be the same order as MONO_TABLE_* */
434 const static unsigned char
435 table_description [] = {
436 MODULE_SCHEMA_OFFSET,
437 TYPEREF_SCHEMA_OFFSET,
438 TYPEDEF_SCHEMA_OFFSET,
439 FIELD_POINTER_SCHEMA_OFFSET,
441 METHOD_POINTER_SCHEMA_OFFSET,
442 METHOD_SCHEMA_OFFSET,
443 PARAM_POINTER_SCHEMA_OFFSET,
445 IFACEMAP_SCHEMA_OFFSET,
446 MEMBERREF_SCHEMA_OFFSET, /* 0xa */
447 CONSTANT_SCHEMA_OFFSET,
448 CUSTOM_ATTR_SCHEMA_OFFSET,
449 FIELD_MARSHAL_SCHEMA_OFFSET,
450 DECL_SEC_SCHEMA_OFFSET,
451 CLASS_LAYOUT_SCHEMA_OFFSET,
452 FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
453 STDALON_SIG_SCHEMA_OFFSET,
454 EVENTMAP_SCHEMA_OFFSET,
455 EVENT_POINTER_SCHEMA_OFFSET,
457 PROPERTY_MAP_SCHEMA_OFFSET,
458 PROPERTY_POINTER_SCHEMA_OFFSET,
459 PROPERTY_SCHEMA_OFFSET,
460 METHOD_SEMA_SCHEMA_OFFSET,
461 METHOD_IMPL_SCHEMA_OFFSET,
462 MODULEREF_SCHEMA_OFFSET, /* 0x1a */
463 TYPESPEC_SCHEMA_OFFSET,
464 IMPLMAP_SCHEMA_OFFSET,
465 FIELD_RVA_SCHEMA_OFFSET,
468 ASSEMBLY_SCHEMA_OFFSET, /* 0x20 */
469 ASSEMBLYPROC_SCHEMA_OFFSET,
470 ASSEMBLYOS_SCHEMA_OFFSET,
471 ASSEMBLYREF_SCHEMA_OFFSET,
472 ASSEMBLYREFPROC_SCHEMA_OFFSET,
473 ASSEMBLYREFOS_SCHEMA_OFFSET,
475 EXPORTED_TYPE_SCHEMA_OFFSET,
476 MANIFEST_SCHEMA_OFFSET,
477 NESTED_CLASS_SCHEMA_OFFSET,
478 GENPARAM_SCHEMA_OFFSET, /* 0x2a */
479 METHOD_SPEC_SCHEMA_OFFSET,
480 GEN_CONSTRAINT_SCHEMA_OFFSET,
484 DOCUMENT_SCHEMA_OFFSET, /* 0x30 */
485 METHODBODY_SCHEMA_OFFSET,
486 LOCALSCOPE_SCHEMA_OFFSET,
487 LOCALVARIABLE_SCHEMA_OFFSET,
488 LOCALCONSTANT_SCHEMA_OFFSET,
489 IMPORTSCOPE_SCHEMA_OFFSET,
490 ASYNCMETHOD_SCHEMA_OFFSET,
491 CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET
494 #ifdef HAVE_ARRAY_ELEM_INIT
495 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
496 #define MSGSTRFIELD1(line) str##line
497 static const struct msgstr_t {
498 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
499 #include "mono/cil/tables.def"
502 #define TABLEDEF(a,b) b,
503 #include "mono/cil/tables.def"
506 static const gint16 tableidx [] = {
507 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
508 #include "mono/cil/tables.def"
513 #define TABLEDEF(a,b) b,
514 static const char* const
515 mono_tables_names [] = {
516 #include "mono/cil/tables.def"
522 /* If TRUE (but also see DISABLE_STICT_STRONG_NAMES #define), Mono will check
523 * that the public key token, culture and version of a candidate assembly matches
524 * the requested strong name. If FALSE, as long as the name matches, the candidate
527 static gboolean check_strong_names_strictly = FALSE;
529 // Amount initially reserved in each imageset's mempool.
530 // FIXME: This number is arbitrary, a more practical number should be found
531 #define INITIAL_IMAGE_SET_SIZE 1024
534 * mono_meta_table_name:
535 * \param table table index
537 * Returns the name of the given ECMA metadata logical format table
538 * as described in ECMA 335, Partition II, Section 22.
540 * \returns the name for the \p table index
543 mono_meta_table_name (int table)
545 if ((table < 0) || (table > MONO_TABLE_LAST))
548 #ifdef HAVE_ARRAY_ELEM_INIT
549 return (const char*)&tablestr + tableidx [table];
551 return mono_tables_names [table];
555 /* The guy who wrote the spec for this should not be allowed near a
558 If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
559 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
560 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
561 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
562 inverse of this mapping.
565 #define rtsize(meta,s,b) (((s) < (1 << (b)) ? 2 : 4))
568 idx_size (MonoImage *meta, int tableidx)
570 if (meta->referenced_tables && (meta->referenced_tables & ((guint64)1 << tableidx)))
571 return meta->referenced_table_rows [tableidx] < 65536 ? 2 : 4;
573 return meta->tables [tableidx].rows < 65536 ? 2 : 4;
577 get_nrows (MonoImage *meta, int tableidx)
579 if (meta->referenced_tables && (meta->referenced_tables & ((guint64)1 << tableidx)))
580 return meta->referenced_table_rows [tableidx];
582 return meta->tables [tableidx].rows;
585 /* Reference: Partition II - 23.2.6 */
587 * mono_metadata_compute_size:
588 * \param meta metadata context
589 * \param tableindex metadata table number
590 * \param result_bitfield pointer to \c guint32 where to store additional info
592 * \c mono_metadata_compute_size computes the length in bytes of a single
593 * row in a metadata table. The size of each column is encoded in the
594 * \p result_bitfield return value along with the number of columns in the table.
595 * the resulting bitfield should be handed to the \c mono_metadata_table_size
596 * and \c mono_metadata_table_count macros.
597 * This is a Mono runtime internal only function.
600 mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
602 guint32 bitfield = 0;
603 int size = 0, field_size = 0;
606 const unsigned char *description = TableSchemas + table_description [tableindex];
608 for (i = 0; (code = description [i]) != MONO_MT_END; i++){
611 field_size = 4; break;
614 field_size = 2; break;
617 field_size = 1; break;
619 case MONO_MT_BLOB_IDX:
620 field_size = meta->idx_blob_wide ? 4 : 2; break;
622 case MONO_MT_STRING_IDX:
623 field_size = meta->idx_string_wide ? 4 : 2; break;
625 case MONO_MT_GUID_IDX:
626 field_size = meta->idx_guid_wide ? 4 : 2; break;
628 case MONO_MT_TABLE_IDX:
629 /* Uhm, a table index can point to other tables besides the current one
630 * so, it's not correct to use the rowcount of the current table to
631 * get the size for this column - lupus
633 switch (tableindex) {
634 case MONO_TABLE_ASSEMBLYREFOS:
636 field_size = idx_size (meta, MONO_TABLE_ASSEMBLYREF); break;
637 case MONO_TABLE_ASSEMBLYREFPROCESSOR:
639 field_size = idx_size (meta, MONO_TABLE_ASSEMBLYREF); break;
640 case MONO_TABLE_CLASSLAYOUT:
642 field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
643 case MONO_TABLE_EVENTMAP:
644 g_assert (i == 0 || i == 1);
645 field_size = i ? idx_size (meta, MONO_TABLE_EVENT):
646 idx_size (meta, MONO_TABLE_TYPEDEF);
648 case MONO_TABLE_EVENT_POINTER:
650 field_size = idx_size (meta, MONO_TABLE_EVENT); break;
651 case MONO_TABLE_EXPORTEDTYPE:
653 /* the index is in another metadata file, so it must be 4 */
654 field_size = 4; break;
655 case MONO_TABLE_FIELDLAYOUT:
657 field_size = idx_size (meta, MONO_TABLE_FIELD); break;
658 case MONO_TABLE_FIELDRVA:
660 field_size = idx_size (meta, MONO_TABLE_FIELD); break;
661 case MONO_TABLE_FIELD_POINTER:
663 field_size = idx_size (meta, MONO_TABLE_FIELD); break;
664 case MONO_TABLE_IMPLMAP:
666 field_size = idx_size (meta, MONO_TABLE_MODULEREF); break;
667 case MONO_TABLE_INTERFACEIMPL:
669 field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
670 case MONO_TABLE_METHOD:
672 field_size = idx_size (meta, MONO_TABLE_PARAM); break;
673 case MONO_TABLE_METHODIMPL:
675 field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
676 case MONO_TABLE_METHODSEMANTICS:
678 field_size = idx_size (meta, MONO_TABLE_METHOD); break;
679 case MONO_TABLE_METHOD_POINTER:
681 field_size = idx_size (meta, MONO_TABLE_METHOD); break;
682 case MONO_TABLE_NESTEDCLASS:
683 g_assert (i == 0 || i == 1);
684 field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
685 case MONO_TABLE_PARAM_POINTER:
687 field_size = idx_size (meta, MONO_TABLE_PARAM); break;
688 case MONO_TABLE_PROPERTYMAP:
689 g_assert (i == 0 || i == 1);
690 field_size = i ? idx_size (meta, MONO_TABLE_PROPERTY):
691 idx_size (meta, MONO_TABLE_TYPEDEF);
693 case MONO_TABLE_PROPERTY_POINTER:
695 field_size = idx_size (meta, MONO_TABLE_PROPERTY); break;
696 case MONO_TABLE_TYPEDEF:
697 g_assert (i == 4 || i == 5);
698 field_size = i == 4 ? idx_size (meta, MONO_TABLE_FIELD):
699 idx_size (meta, MONO_TABLE_METHOD);
701 case MONO_TABLE_GENERICPARAM:
703 n = MAX (get_nrows (meta, MONO_TABLE_METHOD), get_nrows (meta, MONO_TABLE_TYPEDEF));
704 /*This is a coded token for 2 tables, so takes 1 bit */
705 field_size = rtsize (meta, n, 16 - MONO_TYPEORMETHOD_BITS);
707 case MONO_TABLE_GENERICPARAMCONSTRAINT:
709 field_size = idx_size (meta, MONO_TABLE_GENERICPARAM);
711 case MONO_TABLE_LOCALSCOPE:
714 // FIXME: This table is in another file
715 field_size = idx_size (meta, MONO_TABLE_METHOD);
718 field_size = idx_size (meta, MONO_TABLE_IMPORTSCOPE);
721 field_size = idx_size (meta, MONO_TABLE_LOCALVARIABLE);
724 field_size = idx_size (meta, MONO_TABLE_LOCALCONSTANT);
727 g_assert_not_reached ();
731 case MONO_TABLE_METHODBODY:
733 field_size = idx_size (meta, MONO_TABLE_DOCUMENT); break;
734 case MONO_TABLE_IMPORTSCOPE:
736 field_size = idx_size (meta, MONO_TABLE_IMPORTSCOPE); break;
737 case MONO_TABLE_STATEMACHINEMETHOD:
738 g_assert(i == 0 || i == 1);
739 field_size = idx_size(meta, MONO_TABLE_METHOD); break;
741 g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex, i);
746 * HasConstant: ParamDef, FieldDef, Property
748 case MONO_MT_CONST_IDX:
749 n = MAX (get_nrows (meta, MONO_TABLE_PARAM),
750 get_nrows (meta, MONO_TABLE_FIELD));
751 n = MAX (n, get_nrows (meta, MONO_TABLE_PROPERTY));
753 /* 2 bits to encode tag */
754 field_size = rtsize (meta, n, 16-2);
758 * HasCustomAttribute: points to any table but
761 case MONO_MT_HASCAT_IDX:
763 * We believe that since the signature and
764 * permission are indexing the Blob heap,
765 * we should consider the blob size first
767 /* I'm not a believer - lupus
768 if (meta->idx_blob_wide){
773 n = MAX (get_nrows (meta, MONO_TABLE_METHOD),
774 get_nrows (meta, MONO_TABLE_FIELD));
775 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPEREF));
776 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPEDEF));
777 n = MAX (n, get_nrows (meta, MONO_TABLE_PARAM));
778 n = MAX (n, get_nrows (meta, MONO_TABLE_INTERFACEIMPL));
779 n = MAX (n, get_nrows (meta, MONO_TABLE_MEMBERREF));
780 n = MAX (n, get_nrows (meta, MONO_TABLE_MODULE));
781 n = MAX (n, get_nrows (meta, MONO_TABLE_DECLSECURITY));
782 n = MAX (n, get_nrows (meta, MONO_TABLE_PROPERTY));
783 n = MAX (n, get_nrows (meta, MONO_TABLE_EVENT));
784 n = MAX (n, get_nrows (meta, MONO_TABLE_STANDALONESIG));
785 n = MAX (n, get_nrows (meta, MONO_TABLE_MODULEREF));
786 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPESPEC));
787 n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLY));
788 n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
789 n = MAX (n, get_nrows (meta, MONO_TABLE_FILE));
790 n = MAX (n, get_nrows (meta, MONO_TABLE_EXPORTEDTYPE));
791 n = MAX (n, get_nrows (meta, MONO_TABLE_MANIFESTRESOURCE));
792 n = MAX (n, get_nrows (meta, MONO_TABLE_GENERICPARAM));
793 n = MAX (n, get_nrows (meta, MONO_TABLE_GENERICPARAMCONSTRAINT));
794 n = MAX (n, get_nrows (meta, MONO_TABLE_METHODSPEC));
796 /* 5 bits to encode */
797 field_size = rtsize (meta, n, 16-5);
801 * HasCustomAttribute: points to any table but
805 case MONO_MT_HASCUSTDEBUG_IDX:
806 n = MAX(get_nrows (meta, MONO_TABLE_METHOD),
807 get_nrows (meta, MONO_TABLE_FIELD));
808 n = MAX(n, get_nrows (meta, MONO_TABLE_TYPEREF));
809 n = MAX(n, get_nrows (meta, MONO_TABLE_TYPEDEF));
810 n = MAX(n, get_nrows (meta, MONO_TABLE_PARAM));
811 n = MAX(n, get_nrows (meta, MONO_TABLE_INTERFACEIMPL));
812 n = MAX(n, get_nrows (meta, MONO_TABLE_MEMBERREF));
813 n = MAX(n, get_nrows (meta, MONO_TABLE_MODULE));
814 n = MAX(n, get_nrows (meta, MONO_TABLE_DECLSECURITY));
815 n = MAX(n, get_nrows (meta, MONO_TABLE_PROPERTY));
816 n = MAX(n, get_nrows (meta, MONO_TABLE_EVENT));
817 n = MAX(n, get_nrows (meta, MONO_TABLE_STANDALONESIG));
818 n = MAX(n, get_nrows (meta, MONO_TABLE_MODULEREF));
819 n = MAX(n, get_nrows (meta, MONO_TABLE_TYPESPEC));
820 n = MAX(n, get_nrows (meta, MONO_TABLE_ASSEMBLY));
821 n = MAX(n, get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
822 n = MAX(n, get_nrows (meta, MONO_TABLE_FILE));
823 n = MAX(n, get_nrows (meta, MONO_TABLE_EXPORTEDTYPE));
824 n = MAX(n, get_nrows (meta, MONO_TABLE_MANIFESTRESOURCE));
825 n = MAX(n, get_nrows (meta, MONO_TABLE_GENERICPARAM));
826 n = MAX(n, get_nrows (meta, MONO_TABLE_GENERICPARAMCONSTRAINT));
827 n = MAX(n, get_nrows (meta, MONO_TABLE_METHODSPEC));
828 n = MAX(n, get_nrows (meta, MONO_TABLE_DOCUMENT));
829 n = MAX(n, get_nrows (meta, MONO_TABLE_LOCALSCOPE));
830 n = MAX(n, get_nrows (meta, MONO_TABLE_LOCALVARIABLE));
831 n = MAX(n, get_nrows (meta, MONO_TABLE_LOCALCONSTANT));
832 n = MAX(n, get_nrows (meta, MONO_TABLE_IMPORTSCOPE));
834 /* 5 bits to encode */
835 field_size = rtsize(meta, n, 16 - 5);
839 * CustomAttributeType: MethodDef, MemberRef.
841 case MONO_MT_CAT_IDX:
842 n = MAX (get_nrows (meta, MONO_TABLE_METHOD),
843 get_nrows (meta, MONO_TABLE_MEMBERREF));
845 /* 3 bits to encode */
846 field_size = rtsize (meta, n, 16-3);
850 * HasDeclSecurity: Typedef, MethodDef, Assembly
852 case MONO_MT_HASDEC_IDX:
853 n = MAX (get_nrows (meta, MONO_TABLE_TYPEDEF),
854 get_nrows (meta, MONO_TABLE_METHOD));
855 n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLY));
857 /* 2 bits to encode */
858 field_size = rtsize (meta, n, 16-2);
862 * Implementation: File, AssemblyRef, ExportedType
864 case MONO_MT_IMPL_IDX:
865 n = MAX (get_nrows (meta, MONO_TABLE_FILE),
866 get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
867 n = MAX (n, get_nrows (meta, MONO_TABLE_EXPORTEDTYPE));
869 /* 2 bits to encode tag */
870 field_size = rtsize (meta, n, 16-2);
874 * HasFieldMarshall: FieldDef, ParamDef
876 case MONO_MT_HFM_IDX:
877 n = MAX (get_nrows (meta, MONO_TABLE_FIELD),
878 get_nrows (meta, MONO_TABLE_PARAM));
880 /* 1 bit used to encode tag */
881 field_size = rtsize (meta, n, 16-1);
885 * MemberForwarded: FieldDef, MethodDef
888 n = MAX (get_nrows (meta, MONO_TABLE_FIELD),
889 get_nrows (meta, MONO_TABLE_METHOD));
891 /* 1 bit used to encode tag */
892 field_size = rtsize (meta, n, 16-1);
896 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
898 * It is TypeDef, _TypeRef_, TypeSpec, instead.
900 case MONO_MT_TDOR_IDX:
901 n = MAX (get_nrows (meta, MONO_TABLE_TYPEDEF),
902 get_nrows (meta, MONO_TABLE_TYPEREF));
903 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPESPEC));
905 /* 2 bits to encode */
906 field_size = rtsize (meta, n, 16-2);
910 * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
912 case MONO_MT_MRP_IDX:
913 n = MAX (get_nrows (meta, MONO_TABLE_TYPEDEF),
914 get_nrows (meta, MONO_TABLE_TYPEREF));
915 n = MAX (n, get_nrows (meta, MONO_TABLE_METHOD));
916 n = MAX (n, get_nrows (meta, MONO_TABLE_MODULEREF));
917 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPESPEC));
919 /* 3 bits to encode */
920 field_size = rtsize (meta, n, 16 - 3);
924 * MethodDefOrRef: MethodDef, MemberRef
926 case MONO_MT_MDOR_IDX:
927 n = MAX (get_nrows (meta, MONO_TABLE_METHOD),
928 get_nrows (meta, MONO_TABLE_MEMBERREF));
930 /* 1 bit used to encode tag */
931 field_size = rtsize (meta, n, 16-1);
935 * HasSemantics: Property, Event
938 n = MAX (get_nrows (meta, MONO_TABLE_PROPERTY),
939 get_nrows (meta, MONO_TABLE_EVENT));
941 /* 1 bit used to encode tag */
942 field_size = rtsize (meta, n, 16-1);
946 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
949 n = MAX (get_nrows (meta, MONO_TABLE_MODULE),
950 get_nrows (meta, MONO_TABLE_MODULEREF));
951 n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
952 n = MAX (n, get_nrows (meta, MONO_TABLE_TYPEREF));
954 /* 2 bits used to encode tag (ECMA spec claims 3) */
955 field_size = rtsize (meta, n, 16 - 2);
960 * encode field size as follows (we just need to
967 bitfield |= (field_size-1) << shift;
970 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
973 *result_bitfield = (i << 24) | bitfield;
978 * mono_metadata_compute_table_bases:
979 * \param meta metadata context to compute table values
981 * Computes the table bases for the metadata structure.
982 * This is an internal function used by the image loader code.
985 mono_metadata_compute_table_bases (MonoImage *meta)
988 const char *base = meta->tables_base;
990 for (i = 0; i < MONO_TABLE_NUM; i++) {
991 MonoTableInfo *table = &meta->tables [i];
992 if (table->rows == 0)
995 table->row_size = mono_metadata_compute_size (meta, i, &table->size_bitfield);
997 base += table->rows * table->row_size;
1002 * mono_metadata_locate:
1003 * \param meta metadata context
1004 * \param table table code.
1005 * \param idx index of element to retrieve from \p table.
1007 * \returns a pointer to the \p idx element in the metadata table
1008 * whose code is \p table.
1011 mono_metadata_locate (MonoImage *meta, int table, int idx)
1013 /* idx == 0 refers always to NULL */
1014 g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, ""); /*FIXME shouldn't we return NULL here?*/
1016 return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
1020 * mono_metadata_locate_token:
1021 * \param meta metadata context
1022 * \param token metadata token
1024 * \returns a pointer to the data in the metadata represented by the
1028 mono_metadata_locate_token (MonoImage *meta, guint32 token)
1030 return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
1034 * mono_metadata_string_heap:
1035 * \param meta metadata context
1036 * \param index index into the string heap.
1037 * \returns an in-memory pointer to the \p index in the string heap.
1040 mono_metadata_string_heap (MonoImage *meta, guint32 index)
1042 g_assert (index < meta->heap_strings.size);
1043 g_return_val_if_fail (index < meta->heap_strings.size, "");
1044 return meta->heap_strings.data + index;
1048 * mono_metadata_user_string:
1049 * \param meta metadata context
1050 * \param index index into the user string heap.
1051 * \returns an in-memory pointer to the \p index in the user string heap (<code>#US</code>).
1054 mono_metadata_user_string (MonoImage *meta, guint32 index)
1056 g_assert (index < meta->heap_us.size);
1057 g_return_val_if_fail (index < meta->heap_us.size, "");
1058 return meta->heap_us.data + index;
1062 * mono_metadata_blob_heap:
1063 * \param meta metadata context
1064 * \param index index into the blob.
1065 * \returns an in-memory pointer to the \p index in the Blob heap.
1068 mono_metadata_blob_heap (MonoImage *meta, guint32 index)
1070 g_assert (index < meta->heap_blob.size);
1071 g_return_val_if_fail (index < meta->heap_blob.size, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
1072 return meta->heap_blob.data + index;
1076 * mono_metadata_guid_heap:
1077 * \param meta metadata context
1078 * \param index index into the guid heap.
1079 * \returns an in-memory pointer to the \p index in the guid heap.
1082 mono_metadata_guid_heap (MonoImage *meta, guint32 index)
1085 index *= 16; /* adjust for guid size and 1-based index */
1086 g_return_val_if_fail (index < meta->heap_guid.size, "");
1087 return meta->heap_guid.data + index;
1090 static const unsigned char *
1091 dword_align (const unsigned char *ptr)
1093 #if SIZEOF_VOID_P == 8
1094 return (const unsigned char *) (((guint64) (ptr + 3)) & ~3);
1096 return (const unsigned char *) (((guint32) (ptr + 3)) & ~3);
1101 * mono_metadata_decode_row:
1102 * \param t table to extract information from.
1103 * \param idx index in table.
1104 * \param res array of \p res_size cols to store the results in
1106 * This decompresses the metadata element \p idx in table \p t
1107 * into the \c guint32 \p res array that has \p res_size elements
1110 mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size)
1112 guint32 bitfield = t->size_bitfield;
1113 int i, count = mono_metadata_table_count (bitfield);
1116 g_assert (idx < t->rows);
1117 g_assert (idx >= 0);
1118 data = t->base + idx * t->row_size;
1120 g_assert (res_size == count);
1122 for (i = 0; i < count; i++) {
1123 int n = mono_metadata_table_size (bitfield, i);
1127 res [i] = *data; break;
1129 res [i] = read16 (data); break;
1131 res [i] = read32 (data); break;
1133 g_assert_not_reached ();
1140 * mono_metadata_decode_row_col:
1141 * \param t table to extract information from.
1142 * \param idx index for row in table.
1143 * \param col column in the row.
1145 * This function returns the value of column \p col from the \p idx
1146 * row in the table \p t .
1149 mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
1151 guint32 bitfield = t->size_bitfield;
1153 register const char *data;
1156 g_assert (idx < t->rows);
1157 g_assert (col < mono_metadata_table_count (bitfield));
1158 data = t->base + idx * t->row_size;
1160 n = mono_metadata_table_size (bitfield, 0);
1161 for (i = 0; i < col; ++i) {
1163 n = mono_metadata_table_size (bitfield, i + 1);
1169 return read16 (data);
1171 return read32 (data);
1173 g_assert_not_reached ();
1179 * mono_metadata_decode_blob_size:
1180 * \param ptr pointer to a blob object
1181 * \param rptr the new position of the pointer
1183 * This decodes a compressed size as described by 24.2.4 (#US and #Blob a blob or user string object)
1185 * \returns the size of the blob object
1188 mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
1190 const unsigned char *ptr = (const unsigned char *)xptr;
1193 if ((*ptr & 0x80) == 0){
1194 size = ptr [0] & 0x7f;
1196 } else if ((*ptr & 0x40) == 0){
1197 size = ((ptr [0] & 0x3f) << 8) + ptr [1];
1200 size = ((ptr [0] & 0x1f) << 24) +
1212 * mono_metadata_decode_value:
1213 * \param ptr pointer to decode from
1214 * \param rptr the new position of the pointer
1216 * This routine decompresses 32-bit values as specified in the "Blob and
1217 * Signature" section (23.2)
1219 * \returns the decoded value
1222 mono_metadata_decode_value (const char *_ptr, const char **rptr)
1224 const unsigned char *ptr = (const unsigned char *) _ptr;
1225 unsigned char b = *ptr;
1228 if ((b & 0x80) == 0){
1231 } else if ((b & 0x40) == 0){
1232 len = ((b & 0x3f) << 8 | ptr [1]);
1235 len = ((b & 0x1f) << 24) |
1248 * mono_metadata_decode_signed_value:
1249 * \param ptr pointer to decode from
1250 * \param rptr the new position of the pointer
1252 * This routine decompresses 32-bit signed values
1253 * (not specified in the spec)
1255 * \returns the decoded value
1258 mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
1260 guint32 uval = mono_metadata_decode_value (ptr, rptr);
1261 gint32 ival = uval >> 1;
1264 /* ival is a truncated 2's complement negative number. */
1266 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1269 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1270 return ival - 0x2000;
1271 if (ival < 0x10000000)
1272 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1273 return ival - 0x10000000;
1274 g_assert (ival < 0x20000000);
1275 g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival, uval);
1276 return ival - 0x20000000;
1280 * mono_metadata_translate_token_index:
1281 * Translates the given 1-based index into the \c Method, \c Field, \c Event, or \c Param tables
1282 * using the \c *Ptr tables in uncompressed metadata, if they are available.
1284 * FIXME: The caller is not forced to call this function, which is error-prone, since
1285 * forgetting to call it would only show up as a bug on uncompressed metadata.
1288 mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
1290 if (!image->uncompressed_metadata)
1294 case MONO_TABLE_METHOD:
1295 if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
1296 return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
1299 case MONO_TABLE_FIELD:
1300 if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
1301 return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
1304 case MONO_TABLE_EVENT:
1305 if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
1306 return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
1309 case MONO_TABLE_PROPERTY:
1310 if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
1311 return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
1314 case MONO_TABLE_PARAM:
1315 if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
1316 return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
1325 * mono_metadata_decode_table_row:
1327 * Same as \c mono_metadata_decode_row, but takes an \p image + \p table ID pair, and takes
1328 * uncompressed metadata into account, so it should be used to access the
1329 * \c Method, \c Field, \c Param and \c Event tables when the access is made from metadata, i.e.
1330 * \p idx is retrieved from a metadata table, like \c MONO_TYPEDEF_FIELD_LIST.
1333 mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
1335 if (image->uncompressed_metadata)
1336 idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1338 mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
1342 * mono_metadata_decode_table_row_col:
1344 * Same as \c mono_metadata_decode_row_col, but takes an \p image + \p table ID pair, and takes
1345 * uncompressed metadata into account, so it should be used to access the
1346 * \c Method, \c Field, \c Param and \c Event tables.
1348 guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
1350 if (image->uncompressed_metadata)
1351 idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1353 return mono_metadata_decode_row_col (&image->tables [table], idx, col);
1357 * mono_metadata_parse_typedef_or_ref:
1358 * \param m a metadata context.
1359 * \param ptr a pointer to an encoded TypedefOrRef in \p m
1360 * \param rptr pointer updated to match the end of the decoded stream
1361 * \returns a token valid in the \p m metadata decoded from
1362 * the compressed representation.
1365 mono_metadata_parse_typedef_or_ref (MonoImage *m, const char *ptr, const char **rptr)
1368 token = mono_metadata_decode_value (ptr, &ptr);
1371 return mono_metadata_token_from_dor (token);
1375 * mono_metadata_parse_custom_mod:
1376 * \param m a metadata context.
1377 * \param dest storage where the info about the custom modifier is stored (may be NULL)
1378 * \param ptr a pointer to (possibly) the start of a custom modifier list
1379 * \param rptr pointer updated to match the end of the decoded stream
1381 * Checks if \p ptr points to a type custom modifier compressed representation.
1383 * \returns TRUE if a custom modifier was found, FALSE if not.
1386 mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
1388 MonoCustomMod local;
1389 if ((*ptr == MONO_TYPE_CMOD_OPT) || (*ptr == MONO_TYPE_CMOD_REQD)) {
1392 dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
1393 dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, rptr);
1400 * mono_metadata_parse_array_internal:
1401 * @m: a metadata context.
1402 * @transient: whenever to allocate data from the heap
1403 * @ptr: a pointer to an encoded array description.
1404 * @rptr: pointer updated to match the end of the decoded stream
1406 * Decodes the compressed array description found in the metadata @m at @ptr.
1408 * Returns: a #MonoArrayType structure describing the array type
1409 * and dimensions. Memory is allocated from the heap or from the image mempool, depending
1410 * on the value of @transient.
1412 * LOCKING: Acquires the loader lock
1414 static MonoArrayType *
1415 mono_metadata_parse_array_internal (MonoImage *m, MonoGenericContainer *container,
1416 gboolean transient, const char *ptr, const char **rptr, MonoError *error)
1419 MonoArrayType *array;
1422 etype = mono_metadata_parse_type_checked (m, container, 0, FALSE, ptr, &ptr, error); //FIXME this doesn't respect @transient
1426 array = transient ? (MonoArrayType *)g_malloc0 (sizeof (MonoArrayType)) : (MonoArrayType *)mono_image_alloc0 (m, sizeof (MonoArrayType));
1427 array->eklass = mono_class_from_mono_type (etype);
1428 array->rank = mono_metadata_decode_value (ptr, &ptr);
1430 array->numsizes = mono_metadata_decode_value (ptr, &ptr);
1431 if (array->numsizes)
1432 array->sizes = transient ? (int *)g_malloc0 (sizeof (int) * array->numsizes) : (int *)mono_image_alloc0 (m, sizeof (int) * array->numsizes);
1433 for (i = 0; i < array->numsizes; ++i)
1434 array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
1436 array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
1437 if (array->numlobounds)
1438 array->lobounds = transient ? (int *)g_malloc0 (sizeof (int) * array->numlobounds) : (int *)mono_image_alloc0 (m, sizeof (int) * array->numlobounds);
1439 for (i = 0; i < array->numlobounds; ++i)
1440 array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr);
1448 * mono_metadata_parse_array:
1451 mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
1454 MonoArrayType *ret = mono_metadata_parse_array_internal (m, NULL, FALSE, ptr, rptr, &error);
1455 mono_error_cleanup (&error);
1461 * mono_metadata_free_array:
1462 * \param array array description
1464 * Frees the array description returned from \c mono_metadata_parse_array.
1467 mono_metadata_free_array (MonoArrayType *array)
1469 g_free (array->sizes);
1470 g_free (array->lobounds);
1475 * need to add common field and param attributes combinations:
1478 * public static literal
1481 * private static literal
1483 static const MonoType
1485 /* data, attrs, type, nmods, byref, pinned */
1486 {{NULL}, 0, MONO_TYPE_VOID, 0, 0, 0},
1487 {{NULL}, 0, MONO_TYPE_BOOLEAN, 0, 0, 0},
1488 {{NULL}, 0, MONO_TYPE_BOOLEAN, 0, 1, 0},
1489 {{NULL}, 0, MONO_TYPE_CHAR, 0, 0, 0},
1490 {{NULL}, 0, MONO_TYPE_CHAR, 0, 1, 0},
1491 {{NULL}, 0, MONO_TYPE_I1, 0, 0, 0},
1492 {{NULL}, 0, MONO_TYPE_I1, 0, 1, 0},
1493 {{NULL}, 0, MONO_TYPE_U1, 0, 0, 0},
1494 {{NULL}, 0, MONO_TYPE_U1, 0, 1, 0},
1495 {{NULL}, 0, MONO_TYPE_I2, 0, 0, 0},
1496 {{NULL}, 0, MONO_TYPE_I2, 0, 1, 0},
1497 {{NULL}, 0, MONO_TYPE_U2, 0, 0, 0},
1498 {{NULL}, 0, MONO_TYPE_U2, 0, 1, 0},
1499 {{NULL}, 0, MONO_TYPE_I4, 0, 0, 0},
1500 {{NULL}, 0, MONO_TYPE_I4, 0, 1, 0},
1501 {{NULL}, 0, MONO_TYPE_U4, 0, 0, 0},
1502 {{NULL}, 0, MONO_TYPE_U4, 0, 1, 0},
1503 {{NULL}, 0, MONO_TYPE_I8, 0, 0, 0},
1504 {{NULL}, 0, MONO_TYPE_I8, 0, 1, 0},
1505 {{NULL}, 0, MONO_TYPE_U8, 0, 0, 0},
1506 {{NULL}, 0, MONO_TYPE_U8, 0, 1, 0},
1507 {{NULL}, 0, MONO_TYPE_R4, 0, 0, 0},
1508 {{NULL}, 0, MONO_TYPE_R4, 0, 1, 0},
1509 {{NULL}, 0, MONO_TYPE_R8, 0, 0, 0},
1510 {{NULL}, 0, MONO_TYPE_R8, 0, 1, 0},
1511 {{NULL}, 0, MONO_TYPE_STRING, 0, 0, 0},
1512 {{NULL}, 0, MONO_TYPE_STRING, 0, 1, 0},
1513 {{NULL}, 0, MONO_TYPE_OBJECT, 0, 0, 0},
1514 {{NULL}, 0, MONO_TYPE_OBJECT, 0, 1, 0},
1515 {{NULL}, 0, MONO_TYPE_TYPEDBYREF, 0, 0, 0},
1516 {{NULL}, 0, MONO_TYPE_I, 0, 0, 0},
1517 {{NULL}, 0, MONO_TYPE_I, 0, 1, 0},
1518 {{NULL}, 0, MONO_TYPE_U, 0, 0, 0},
1519 {{NULL}, 0, MONO_TYPE_U, 0, 1, 0},
1522 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1524 static GHashTable *type_cache = NULL;
1525 static gint32 next_generic_inst_id = 0;
1527 /* Protected by image_sets_mutex */
1528 static MonoImageSet *mscorlib_image_set;
1529 /* Protected by image_sets_mutex */
1530 static GPtrArray *image_sets;
1531 static mono_mutex_t image_sets_mutex;
1533 static guint mono_generic_class_hash (gconstpointer data);
1536 * MonoTypes with modifies are never cached, so we never check or use that field.
1539 mono_type_hash (gconstpointer data)
1541 const MonoType *type = (const MonoType *) data;
1542 if (type->type == MONO_TYPE_GENERICINST)
1543 return mono_generic_class_hash (type->data.generic_class);
1545 return type->type | (type->byref << 8) | (type->attrs << 9);
1549 mono_type_equal (gconstpointer ka, gconstpointer kb)
1551 const MonoType *a = (const MonoType *) ka;
1552 const MonoType *b = (const MonoType *) kb;
1554 if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
1556 /* need other checks */
1561 mono_metadata_generic_inst_hash (gconstpointer data)
1563 const MonoGenericInst *ginst = (const MonoGenericInst *) data;
1567 for (i = 0; i < ginst->type_argc; ++i) {
1569 hash += mono_metadata_type_hash (ginst->type_argv [i]);
1572 return hash ^ (ginst->is_open << 8);
1576 mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b, gboolean signature_only)
1580 // An optimization: if the ids of two insts are the same, we know they are the same inst and don't check contents.
1581 // Furthermore, because we perform early de-duping, if the ids differ, we know the contents differ.
1582 #ifndef MONO_SMALL_CONFIG // Optimization does not work in MONO_SMALL_CONFIG: There are no IDs
1583 if (a->id && b->id) { // "id 0" means "object has no id"-- de-duping hasn't been performed yet, must check contents.
1586 // In signature-comparison mode id equality implies object equality, but this is not true for inequality.
1587 // Two separate objects could have signature-equavalent contents.
1588 if (!signature_only)
1593 if (a->is_open != b->is_open || a->type_argc != b->type_argc)
1595 for (i = 0; i < a->type_argc; ++i) {
1596 if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], signature_only))
1603 mono_metadata_generic_inst_equal (gconstpointer ka, gconstpointer kb)
1605 const MonoGenericInst *a = (const MonoGenericInst *) ka;
1606 const MonoGenericInst *b = (const MonoGenericInst *) kb;
1608 return mono_generic_inst_equal_full (a, b, FALSE);
1612 mono_generic_class_hash (gconstpointer data)
1614 const MonoGenericClass *gclass = (const MonoGenericClass *) data;
1615 guint hash = mono_metadata_type_hash (&gclass->container_class->byval_arg);
1618 hash += gclass->is_tb_open;
1619 hash += mono_metadata_generic_context_hash (&gclass->context);
1625 mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
1627 const MonoGenericClass *a = (const MonoGenericClass *) ka;
1628 const MonoGenericClass *b = (const MonoGenericClass *) kb;
1630 return _mono_metadata_generic_class_equal (a, b, FALSE);
1634 * mono_metadata_init:
1636 * Initialize the global variables of this module.
1637 * This is a Mono runtime internal function.
1640 mono_metadata_init (void)
1644 /* We guard against double initialization due to how pedump in verification mode works.
1645 Until runtime initialization is properly factored to work with what it needs we need workarounds like this.
1646 FIXME: https://bugzilla.xamarin.com/show_bug.cgi?id=58793
1648 static gboolean inited;
1654 type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
1656 for (i = 0; i < NBUILTIN_TYPES (); ++i)
1657 g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
1659 mono_os_mutex_init_recursive (&image_sets_mutex);
1661 mono_counters_register ("ImgSet Cache Hit", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_cache_hit);
1662 mono_counters_register ("ImgSet Cache Miss", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_cache_miss);
1663 mono_counters_register ("ImgSet Count", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_count);
1667 * mono_metadata_cleanup:
1669 * Free all resources used by this module.
1670 * This is a Mono runtime internal function.
1673 mono_metadata_cleanup (void)
1675 g_hash_table_destroy (type_cache);
1677 g_ptr_array_free (image_sets, TRUE);
1679 mono_os_mutex_destroy (&image_sets_mutex);
1683 * mono_metadata_parse_type:
1684 * \param m metadata context
1685 * \param mode kind of type that may be found at \p ptr
1686 * \param opt_attrs optional attributes to store in the returned type
1687 * \param ptr pointer to the type representation
1688 * \param rptr pointer updated to match the end of the decoded stream
1689 * \param transient whenever to allocate the result from the heap or from a mempool
1691 * Decode a compressed type description found at \p ptr in \p m .
1692 * \p mode can be one of \c MONO_PARSE_MOD_TYPE, \c MONO_PARSE_PARAM, \c MONO_PARSE_RET,
1693 * \c MONO_PARSE_FIELD, \c MONO_PARSE_LOCAL, \c MONO_PARSE_TYPE.
1694 * This function can be used to decode type descriptions in method signatures,
1695 * field signatures, locals signatures etc.
1697 * To parse a generic type, \c generic_container points to the current class'es
1698 * (the \c generic_container field in the <code>MonoClass</code>) or the current generic method's
1699 * (stored in <code>image->property_hash</code>) generic container.
1700 * When we encounter a \c MONO_TYPE_VAR or \c MONO_TYPE_MVAR, it's looked up in
1701 * this \c MonoGenericContainer.
1703 * LOCKING: Acquires the loader lock.
1705 * \returns a \c MonoType structure representing the decoded type.
1708 mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container,
1709 short opt_attrs, gboolean transient, const char *ptr, const char **rptr, MonoError *error)
1711 MonoType *type, *cached;
1713 gboolean byref = FALSE;
1714 gboolean pinned = FALSE;
1715 const char *tmp_ptr;
1716 int count = 0; // Number of mod arguments
1722 * According to the spec, custom modifiers should come before the byref
1723 * flag, but the IL produced by ilasm from the following signature:
1724 * object modopt(...) &
1725 * starts with a byref flag, followed by the modifiers. (bug #49802)
1726 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1727 * it would be better to treat byref as real type constructor instead of
1729 * Also, pinned should come before anything else, but some MSV++ produced
1730 * assemblies violate this (#bug 61990).
1733 /* Count the modifiers first */
1738 case MONO_TYPE_PINNED:
1739 case MONO_TYPE_BYREF:
1742 case MONO_TYPE_CMOD_REQD:
1743 case MONO_TYPE_CMOD_OPT:
1745 mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
1752 if (count) { // There are mods, so the MonoType will be of nonstandard size.
1755 size = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
1756 type = transient ? (MonoType *)g_malloc0 (size) : (MonoType *)mono_image_alloc0 (m, size);
1757 type->num_mods = count;
1759 mono_error_set_bad_image (error, m, "Invalid type with more than 64 modifiers");
1762 } else { // The type is of standard size, so we can allocate it on the stack.
1764 memset (type, 0, MONO_SIZEOF_TYPE);
1767 /* Iterate again, but now parse pinned, byref and custom modifiers */
1772 case MONO_TYPE_PINNED:
1776 case MONO_TYPE_BYREF:
1780 case MONO_TYPE_CMOD_REQD:
1781 case MONO_TYPE_CMOD_OPT:
1782 mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
1790 type->attrs = opt_attrs;
1791 type->byref = byref;
1792 type->pinned = pinned ? 1 : 0;
1794 if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr, error))
1800 // Possibly we can return an already-allocated type instead of the one we decoded
1801 if (!type->num_mods && !transient) {
1802 /* no need to free type here, because it is on the stack */
1803 if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
1804 MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
1806 /* Consider the case:
1808 class Foo<T> { class Bar {} }
1809 class Test : Foo<Test>.Bar {}
1811 When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
1812 a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1814 We ensure that the MonoClass is in a state that we can canonicalize to:
1816 klass->byval_arg.data.klass == klass
1817 klass->this_arg.data.klass == klass
1819 If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1821 LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1822 of a MonoClass which currently holds the loader lock. 'type' is local.
1824 if (ret->data.klass == type->data.klass) {
1828 /* No need to use locking since nobody is modifying the hash table */
1829 if ((cached = (MonoType *)g_hash_table_lookup (type_cache, type))) {
1834 /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1836 if (type == &stype) { // Type was allocated on the stack, so we need to copy it to safety
1837 type = transient ? (MonoType *)g_malloc (MONO_SIZEOF_TYPE) : (MonoType *)mono_image_alloc (m, MONO_SIZEOF_TYPE);
1838 memcpy (type, &stype, MONO_SIZEOF_TYPE);
1845 mono_metadata_parse_type_checked (MonoImage *m, MonoGenericContainer *container,
1846 short opt_attrs, gboolean transient, const char *ptr, const char **rptr, MonoError *error)
1848 return mono_metadata_parse_type_internal (m, container, opt_attrs, transient, ptr, rptr, error);
1852 * LOCKING: Acquires the loader lock.
1855 mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
1856 const char *ptr, const char **rptr)
1859 MonoType * type = mono_metadata_parse_type_internal (m, NULL, opt_attrs, FALSE, ptr, rptr, &error);
1860 mono_error_cleanup (&error);
1865 mono_metadata_method_has_param_attrs (MonoImage *m, int def)
1867 MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1868 MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1869 guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1871 if (def < methodt->rows)
1872 lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1874 lastp = m->tables [MONO_TABLE_PARAM].rows + 1;
1876 for (i = param_index; i < lastp; ++i) {
1877 guint32 flags = mono_metadata_decode_row_col (paramt, i - 1, MONO_PARAM_FLAGS);
1886 * mono_metadata_get_param_attrs:
1888 * @m The image to loader parameter attributes from
1889 * @def method def token (one based)
1890 * @param_count number of params to decode including the return value
1892 * Return the parameter attributes for the method whose MethodDef index is DEF. The
1893 * returned memory needs to be freed by the caller. If all the param attributes are
1894 * 0, then NULL is returned.
1897 mono_metadata_get_param_attrs (MonoImage *m, int def, int param_count)
1899 MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1900 MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1901 guint32 cols [MONO_PARAM_SIZE];
1902 guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1905 if (def < methodt->rows)
1906 lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1908 lastp = paramt->rows + 1;
1910 for (i = param_index; i < lastp; ++i) {
1911 mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
1912 if (cols [MONO_PARAM_FLAGS]) {
1914 pattrs = g_new0 (int, param_count);
1915 /* at runtime we just ignore this kind of malformed file:
1916 * the verifier can signal the error to the user
1918 if (cols [MONO_PARAM_SEQUENCE] >= param_count)
1920 pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
1929 * mono_metadata_parse_signature:
1930 * \param image metadata context
1931 * \param token metadata token
1933 * Decode a method signature stored in the \c StandAloneSig table
1935 * \returns a \c MonoMethodSignature describing the signature.
1937 MonoMethodSignature*
1938 mono_metadata_parse_signature (MonoImage *image, guint32 token)
1941 MonoMethodSignature *ret;
1942 ret = mono_metadata_parse_signature_checked (image, token, &error);
1943 mono_error_cleanup (&error);
1948 * mono_metadata_parse_signature_checked:
1949 * @image: metadata context
1950 * @token: metadata token
1951 * @error: set on error
1953 * Decode a method signature stored in the STANDALONESIG table
1955 * Returns: a MonoMethodSignature describing the signature. On failure
1956 * returns NULL and sets @error.
1958 MonoMethodSignature*
1959 mono_metadata_parse_signature_checked (MonoImage *image, guint32 token, MonoError *error)
1963 MonoTableInfo *tables = image->tables;
1964 guint32 idx = mono_metadata_token_index (token);
1968 if (image_is_dynamic (image)) {
1969 return (MonoMethodSignature *)mono_lookup_dynamic_token (image, token, NULL, error);
1972 g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
1974 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
1976 ptr = mono_metadata_blob_heap (image, sig);
1977 mono_metadata_decode_blob_size (ptr, &ptr);
1979 return mono_metadata_parse_method_signature_full (image, NULL, 0, ptr, NULL, error);
1983 * mono_metadata_signature_alloc:
1984 * \param image metadata context
1985 * \param nparams number of parameters in the signature
1987 * Allocate a \c MonoMethodSignature structure with the specified number of params.
1988 * The return type and the params types need to be filled later.
1989 * This is a Mono runtime internal function.
1991 * LOCKING: Assumes the loader lock is held.
1993 * \returns the new \c MonoMethodSignature structure.
1995 MonoMethodSignature*
1996 mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
1998 MonoMethodSignature *sig;
2000 sig = (MonoMethodSignature *)mono_image_alloc0 (m, MONO_SIZEOF_METHOD_SIGNATURE + ((gint32)nparams) * sizeof (MonoType*));
2001 sig->param_count = nparams;
2002 sig->sentinelpos = -1;
2007 static MonoMethodSignature*
2008 mono_metadata_signature_dup_internal_with_padding (MonoImage *image, MonoMemPool *mp, MonoMethodSignature *sig, size_t padding)
2010 int sigsize, sig_header_size;
2011 MonoMethodSignature *ret;
2012 sigsize = sig_header_size = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *) + padding;
2014 sigsize += MONO_SIZEOF_TYPE;
2017 ret = (MonoMethodSignature *)mono_image_alloc (image, sigsize);
2019 ret = (MonoMethodSignature *)mono_mempool_alloc (mp, sigsize);
2021 ret = (MonoMethodSignature *)g_malloc (sigsize);
2024 memcpy (ret, sig, sig_header_size - padding);
2026 // Copy return value because of ownership semantics.
2028 // Danger! Do not alter padding use without changing the dup_add_this below
2029 intptr_t end_of_header = (intptr_t)( (char*)(ret) + sig_header_size);
2030 ret->ret = (MonoType *)end_of_header;
2031 memcpy (ret->ret, sig->ret, MONO_SIZEOF_TYPE);
2037 static MonoMethodSignature*
2038 mono_metadata_signature_dup_internal (MonoImage *image, MonoMemPool *mp, MonoMethodSignature *sig)
2040 return mono_metadata_signature_dup_internal_with_padding (image, mp, sig, 0);
2043 * signature_dup_add_this:
2045 * Make a copy of @sig, adding an explicit this argument.
2047 MonoMethodSignature*
2048 mono_metadata_signature_dup_add_this (MonoImage *image, MonoMethodSignature *sig, MonoClass *klass)
2050 MonoMethodSignature *ret;
2051 ret = mono_metadata_signature_dup_internal_with_padding (image, NULL, sig, sizeof (MonoType *));
2053 ret->param_count = sig->param_count + 1;
2054 ret->hasthis = FALSE;
2056 for (int i = sig->param_count - 1; i >= 0; i --)
2057 ret->params [i + 1] = sig->params [i];
2058 ret->params [0] = klass->valuetype ? &klass->this_arg : &klass->byval_arg;
2060 for (int i = sig->param_count - 1; i >= 0; i --)
2061 g_assert(ret->params [i + 1]->type == sig->params [i]->type && ret->params [i+1]->type != MONO_TYPE_END);
2062 g_assert (ret->ret->type == sig->ret->type && ret->ret->type != MONO_TYPE_END);
2069 MonoMethodSignature*
2070 mono_metadata_signature_dup_full (MonoImage *image, MonoMethodSignature *sig)
2072 MonoMethodSignature *ret = mono_metadata_signature_dup_internal (image, NULL, sig);
2074 for (int i = 0 ; i < sig->param_count; i ++)
2075 g_assert(ret->params [i]->type == sig->params [i]->type);
2076 g_assert (ret->ret->type == sig->ret->type);
2081 /*The mempool is accessed without synchronization*/
2082 MonoMethodSignature*
2083 mono_metadata_signature_dup_mempool (MonoMemPool *mp, MonoMethodSignature *sig)
2085 return mono_metadata_signature_dup_internal (NULL, mp, sig);
2089 * mono_metadata_signature_dup:
2090 * \param sig method signature
2092 * Duplicate an existing \c MonoMethodSignature so it can be modified.
2093 * This is a Mono runtime internal function.
2095 * \returns the new \c MonoMethodSignature structure.
2097 MonoMethodSignature*
2098 mono_metadata_signature_dup (MonoMethodSignature *sig)
2100 return mono_metadata_signature_dup_full (NULL, sig);
2104 * mono_metadata_signature_size:
2106 * Return the amount of memory allocated to SIG.
2109 mono_metadata_signature_size (MonoMethodSignature *sig)
2111 return MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
2115 * mono_metadata_parse_method_signature:
2116 * @m: metadata context
2117 * @generic_container: generics container
2118 * @def: the MethodDef index or 0 for Ref signatures.
2119 * @ptr: pointer to the signature metadata representation
2120 * @rptr: pointer updated to match the end of the decoded stream
2122 * Decode a method signature stored at @ptr.
2123 * This is a Mono runtime internal function.
2125 * LOCKING: Assumes the loader lock is held.
2127 * Returns: a MonoMethodSignature describing the signature.
2129 MonoMethodSignature *
2130 mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container,
2131 int def, const char *ptr, const char **rptr, MonoError *error)
2133 MonoMethodSignature *method;
2134 int i, *pattrs = NULL;
2135 guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
2136 guint32 gen_param_count = 0;
2137 gboolean is_open = FALSE;
2142 gen_param_count = 1;
2147 call_convention = *ptr & 0x0F;
2149 if (gen_param_count)
2150 gen_param_count = mono_metadata_decode_value (ptr, &ptr);
2151 param_count = mono_metadata_decode_value (ptr, &ptr);
2154 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 */
2156 method = mono_metadata_signature_alloc (m, param_count);
2157 method->hasthis = hasthis;
2158 method->explicit_this = explicit_this;
2159 method->call_convention = call_convention;
2160 method->generic_param_count = gen_param_count;
2162 if (call_convention != 0xa) {
2163 method->ret = mono_metadata_parse_type_checked (m, container, pattrs ? pattrs [0] : 0, FALSE, ptr, &ptr, error);
2165 mono_metadata_free_method_signature (method);
2169 is_open = mono_class_is_open_constructed_type (method->ret);
2172 for (i = 0; i < method->param_count; ++i) {
2173 if (*ptr == MONO_TYPE_SENTINEL) {
2174 if (method->call_convention != MONO_CALL_VARARG || def) {
2175 mono_error_set_bad_image (error, m, "Found sentinel for methoddef or no vararg");
2179 if (method->sentinelpos >= 0) {
2180 mono_error_set_bad_image (error, m, "Found sentinel twice in the same signature.");
2184 method->sentinelpos = i;
2187 method->params [i] = mono_metadata_parse_type_checked (m, container, pattrs ? pattrs [i+1] : 0, FALSE, ptr, &ptr, error);
2188 if (!method->params [i]) {
2189 mono_metadata_free_method_signature (method);
2194 is_open = mono_class_is_open_constructed_type (method->params [i]);
2197 /* The sentinel could be missing if the caller does not pass any additional arguments */
2198 if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0)
2199 method->sentinelpos = method->param_count;
2201 method->has_type_parameters = is_open;
2203 if (def && (method->call_convention == MONO_CALL_VARARG))
2204 method->sentinelpos = method->param_count;
2211 * Add signature to a cache and increase ref count...
2218 * mono_metadata_parse_method_signature:
2219 * \param m metadata context
2220 * \param def the \c MethodDef index or 0 for \c Ref signatures.
2221 * \param ptr pointer to the signature metadata representation
2222 * \param rptr pointer updated to match the end of the decoded stream
2224 * Decode a method signature stored at \p ptr.
2225 * This is a Mono runtime internal function.
2227 * LOCKING: Assumes the loader lock is held.
2229 * \returns a \c MonoMethodSignature describing the signature.
2231 MonoMethodSignature *
2232 mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
2235 * This function MUST NOT be called by runtime code as it does error handling incorrectly.
2236 * Use mono_metadata_parse_method_signature_full instead.
2237 * It's ok to asser on failure as we no longer use it.
2240 MonoMethodSignature *ret;
2241 ret = mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr, &error);
2242 g_assert (mono_error_ok (&error));
2248 * mono_metadata_free_method_signature:
2249 * \param sig signature to destroy
2251 * Free the memory allocated in the signature \p sig.
2252 * This method needs to be robust and work also on partially-built
2253 * signatures, so it does extra checks.
2256 mono_metadata_free_method_signature (MonoMethodSignature *sig)
2258 /* Everything is allocated from mempools */
2262 mono_metadata_free_type (sig->ret);
2263 for (i = 0; i < sig->param_count; ++i) {
2264 if (sig->params [i])
2265 mono_metadata_free_type (sig->params [i]);
2271 mono_metadata_free_inflated_signature (MonoMethodSignature *sig)
2275 /* Allocated in inflate_generic_signature () */
2277 mono_metadata_free_type (sig->ret);
2278 for (i = 0; i < sig->param_count; ++i) {
2279 if (sig->params [i])
2280 mono_metadata_free_type (sig->params [i]);
2286 inflated_method_equal (gconstpointer a, gconstpointer b)
2288 const MonoMethodInflated *ma = (const MonoMethodInflated *)a;
2289 const MonoMethodInflated *mb = (const MonoMethodInflated *)b;
2290 if (ma->declaring != mb->declaring)
2292 return mono_metadata_generic_context_equal (&ma->context, &mb->context);
2296 inflated_method_hash (gconstpointer a)
2298 const MonoMethodInflated *ma = (const MonoMethodInflated *)a;
2299 return (mono_metadata_generic_context_hash (&ma->context) ^ mono_aligned_addr_hash (ma->declaring));
2303 inflated_signature_equal (gconstpointer a, gconstpointer b)
2305 const MonoInflatedMethodSignature *sig1 = (const MonoInflatedMethodSignature *)a;
2306 const MonoInflatedMethodSignature *sig2 = (const MonoInflatedMethodSignature *)b;
2308 /* sig->sig is assumed to be canonized */
2309 if (sig1->sig != sig2->sig)
2311 /* The generic instances are canonized */
2312 return mono_metadata_generic_context_equal (&sig1->context, &sig2->context);
2316 inflated_signature_hash (gconstpointer a)
2318 const MonoInflatedMethodSignature *sig = (const MonoInflatedMethodSignature *)a;
2320 /* sig->sig is assumed to be canonized */
2321 return mono_metadata_generic_context_hash (&sig->context) ^ mono_aligned_addr_hash (sig->sig);
2325 dump_ginst (MonoGenericInst *ginst)
2330 g_print ("Ginst: <");
2331 for (i = 0; i < ginst->type_argc; ++i) {
2334 name = mono_type_get_name (ginst->type_argv [i]);
2335 g_print ("%s", name);
2341 static gboolean type_in_image (MonoType *type, MonoImage *image);
2344 signature_in_image (MonoMethodSignature *sig, MonoImage *image)
2346 gpointer iter = NULL;
2349 while ((p = mono_signature_get_params (sig, &iter)) != NULL)
2350 if (type_in_image (p, image))
2353 return type_in_image (mono_signature_get_return_type (sig), image);
2357 ginst_in_image (MonoGenericInst *ginst, MonoImage *image)
2361 for (i = 0; i < ginst->type_argc; ++i) {
2362 if (type_in_image (ginst->type_argv [i], image))
2370 gclass_in_image (MonoGenericClass *gclass, MonoImage *image)
2372 return gclass->container_class->image == image ||
2373 ginst_in_image (gclass->context.class_inst, image);
2377 type_in_image (MonoType *type, MonoImage *image)
2380 switch (type->type) {
2381 case MONO_TYPE_GENERICINST:
2382 return gclass_in_image (type->data.generic_class, image);
2384 type = type->data.type;
2386 case MONO_TYPE_SZARRAY:
2387 type = &type->data.klass->byval_arg;
2389 case MONO_TYPE_ARRAY:
2390 type = &type->data.array->eklass->byval_arg;
2392 case MONO_TYPE_FNPTR:
2393 return signature_in_image (type->data.method, image);
2395 case MONO_TYPE_MVAR:
2396 return image == get_image_for_generic_param (type->data.generic_param);
2398 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2399 return image == mono_class_from_mono_type (type)->image;
2404 image_sets_lock (void)
2406 mono_os_mutex_lock (&image_sets_mutex);
2410 image_sets_unlock (void)
2412 mono_os_mutex_unlock (&image_sets_mutex);
2416 compare_pointers (const void *a, const void *b)
2418 return (size_t)a - (size_t)b;
2422 #define HASH_TABLE_SIZE 1103
2423 static MonoImageSet *img_set_cache [HASH_TABLE_SIZE];
2426 mix_hash (uintptr_t source)
2428 unsigned int hash = source;
2431 hash = (((hash * 215497) >> 16) ^ ((hash * 1823231) + hash));
2433 // Mix in highest bits on 64-bit systems only
2434 if (sizeof (source) > 4)
2435 hash = hash ^ (source >> 32);
2441 hash_images (MonoImage **images, int nimages)
2445 for (i = 0; i < nimages; ++i)
2446 res += mix_hash ((size_t)images [i]);
2452 compare_img_set (MonoImageSet *set, MonoImage **images, int nimages)
2456 if (set->nimages != nimages)
2459 for (j = 0; j < nimages; ++j) {
2460 for (k = 0; k < nimages; ++k)
2461 if (set->images [k] == images [j])
2462 break; // Break on match
2464 // If we iterated all the way through set->images, images[j] was *not* found.
2466 break; // Break on "image not found"
2469 // If we iterated all the way through images without breaking, all items in images were found in set->images
2470 return j == nimages;
2474 static MonoImageSet*
2475 img_set_cache_get (MonoImage **images, int nimages)
2477 guint32 hash_code = hash_images (images, nimages);
2478 int index = hash_code % HASH_TABLE_SIZE;
2479 MonoImageSet *img = img_set_cache [index];
2480 if (!img || !compare_img_set (img, images, nimages)) {
2481 ++img_set_cache_miss;
2484 ++img_set_cache_hit;
2489 img_set_cache_add (MonoImageSet *set)
2491 guint32 hash_code = hash_images (set->images, set->nimages);
2492 int index = hash_code % HASH_TABLE_SIZE;
2493 img_set_cache [index] = set;
2497 img_set_cache_remove (MonoImageSet *is)
2499 guint32 hash_code = hash_images (is->images, is->nimages);
2500 int index = hash_code % HASH_TABLE_SIZE;
2501 if (img_set_cache [index] == is)
2502 img_set_cache [index] = NULL;
2507 * Return a MonoImageSet representing the set of images in IMAGES.
2509 static MonoImageSet*
2510 get_image_set (MonoImage **images, int nimages)
2516 /* Common case: Image set contains corlib only. If we've seen that case before, we cached the set. */
2517 if (nimages == 1 && images [0] == mono_defaults.corlib && mscorlib_image_set)
2518 return mscorlib_image_set;
2520 /* Happens with empty generic instances */
2521 // 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.
2523 return mscorlib_image_set;
2525 set = img_set_cache_get (images, nimages);
2532 image_sets = g_ptr_array_new ();
2534 // Before we go on, we should check to see whether a MonoImageSet with these images already exists.
2535 // We can search the referred-by imagesets of any one of our images to do this. Arbitrarily pick one here:
2536 if (images [0] == mono_defaults.corlib && nimages > 1)
2537 l = images [1]->image_sets; // Prefer not to search the imagesets of corlib-- that will be a long list.
2539 l = images [0]->image_sets;
2542 while (l) // Iterate over selected list, looking for an imageset with members equal to our target one
2544 set = (MonoImageSet *)l->data;
2546 if (set->nimages == nimages) { // Member count differs, this can't be it
2547 // Compare all members to all members-- order might be different
2548 for (j = 0; j < nimages; ++j) {
2549 for (k = 0; k < nimages; ++k)
2550 if (set->images [k] == images [j])
2551 break; // Break on match
2553 // If we iterated all the way through set->images, images[j] was *not* found.
2555 break; // Break on "image not found"
2558 // If we iterated all the way through images without breaking, all items in images were found in set->images
2560 // Break on "found a set with equal members".
2561 // This happens in case of a hash collision with a previously cached set.
2569 // If we iterated all the way through l without breaking, the imageset does not already exist and we shuold create it
2571 set = g_new0 (MonoImageSet, 1);
2572 set->nimages = nimages;
2573 set->images = g_new0 (MonoImage*, nimages);
2574 mono_os_mutex_init_recursive (&set->lock);
2575 for (i = 0; i < nimages; ++i)
2576 set->images [i] = images [i];
2577 set->gclass_cache = mono_conc_hashtable_new_full (mono_generic_class_hash, mono_generic_class_equal, NULL, (GDestroyNotify)free_generic_class);
2578 set->ginst_cache = g_hash_table_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst);
2579 set->gmethod_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method);
2580 set->gsignature_cache = g_hash_table_new_full (inflated_signature_hash, inflated_signature_equal, NULL, (GDestroyNotify)free_inflated_signature);
2582 for (i = 0; i < nimages; ++i)
2583 set->images [i]->image_sets = g_slist_prepend (set->images [i]->image_sets, set);
2585 g_ptr_array_add (image_sets, set);
2589 /* Cache the set. If there was a cache collision, the previously cached value will be replaced. */
2590 img_set_cache_add (set);
2592 if (nimages == 1 && images [0] == mono_defaults.corlib) {
2593 mono_memory_barrier ();
2594 mscorlib_image_set = set;
2597 image_sets_unlock ();
2603 delete_image_set (MonoImageSet *set)
2607 mono_conc_hashtable_destroy (set->gclass_cache);
2608 g_hash_table_destroy (set->ginst_cache);
2609 g_hash_table_destroy (set->gmethod_cache);
2610 g_hash_table_destroy (set->gsignature_cache);
2612 mono_wrapper_caches_free (&set->wrapper_caches);
2616 for (i = 0; i < set->nimages; ++i)
2617 set->images [i]->image_sets = g_slist_remove (set->images [i]->image_sets, set);
2619 g_ptr_array_remove (image_sets, set);
2621 image_sets_unlock ();
2623 img_set_cache_remove (set);
2626 mono_mempool_destroy (set->mempool);
2627 g_free (set->images);
2628 mono_os_mutex_destroy (&set->lock);
2633 mono_image_set_lock (MonoImageSet *set)
2635 mono_os_mutex_lock (&set->lock);
2639 mono_image_set_unlock (MonoImageSet *set)
2641 mono_os_mutex_unlock (&set->lock);
2645 mono_image_set_alloc (MonoImageSet *set, guint size)
2649 mono_image_set_lock (set);
2651 set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE);
2652 res = mono_mempool_alloc (set->mempool, size);
2653 mono_image_set_unlock (set);
2659 mono_image_set_alloc0 (MonoImageSet *set, guint size)
2663 mono_image_set_lock (set);
2665 set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE);
2666 res = mono_mempool_alloc0 (set->mempool, size);
2667 mono_image_set_unlock (set);
2673 mono_image_set_strdup (MonoImageSet *set, const char *s)
2677 mono_image_set_lock (set);
2679 set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE);
2680 res = mono_mempool_strdup (set->mempool, s);
2681 mono_image_set_unlock (set);
2686 // Get a descriptive string for a MonoImageSet
2687 // Callers are obligated to free buffer with g_free after use
2689 mono_image_set_description (MonoImageSet *set)
2691 GString *result = g_string_new (NULL);
2693 g_string_append (result, "[");
2694 for (img = 0; img < set->nimages; img++)
2697 g_string_append (result, ", ");
2698 g_string_append (result, set->images[img]->name);
2700 g_string_append (result, "]");
2701 return g_string_free (result, FALSE);
2705 * Structure used by the collect_..._images functions to store the image list.
2708 MonoImage *image_buf [64];
2710 int nimages, images_len;
2714 collect_data_init (CollectData *data)
2716 data->images = data->image_buf;
2717 data->images_len = 64;
2722 collect_data_free (CollectData *data)
2724 if (data->images != data->image_buf)
2725 g_free (data->images);
2729 enlarge_data (CollectData *data)
2731 int new_len = data->images_len < 16 ? 16 : data->images_len * 2;
2732 MonoImage **d = g_new (MonoImage *, new_len);
2735 g_assert_not_reached ();
2736 memcpy (d, data->images, data->images_len);
2737 if (data->images != data->image_buf)
2738 g_free (data->images);
2740 data->images_len = new_len;
2744 add_image (MonoImage *image, CollectData *data)
2748 /* The arrays are small, so use a linear search instead of a hash table */
2749 for (i = 0; i < data->nimages; ++i)
2750 if (data->images [i] == image)
2753 if (data->nimages == data->images_len)
2754 enlarge_data (data);
2756 data->images [data->nimages ++] = image;
2760 collect_type_images (MonoType *type, CollectData *data);
2763 collect_ginst_images (MonoGenericInst *ginst, CollectData *data)
2767 for (i = 0; i < ginst->type_argc; ++i) {
2768 collect_type_images (ginst->type_argv [i], data);
2773 collect_gclass_images (MonoGenericClass *gclass, CollectData *data)
2775 add_image (gclass->container_class->image, data);
2776 if (gclass->context.class_inst)
2777 collect_ginst_images (gclass->context.class_inst, data);
2781 collect_signature_images (MonoMethodSignature *sig, CollectData *data)
2783 gpointer iter = NULL;
2786 collect_type_images (mono_signature_get_return_type (sig), data);
2787 while ((p = mono_signature_get_params (sig, &iter)) != NULL)
2788 collect_type_images (p, data);
2792 collect_inflated_signature_images (MonoInflatedMethodSignature *sig, CollectData *data)
2794 collect_signature_images (sig->sig, data);
2795 if (sig->context.class_inst)
2796 collect_ginst_images (sig->context.class_inst, data);
2797 if (sig->context.method_inst)
2798 collect_ginst_images (sig->context.method_inst, data);
2802 collect_method_images (MonoMethodInflated *method, CollectData *data)
2804 MonoMethod *m = method->declaring;
2806 add_image (method->declaring->klass->image, data);
2807 if (method->context.class_inst)
2808 collect_ginst_images (method->context.class_inst, data);
2809 if (method->context.method_inst)
2810 collect_ginst_images (method->context.method_inst, data);
2812 * Dynamic assemblies have no references, so the images they depend on can be unloaded before them.
2814 if (image_is_dynamic (m->klass->image))
2815 collect_signature_images (mono_method_signature (m), data);
2819 collect_type_images (MonoType *type, CollectData *data)
2822 switch (type->type) {
2823 case MONO_TYPE_GENERICINST:
2824 collect_gclass_images (type->data.generic_class, data);
2827 type = type->data.type;
2829 case MONO_TYPE_SZARRAY:
2830 type = &type->data.klass->byval_arg;
2832 case MONO_TYPE_ARRAY:
2833 type = &type->data.array->eklass->byval_arg;
2835 case MONO_TYPE_FNPTR:
2836 //return signature_in_image (type->data.method, image);
2837 g_assert_not_reached ();
2839 case MONO_TYPE_MVAR:
2841 MonoImage *image = get_image_for_generic_param (type->data.generic_param);
2842 add_image (image, data);
2845 case MONO_TYPE_CLASS:
2846 case MONO_TYPE_VALUETYPE:
2847 add_image (mono_class_from_mono_type (type)->image, data);
2850 add_image (mono_defaults.corlib, data);
2857 } CleanForImageUserData;
2860 steal_gclass_in_image (gpointer key, gpointer value, gpointer data)
2862 MonoGenericClass *gclass = (MonoGenericClass *)key;
2863 CleanForImageUserData *user_data = (CleanForImageUserData *)data;
2865 g_assert (gclass_in_image (gclass, user_data->image));
2867 user_data->list = g_slist_prepend (user_data->list, gclass);
2872 steal_ginst_in_image (gpointer key, gpointer value, gpointer data)
2874 MonoGenericInst *ginst = (MonoGenericInst *)key;
2875 CleanForImageUserData *user_data = (CleanForImageUserData *)data;
2877 // This doesn't work during corlib compilation
2878 //g_assert (ginst_in_image (ginst, user_data->image));
2880 user_data->list = g_slist_prepend (user_data->list, ginst);
2885 inflated_method_in_image (gpointer key, gpointer value, gpointer data)
2887 MonoImage *image = (MonoImage *)data;
2888 MonoMethodInflated *method = (MonoMethodInflated *)key;
2891 // https://bugzilla.novell.com/show_bug.cgi?id=458168
2892 g_assert (method->declaring->klass->image == image ||
2893 (method->context.class_inst && ginst_in_image (method->context.class_inst, image)) ||
2894 (method->context.method_inst && ginst_in_image (method->context.method_inst, image)) || (((MonoMethod*)method)->signature && signature_in_image (mono_method_signature ((MonoMethod*)method), image)));
2900 inflated_signature_in_image (gpointer key, gpointer value, gpointer data)
2902 MonoImage *image = (MonoImage *)data;
2903 MonoInflatedMethodSignature *sig = (MonoInflatedMethodSignature *)key;
2905 return signature_in_image (sig->sig, image) ||
2906 (sig->context.class_inst && ginst_in_image (sig->context.class_inst, image)) ||
2907 (sig->context.method_inst && ginst_in_image (sig->context.method_inst, image));
2911 check_gmethod (gpointer key, gpointer value, gpointer data)
2913 MonoMethodInflated *method = (MonoMethodInflated *)key;
2914 MonoImage *image = (MonoImage *)data;
2916 if (method->context.class_inst)
2917 g_assert (!ginst_in_image (method->context.class_inst, image));
2918 if (method->context.method_inst)
2919 g_assert (!ginst_in_image (method->context.method_inst, image));
2920 if (((MonoMethod*)method)->signature)
2921 g_assert (!signature_in_image (mono_method_signature ((MonoMethod*)method), image));
2927 * Run a consistency check on the image set data structures.
2929 static G_GNUC_UNUSED void
2930 check_image_sets (MonoImage *image)
2933 GSList *l = image->image_sets;
2938 for (i = 0; i < image_sets->len; ++i) {
2939 MonoImageSet *set = (MonoImageSet *)g_ptr_array_index (image_sets, i);
2941 if (!g_slist_find (l, set)) {
2942 g_hash_table_foreach (set->gmethod_cache, check_gmethod, image);
2948 mono_metadata_clean_for_image (MonoImage *image)
2950 CleanForImageUserData ginst_data, gclass_data;
2951 GSList *l, *set_list;
2953 //check_image_sets (image);
2956 * The data structures could reference each other so we delete them in two phases.
2957 * This is required because of the hashing functions in gclass/ginst_cache.
2959 ginst_data.image = gclass_data.image = image;
2960 ginst_data.list = gclass_data.list = NULL;
2962 /* Collect the items to delete */
2963 /* delete_image_set () modifies the lists so make a copy */
2964 for (l = image->image_sets; l; l = l->next) {
2965 MonoImageSet *set = (MonoImageSet *)l->data;
2967 mono_image_set_lock (set);
2968 mono_conc_hashtable_foreach_steal (set->gclass_cache, steal_gclass_in_image, &gclass_data);
2969 g_hash_table_foreach_steal (set->ginst_cache, steal_ginst_in_image, &ginst_data);
2970 g_hash_table_foreach_remove (set->gmethod_cache, inflated_method_in_image, image);
2971 g_hash_table_foreach_remove (set->gsignature_cache, inflated_signature_in_image, image);
2972 mono_image_set_unlock (set);
2975 /* Delete the removed items */
2976 for (l = ginst_data.list; l; l = l->next)
2977 free_generic_inst ((MonoGenericInst *)l->data);
2978 for (l = gclass_data.list; l; l = l->next)
2979 free_generic_class ((MonoGenericClass *)l->data);
2980 g_slist_free (ginst_data.list);
2981 g_slist_free (gclass_data.list);
2982 /* delete_image_set () modifies the lists so make a copy */
2983 set_list = g_slist_copy (image->image_sets);
2984 for (l = set_list; l; l = l->next) {
2985 MonoImageSet *set = (MonoImageSet *)l->data;
2987 delete_image_set (set);
2989 g_slist_free (set_list);
2993 free_inflated_method (MonoMethodInflated *imethod)
2995 MonoMethod *method = (MonoMethod*)imethod;
2997 if (method->signature)
2998 mono_metadata_free_inflated_signature (method->signature);
3000 if (method->wrapper_type)
3001 g_free (((MonoMethodWrapper*)method)->method_data);
3007 free_generic_inst (MonoGenericInst *ginst)
3011 /* The ginst itself is allocated from the image set mempool */
3012 for (i = 0; i < ginst->type_argc; ++i)
3013 mono_metadata_free_type (ginst->type_argv [i]);
3017 free_generic_class (MonoGenericClass *gclass)
3019 /* The gclass itself is allocated from the image set mempool */
3020 if (gclass->cached_class && gclass->cached_class->interface_id)
3021 mono_unload_interface_id (gclass->cached_class);
3025 free_inflated_signature (MonoInflatedMethodSignature *sig)
3027 mono_metadata_free_inflated_signature (sig->sig);
3032 * mono_metadata_get_inflated_signature:
3034 * Given an inflated signature and a generic context, return a canonical copy of the
3035 * signature. The returned signature might be equal to SIG or it might be a cached copy.
3037 MonoMethodSignature *
3038 mono_metadata_get_inflated_signature (MonoMethodSignature *sig, MonoGenericContext *context)
3040 MonoInflatedMethodSignature helper;
3041 MonoInflatedMethodSignature *res;
3046 helper.context.class_inst = context->class_inst;
3047 helper.context.method_inst = context->method_inst;
3049 collect_data_init (&data);
3051 collect_inflated_signature_images (&helper, &data);
3053 set = get_image_set (data.images, data.nimages);
3055 collect_data_free (&data);
3057 mono_image_set_lock (set);
3059 res = (MonoInflatedMethodSignature *)g_hash_table_lookup (set->gsignature_cache, &helper);
3061 res = g_new0 (MonoInflatedMethodSignature, 1);
3063 res->context.class_inst = context->class_inst;
3064 res->context.method_inst = context->method_inst;
3065 g_hash_table_insert (set->gsignature_cache, res, res);
3068 mono_image_set_unlock (set);
3074 mono_metadata_get_image_set_for_method (MonoMethodInflated *method)
3077 CollectData image_set_data;
3079 collect_data_init (&image_set_data);
3080 collect_method_images (method, &image_set_data);
3081 set = get_image_set (image_set_data.images, image_set_data.nimages);
3082 collect_data_free (&image_set_data);
3088 type_is_gtd (MonoType *type)
3090 switch (type->type) {
3091 case MONO_TYPE_CLASS:
3092 case MONO_TYPE_VALUETYPE:
3093 return mono_class_is_gtd (type->data.klass);
3100 * mono_metadata_get_generic_inst:
3102 * Given a list of types, return a MonoGenericInst that represents that list.
3103 * The returned MonoGenericInst has its own copy of the list of types. The list
3104 * passed in the argument can be freed, modified or disposed of.
3108 mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
3110 MonoGenericInst *ginst;
3113 int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
3115 for (i = 0; i < type_argc; ++i)
3116 if (mono_class_is_open_constructed_type (type_argv [i]))
3118 is_open = (i < type_argc);
3120 ginst = (MonoGenericInst *)g_alloca (size);
3121 memset (ginst, 0, sizeof (MonoGenericInst));
3122 ginst->is_open = is_open;
3123 ginst->type_argc = type_argc;
3124 memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
3126 for (i = 0; i < type_argc; ++i) {
3127 MonoType *t = ginst->type_argv [i];
3128 if (type_is_gtd (t)) {
3129 ginst->type_argv [i] = mono_class_gtd_get_canonical_inst (t->data.klass);
3133 return mono_metadata_get_canonical_generic_inst (ginst);
3138 * mono_metadata_get_canonical_generic_inst:
3139 * \param candidate an arbitrary generic instantiation
3141 * \returns the canonical generic instantiation that represents the given
3142 * candidate by identifying the image set for the candidate instantiation and
3143 * finding the instance in the image set or adding a copy of the given instance
3146 * The returned MonoGenericInst has its own copy of the list of types. The list
3147 * passed in the argument can be freed, modified or disposed of.
3151 mono_metadata_get_canonical_generic_inst (MonoGenericInst *candidate)
3154 int type_argc = candidate->type_argc;
3155 gboolean is_open = candidate->is_open;
3158 collect_data_init (&data);
3160 collect_ginst_images (candidate, &data);
3162 set = get_image_set (data.images, data.nimages);
3164 collect_data_free (&data);
3166 mono_image_set_lock (set);
3168 MonoGenericInst *ginst = (MonoGenericInst *)g_hash_table_lookup (set->ginst_cache, candidate);
3170 int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
3171 ginst = (MonoGenericInst *)mono_image_set_alloc0 (set, size);
3172 #ifndef MONO_SMALL_CONFIG
3173 ginst->id = InterlockedIncrement (&next_generic_inst_id);
3175 ginst->is_open = is_open;
3176 ginst->type_argc = type_argc;
3178 for (int i = 0; i < type_argc; ++i)
3179 ginst->type_argv [i] = mono_metadata_type_dup (NULL, candidate->type_argv [i]);
3181 g_hash_table_insert (set->ginst_cache, ginst, ginst);
3184 mono_image_set_unlock (set);
3189 mono_metadata_is_type_builder_generic_type_definition (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
3191 MonoGenericContainer *container = mono_class_get_generic_container (container_class);
3193 if (!is_dynamic || container_class->wastypebuilder || container->type_argc != inst->type_argc)
3195 return inst == container->context.class_inst;
3199 * mono_metadata_lookup_generic_class:
3201 * Returns a MonoGenericClass with the given properties.
3205 mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
3207 MonoGenericClass *gclass;
3208 MonoGenericClass helper;
3209 gboolean is_tb_open = mono_metadata_is_type_builder_generic_type_definition (container_class, inst, is_dynamic);
3213 g_assert (mono_class_get_generic_container (container_class)->type_argc == inst->type_argc);
3215 memset (&helper, 0, sizeof(helper)); // act like g_new0
3216 helper.container_class = container_class;
3217 helper.context.class_inst = inst;
3218 helper.is_dynamic = is_dynamic; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
3219 helper.is_tb_open = is_tb_open;
3221 collect_data_init (&data);
3223 collect_gclass_images (&helper, &data);
3225 set = get_image_set (data.images, data.nimages);
3227 collect_data_free (&data);
3229 gclass = (MonoGenericClass *)mono_conc_hashtable_lookup (set->gclass_cache, &helper);
3231 /* A tripwire just to keep us honest */
3232 g_assert (!helper.cached_class);
3237 gclass = mono_image_set_new0 (set, MonoGenericClass, 1);
3239 gclass->is_dynamic = 1;
3241 gclass->is_tb_open = is_tb_open;
3242 gclass->container_class = container_class;
3243 gclass->context.class_inst = inst;
3244 gclass->context.method_inst = NULL;
3245 gclass->owner = set;
3246 if (inst == mono_class_get_generic_container (container_class)->context.class_inst && !is_tb_open)
3247 gclass->cached_class = container_class;
3249 mono_image_set_lock (set);
3251 MonoGenericClass *gclass2 = mono_conc_hashtable_insert (set->gclass_cache, gclass, gclass);
3255 // g_hash_table_insert (set->gclass_cache, gclass, gclass);
3257 mono_image_set_unlock (set);
3263 * mono_metadata_inflate_generic_inst:
3265 * Instantiate the generic instance @ginst with the context @context.
3266 * Check @error for success.
3270 mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context, MonoError *error)
3272 MonoType **type_argv;
3273 MonoGenericInst *nginst = NULL;
3278 if (!ginst->is_open)
3281 type_argv = g_new0 (MonoType*, ginst->type_argc);
3283 for (i = 0; i < ginst->type_argc; i++) {
3284 type_argv [i] = mono_class_inflate_generic_type_checked (ginst->type_argv [i], context, error);
3285 if (!mono_error_ok (error))
3290 nginst = mono_metadata_get_generic_inst (ginst->type_argc, type_argv);
3293 for (i = 0; i < count; i++)
3294 mono_metadata_free_type (type_argv [i]);
3301 mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container,
3302 int count, const char *ptr, const char **rptr, MonoError *error)
3304 MonoType **type_argv;
3305 MonoGenericInst *ginst;
3309 type_argv = g_new0 (MonoType*, count);
3311 for (i = 0; i < count; i++) {
3312 MonoType *t = mono_metadata_parse_type_checked (m, container, 0, FALSE, ptr, &ptr, error);
3323 ginst = mono_metadata_get_generic_inst (count, type_argv);
3331 do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
3332 const char *ptr, const char **rptr, MonoError *error)
3334 MonoGenericInst *inst;
3341 // XXX how about transient?
3342 gtype = mono_metadata_parse_type_checked (m, NULL, 0, FALSE, ptr, &ptr, error);
3346 gklass = mono_class_from_mono_type (gtype);
3347 if (!mono_class_is_gtd (gklass)) {
3348 mono_error_set_bad_image (error, m, "Generic instance with non-generic definition");
3352 count = mono_metadata_decode_value (ptr, &ptr);
3353 inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr, error);
3360 type->data.generic_class = mono_metadata_lookup_generic_class (gklass, inst, FALSE);
3366 * @gc: The generic container to normalize
3367 * @type: The kind of generic parameters the resulting generic-container should contain
3370 static MonoGenericContainer *
3371 select_container (MonoGenericContainer *gc, MonoTypeEnum type)
3373 gboolean is_var = (type == MONO_TYPE_VAR);
3377 g_assert (is_var || type == MONO_TYPE_MVAR);
3380 if (gc->is_method || gc->parent)
3382 * The current MonoGenericContainer is a generic method -> its `parent'
3383 * points to the containing class'es container.
3391 MonoGenericContainer *
3392 get_anonymous_container_for_image (MonoImage *image, gboolean is_mvar)
3394 MonoGenericContainer **container_pointer;
3396 container_pointer = &image->anonymous_generic_method_container;
3398 container_pointer = &image->anonymous_generic_class_container;
3399 MonoGenericContainer *result = *container_pointer;
3401 // This container has never been created; make it now.
3404 // Note this is never deallocated anywhere-- it exists for the lifetime of the image it's allocated from
3405 result = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
3406 result->owner.image = image;
3407 result->is_anonymous = TRUE;
3408 result->is_small_param = TRUE;
3409 result->is_method = is_mvar;
3411 // If another thread already made a container, use that and leak this new one.
3412 // (Technically it would currently be safe to just assign instead of CASing.)
3413 MonoGenericContainer *exchange = (MonoGenericContainer *)InterlockedCompareExchangePointer ((volatile gpointer *)container_pointer, result, NULL);
3421 * mono_metadata_parse_generic_param:
3422 * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3423 * see mono_metadata_parse_type_checked() for details.
3424 * Internal routine to parse a generic type parameter.
3425 * LOCKING: Acquires the loader lock
3427 static MonoGenericParam *
3428 mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
3429 MonoTypeEnum type, const char *ptr, const char **rptr, MonoError *error)
3431 int index = mono_metadata_decode_value (ptr, &ptr);
3437 generic_container = select_container (generic_container, type);
3438 if (!generic_container) {
3439 gboolean is_mvar = FALSE;
3444 case MONO_TYPE_MVAR:
3448 g_error ("Cerating generic param object with invalid MonoType"); // This is not a generic param
3451 /* Create dummy MonoGenericParam */
3452 MonoGenericParam *param;
3454 param = (MonoGenericParam *)mono_image_alloc0 (m, sizeof (MonoGenericParam));
3456 param->owner = get_anonymous_container_for_image (m, is_mvar);
3461 if (index >= generic_container->type_argc) {
3462 mono_error_set_bad_image (error, m, "Invalid generic %s parameter index %d, max index is %d",
3463 generic_container->is_method ? "method" : "type",
3464 index, generic_container->type_argc);
3468 //This can't return NULL
3469 return mono_generic_container_get_param (generic_container, index);
3473 * mono_metadata_get_shared_type:
3475 * Return a shared instance of TYPE, if available, NULL otherwise.
3476 * Shared MonoType instances help save memory. Their contents should not be modified
3477 * by the caller. They do not need to be freed as their lifetime is bound by either
3478 * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3479 * instance they are embedded in. If they are freed, they should be freed using
3480 * mono_metadata_free_type () instead of g_free ().
3483 mono_metadata_get_shared_type (MonoType *type)
3487 /* No need to use locking since nobody is modifying the hash table */
3488 if ((cached = (MonoType *)g_hash_table_lookup (type_cache, type)))
3491 switch (type->type){
3492 case MONO_TYPE_CLASS:
3493 case MONO_TYPE_VALUETYPE:
3494 if (type == &type->data.klass->byval_arg)
3496 if (type == &type->data.klass->this_arg)
3507 compare_type_literals (MonoImage *image, int class_type, int type_type, MonoError *error)
3511 /* byval_arg.type can be zero if we're decoding a type that references a class been loading.
3512 * See mcs/test/gtest-440. and #650936.
3513 * FIXME This better be moved to the metadata verifier as it can catch more cases.
3517 /* NET 1.1 assemblies might encode string and object in a denormalized way.
3520 if (class_type == type_type)
3523 if (type_type == MONO_TYPE_CLASS) {
3524 if (class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT)
3526 //XXX stringify this argument
3527 mono_error_set_bad_image (error, image, "Expected reference type but got type kind %d", class_type);
3531 g_assert (type_type == MONO_TYPE_VALUETYPE);
3532 switch (class_type) {
3533 case MONO_TYPE_BOOLEAN:
3534 case MONO_TYPE_CHAR:
3547 case MONO_TYPE_CLASS:
3550 //XXX stringify this argument
3551 mono_error_set_bad_image (error, image, "Expected value type but got type kind %d", class_type);
3557 verify_var_type_and_container (MonoImage *image, int var_type, MonoGenericContainer *container, MonoError *error)
3560 if (var_type == MONO_TYPE_MVAR) {
3561 if (!container->is_method) { //MVAR and a method container
3562 mono_error_set_bad_image (error, image, "MVAR parsed in a context without a method container");
3566 if (!(!container->is_method || //VAR and class container
3567 (container->is_method && container->parent))) { //VAR and method container with parent
3568 mono_error_set_bad_image (error, image, "VAR parsed in a context without a class container");
3576 * do_mono_metadata_parse_type:
3577 * @type: MonoType to be filled in with the return value
3579 * @generic_context: generics_context
3580 * @transient: whenever to allocate data from the heap
3581 * @ptr: pointer to the encoded type
3582 * @rptr: pointer where the end of the encoded type is saved
3584 * Internal routine used to "fill" the contents of @type from an
3585 * allocated pointer. This is done this way to avoid doing too
3586 * many mini-allocations (particularly for the MonoFieldType which
3587 * most of the time is just a MonoType, but sometimes might be augmented).
3589 * This routine is used by mono_metadata_parse_type and
3590 * mono_metadata_parse_field_type
3592 * This extracts a Type as specified in Partition II (22.2.12)
3594 * Returns: FALSE if the type could not be loaded
3597 do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
3598 gboolean transient, const char *ptr, const char **rptr, MonoError *error)
3602 type->type = (MonoTypeEnum)mono_metadata_decode_value (ptr, &ptr);
3604 switch (type->type){
3605 case MONO_TYPE_VOID:
3606 case MONO_TYPE_BOOLEAN:
3607 case MONO_TYPE_CHAR:
3620 case MONO_TYPE_STRING:
3621 case MONO_TYPE_OBJECT:
3622 case MONO_TYPE_TYPEDBYREF:
3624 case MONO_TYPE_VALUETYPE:
3625 case MONO_TYPE_CLASS: {
3628 token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
3629 klass = mono_class_get_checked (m, token, error);
3630 type->data.klass = klass;
3634 if (!compare_type_literals (m, klass->byval_arg.type, type->type, error))
3639 case MONO_TYPE_SZARRAY: {
3640 MonoType *etype = mono_metadata_parse_type_checked (m, container, 0, transient, ptr, &ptr, error);
3644 type->data.klass = mono_class_from_mono_type (etype);
3647 mono_metadata_free_type (etype);
3649 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.
3652 case MONO_TYPE_PTR: {
3653 type->data.type = mono_metadata_parse_type_checked (m, container, 0, transient, ptr, &ptr, error);
3654 if (!type->data.type)
3658 case MONO_TYPE_FNPTR: {
3659 type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr, error);
3660 if (!type->data.method)
3664 case MONO_TYPE_ARRAY: {
3665 type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr, error);
3666 if (!type->data.array)
3670 case MONO_TYPE_MVAR:
3671 case MONO_TYPE_VAR: {
3672 if (container && !verify_var_type_and_container (m, type->type, container, error))
3675 type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr, error);
3676 if (!type->data.generic_param)
3681 case MONO_TYPE_GENERICINST: {
3682 if (!do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr, error))
3687 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);
3697 * mono_metadata_free_type:
3698 * \param type type to free
3700 * Free the memory allocated for type \p type which is allocated on the heap.
3703 mono_metadata_free_type (MonoType *type)
3705 if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
3708 switch (type->type){
3709 case MONO_TYPE_OBJECT:
3710 case MONO_TYPE_STRING:
3711 if (!type->data.klass)
3714 case MONO_TYPE_CLASS:
3715 case MONO_TYPE_VALUETYPE:
3716 if (type == &type->data.klass->byval_arg || type == &type->data.klass->this_arg)
3720 mono_metadata_free_type (type->data.type);
3722 case MONO_TYPE_FNPTR:
3723 mono_metadata_free_method_signature (type->data.method);
3725 case MONO_TYPE_ARRAY:
3726 mono_metadata_free_array (type->data.array);
3737 hex_dump (const char *buffer, int base, int count)
3739 int show_header = 1;
3747 for (i = 0; i < count; i++){
3750 printf ("\n0x%08x: ", (unsigned char) base + i);
3752 printf ("%02x ", (unsigned char) (buffer [i]));
3759 * @ptr: Points to the beginning of the Section Data (25.3)
3761 static MonoExceptionClause*
3762 parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr, MonoError *error)
3764 unsigned char sect_data_flags;
3766 guint32 sect_data_len;
3767 MonoExceptionClause* clauses = NULL;
3772 /* align on 32-bit boundary */
3773 ptr = dword_align (ptr);
3774 sect_data_flags = *ptr;
3777 is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
3779 sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
3782 sect_data_len = ptr [0];
3786 if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
3787 const unsigned char *p = dword_align (ptr);
3789 *num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
3790 /* we could just store a pointer if we don't need to byteswap */
3791 clauses = (MonoExceptionClause *)g_malloc0 (sizeof (MonoExceptionClause) * (*num_clauses));
3792 for (i = 0; i < *num_clauses; ++i) {
3793 MonoExceptionClause *ec = &clauses [i];
3796 ec->flags = read32 (p);
3797 ec->try_offset = read32 (p + 4);
3798 ec->try_len = read32 (p + 8);
3799 ec->handler_offset = read32 (p + 12);
3800 ec->handler_len = read32 (p + 16);
3801 tof_value = read32 (p + 20);
3804 ec->flags = read16 (p);
3805 ec->try_offset = read16 (p + 2);
3806 ec->try_len = *(p + 4);
3807 ec->handler_offset = read16 (p + 5);
3808 ec->handler_len = *(p + 7);
3809 tof_value = read32 (p + 8);
3812 if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
3813 ec->data.filter_offset = tof_value;
3814 } else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) {
3815 ec->data.catch_class = NULL;
3817 ec->data.catch_class = mono_class_get_checked (m, tof_value, error);
3818 if (!is_ok (error)) {
3824 ec->data.catch_class = NULL;
3826 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
3830 if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
3831 ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
3838 * mono_method_get_header_summary:
3839 * @method: The method to get the header.
3840 * @summary: Where to store the header
3843 * Returns: TRUE if the header was properly decoded.
3846 mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *summary)
3852 unsigned char flags, format;
3855 /*Only the GMD has a pointer to the metadata.*/
3856 while (method->is_inflated)
3857 method = ((MonoMethodInflated*)method)->declaring;
3859 summary->code_size = 0;
3860 summary->has_clauses = FALSE;
3862 /*FIXME extract this into a MACRO and share it with mono_method_get_header*/
3863 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))
3866 if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) {
3867 MonoMethodHeader *header = ((MonoMethodWrapper *)method)->header;
3870 summary->code_size = header->code_size;
3871 summary->has_clauses = header->num_clauses > 0;
3876 idx = mono_metadata_token_index (method->token);
3877 img = method->klass->image;
3878 rva = mono_metadata_decode_row_col (&img->tables [MONO_TABLE_METHOD], idx - 1, MONO_METHOD_RVA);
3880 /*We must run the verifier since we'll be decoding it.*/
3881 if (!mono_verifier_verify_method_header (img, rva, NULL))
3884 ptr = mono_image_rva_map (img, rva);
3888 flags = *(const unsigned char *)ptr;
3889 format = flags & METHOD_HEADER_FORMAT_MASK;
3892 case METHOD_HEADER_TINY_FORMAT:
3894 summary->code_size = flags >> 2;
3896 case METHOD_HEADER_FAT_FORMAT:
3897 fat_flags = read16 (ptr);
3899 summary->code_size = read32 (ptr);
3900 if (fat_flags & METHOD_HEADER_MORE_SECTS)
3901 summary->has_clauses = TRUE;
3910 * mono_metadata_parse_mh_full:
3911 * @m: metadata context
3912 * @generic_context: generics context
3913 * @ptr: pointer to the method header.
3915 * Decode the method header at @ptr, including pointer to the IL code,
3916 * info about local variables and optional exception tables.
3917 * This is a Mono runtime internal function.
3919 * LOCKING: Acquires the loader lock.
3921 * Returns: a transient MonoMethodHeader allocated from the heap.
3924 mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr, MonoError *error)
3926 MonoMethodHeader *mh = NULL;
3927 unsigned char flags = *(const unsigned char *) ptr;
3928 unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
3930 guint32 local_var_sig_tok, max_stack, code_size, init_locals;
3931 const unsigned char *code;
3932 MonoExceptionClause* clauses = NULL;
3933 int num_clauses = 0;
3934 MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
3935 guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
3940 mono_error_set_bad_image (error, m, "Method header with null pointer");
3945 case METHOD_HEADER_TINY_FORMAT:
3946 mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER);
3949 mh->is_transient = TRUE;
3950 local_var_sig_tok = 0;
3951 mh->code_size = flags >> 2;
3952 mh->code = (unsigned char*)ptr;
3954 case METHOD_HEADER_FAT_FORMAT:
3955 fat_flags = read16 (ptr);
3957 max_stack = read16 (ptr);
3959 code_size = read32 (ptr);
3961 local_var_sig_tok = read32 (ptr);
3964 if (fat_flags & METHOD_HEADER_INIT_LOCALS)
3969 code = (unsigned char*)ptr;
3971 if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
3975 * There are more sections
3977 ptr = (char*)code + code_size;
3980 mono_error_set_bad_image (error, m, "Invalid method header format %d", format);
3984 if (local_var_sig_tok) {
3985 int idx = (local_var_sig_tok & 0xffffff)-1;
3986 if (idx >= t->rows || idx < 0) {
3987 mono_error_set_bad_image (error, m, "Invalid method header local vars signature token 0x%8x", idx);
3990 mono_metadata_decode_row (t, idx, cols, 1);
3992 if (!mono_verifier_verify_standalone_signature (m, cols [MONO_STAND_ALONE_SIGNATURE], NULL)) {
3993 mono_error_set_bad_image (error, m, "Method header locals signature 0x%8x verification failed", idx);
3997 if (fat_flags & METHOD_HEADER_MORE_SECTS) {
3998 clauses = parse_section_data (m, &num_clauses, (const unsigned char*)ptr, error);
4002 if (local_var_sig_tok) {
4003 const char *locals_ptr;
4006 locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
4007 mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
4008 if (*locals_ptr != 0x07)
4009 g_warning ("wrong signature for locals blob");
4011 len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
4012 mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*) + num_clauses * sizeof (MonoExceptionClause));
4013 mh->num_locals = len;
4014 for (i = 0; i < len; ++i) {
4015 mh->locals [i] = mono_metadata_parse_type_internal (m, container, 0, TRUE, locals_ptr, &locals_ptr, error);
4020 mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause));
4023 mh->code_size = code_size;
4024 mh->max_stack = max_stack;
4025 mh->is_transient = TRUE;
4026 mh->init_locals = init_locals;
4028 MonoExceptionClause* clausesp = (MonoExceptionClause*)&mh->locals [mh->num_locals];
4029 memcpy (clausesp, clauses, num_clauses * sizeof (MonoExceptionClause));
4031 mh->clauses = clausesp;
4032 mh->num_clauses = num_clauses;
4043 * mono_metadata_parse_mh:
4044 * \param generic_context generics context
4045 * \param ptr pointer to the method header.
4047 * Decode the method header at \p ptr, including pointer to the IL code,
4048 * info about local variables and optional exception tables.
4050 * \returns a transient \c MonoMethodHeader allocated from the heap.
4053 mono_metadata_parse_mh (MonoImage *m, const char *ptr)
4056 MonoMethodHeader *header = mono_metadata_parse_mh_full (m, NULL, ptr, &error);
4057 mono_error_cleanup (&error);
4062 * mono_metadata_free_mh:
4063 * \param mh a method header
4065 * Free the memory allocated for the method header.
4068 mono_metadata_free_mh (MonoMethodHeader *mh)
4072 /* If it is not transient it means it's part of a wrapper method,
4073 * or a SRE-generated method, so the lifetime in that case is
4074 * dictated by the method's own lifetime
4076 if (mh->is_transient) {
4077 for (i = 0; i < mh->num_locals; ++i)
4078 mono_metadata_free_type (mh->locals [i]);
4084 * mono_method_header_get_code:
4085 * \param header a \c MonoMethodHeader pointer
4086 * \param code_size memory location for returning the code size
4087 * \param max_stack memory location for returning the max stack
4089 * Method header accessor to retreive info about the IL code properties:
4090 * a pointer to the IL code itself, the size of the code and the max number
4091 * of stack slots used by the code.
4093 * \returns pointer to the IL code represented by the method header.
4095 const unsigned char*
4096 mono_method_header_get_code (MonoMethodHeader *header, guint32* code_size, guint32* max_stack)
4099 *code_size = header->code_size;
4101 *max_stack = header->max_stack;
4102 return header->code;
4106 * mono_method_header_get_locals:
4107 * \param header a \c MonoMethodHeader pointer
4108 * \param num_locals memory location for returning the number of local variables
4109 * \param init_locals memory location for returning the init_locals flag
4111 * Method header accessor to retreive info about the local variables:
4112 * an array of local types, the number of locals and whether the locals
4113 * are supposed to be initialized to 0 on method entry
4115 * \returns pointer to an array of types of the local variables
4118 mono_method_header_get_locals (MonoMethodHeader *header, guint32* num_locals, gboolean *init_locals)
4121 *num_locals = header->num_locals;
4123 *init_locals = header->init_locals;
4124 return header->locals;
4128 * mono_method_header_get_num_clauses:
4129 * @header: a MonoMethodHeader pointer
4131 * Method header accessor to retreive the number of exception clauses.
4133 * Returns: the number of exception clauses present
4136 mono_method_header_get_num_clauses (MonoMethodHeader *header)
4138 return header->num_clauses;
4142 * mono_method_header_get_clauses:
4143 * \param header a \c MonoMethodHeader pointer
4144 * \param method \c MonoMethod the header belongs to
4145 * \param iter pointer to a iterator
4146 * \param clause pointer to a \c MonoExceptionClause structure which will be filled with the info
4148 * Get the info about the exception clauses in the method. Set \c *iter to NULL to
4149 * initiate the iteration, then call the method repeatedly until it returns FALSE.
4150 * At each iteration, the structure pointed to by clause if filled with the
4151 * exception clause information.
4153 * \returns TRUE if clause was filled with info, FALSE if there are no more exception
4157 mono_method_header_get_clauses (MonoMethodHeader *header, MonoMethod *method, gpointer *iter, MonoExceptionClause *clause)
4159 MonoExceptionClause *sc;
4160 /* later we'll be able to use this interface to parse the clause info on demand,
4161 * without allocating anything.
4163 if (!iter || !header->num_clauses)
4166 *iter = sc = header->clauses;
4170 sc = (MonoExceptionClause *)*iter;
4172 if (sc < header->clauses + header->num_clauses) {
4181 * mono_metadata_parse_field_type:
4182 * \param m metadata context to extract information from
4183 * \param ptr pointer to the field signature
4184 * \param rptr pointer updated to match the end of the decoded stream
4186 * Parses the field signature, and returns the type information for it.
4188 * \returns The \c MonoType that was extracted from \p ptr .
4191 mono_metadata_parse_field_type (MonoImage *m, short field_flags, const char *ptr, const char **rptr)
4194 MonoType * type = mono_metadata_parse_type_internal (m, NULL, field_flags, FALSE, ptr, rptr, &error);
4195 mono_error_cleanup (&error);
4200 * mono_metadata_parse_param:
4201 * \param m metadata context to extract information from
4202 * \param ptr pointer to the param signature
4203 * \param rptr pointer updated to match the end of the decoded stream
4205 * Parses the param signature, and returns the type information for it.
4207 * \returns The \c MonoType that was extracted from \p ptr .
4210 mono_metadata_parse_param (MonoImage *m, const char *ptr, const char **rptr)
4213 MonoType * type = mono_metadata_parse_type_internal (m, NULL, 0, FALSE, ptr, rptr, &error);
4214 mono_error_cleanup (&error);
4219 * mono_metadata_token_from_dor:
4220 * \param dor_token A \c TypeDefOrRef coded index
4222 * \p dor_token is a \c TypeDefOrRef coded index: it contains either
4223 * a \c TypeDef, \c TypeRef or \c TypeSpec in the lower bits, and the upper
4224 * bits contain an index into the table.
4226 * \returns an expanded token
4229 mono_metadata_token_from_dor (guint32 dor_index)
4233 table = dor_index & 0x03;
4234 idx = dor_index >> 2;
4237 case 0: /* TypeDef */
4238 return MONO_TOKEN_TYPE_DEF | idx;
4239 case 1: /* TypeRef */
4240 return MONO_TOKEN_TYPE_REF | idx;
4241 case 2: /* TypeSpec */
4242 return MONO_TOKEN_TYPE_SPEC | idx;
4244 g_assert_not_reached ();
4251 * We use this to pass context information to the row locator
4254 int idx; /* The index that we are trying to locate */
4255 int col_idx; /* The index in the row where idx may be stored */
4256 MonoTableInfo *t; /* pointer to the table */
4261 * How the row locator works.
4266 * ___|___------> _______
4269 * A column in the rows of table A references an index in table B.
4270 * For example A may be the TYPEDEF table and B the METHODDEF table.
4272 * Given an index in table B we want to get the row in table A
4273 * where the column n references our index in B.
4275 * In the locator_t structure:
4277 * col_idx is the column number
4278 * index is the index in table B
4279 * result will be the index in table A
4282 * Table A Table B column (in table A)
4283 * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
4284 * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
4285 * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
4286 * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
4287 * METHODSEM PROPERTY ASSOCIATION (encoded index)
4289 * Note that we still don't support encoded indexes.
4293 typedef_locator (const void *a, const void *b)
4295 locator_t *loc = (locator_t *) a;
4296 const char *bb = (const char *) b;
4297 int typedef_index = (bb - loc->t->base) / loc->t->row_size;
4298 guint32 col, col_next;
4300 col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx);
4306 * Need to check that the next row is valid.
4308 if (typedef_index + 1 < loc->t->rows) {
4309 col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx);
4310 if (loc->idx >= col_next)
4313 if (col == col_next)
4317 loc->result = typedef_index;
4323 table_locator (const void *a, const void *b)
4325 locator_t *loc = (locator_t *) a;
4326 const char *bb = (const char *) b;
4327 guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
4330 col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
4332 if (loc->idx == col) {
4333 loc->result = table_index;
4343 declsec_locator (const void *a, const void *b)
4345 locator_t *loc = (locator_t *) a;
4346 const char *bb = (const char *) b;
4347 guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
4350 col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
4352 if (loc->idx == col) {
4353 loc->result = table_index;
4365 * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
4366 * which contains IDX.
4369 search_ptr_table (MonoImage *image, int table, int idx)
4371 MonoTableInfo *ptrdef = &image->tables [table];
4374 /* Use a linear search to find our index in the table */
4375 for (i = 0; i < ptrdef->rows; i ++)
4376 /* All the Ptr tables have the same structure */
4377 if (mono_metadata_decode_row_col (ptrdef, i, 0) == idx)
4380 if (i < ptrdef->rows)
4387 * mono_metadata_typedef_from_field:
4388 * \param meta metadata context
4389 * \param index FieldDef token
4391 * \returns the 1-based index into the \c TypeDef table of the type that
4392 * declared the field described by \p index, or 0 if not found.
4395 mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
4397 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
4403 loc.idx = mono_metadata_token_index (index);
4404 loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
4407 if (meta->uncompressed_metadata)
4408 loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
4410 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
4413 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4414 return loc.result + 1;
4418 * mono_metadata_typedef_from_method:
4419 * \param meta metadata context
4420 * \param index \c MethodDef token
4421 * \returns the 1-based index into the \c TypeDef table of the type that
4422 * declared the method described by \p index. 0 if not found.
4425 mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
4427 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
4433 loc.idx = mono_metadata_token_index (index);
4434 loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
4437 if (meta->uncompressed_metadata)
4438 loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx);
4440 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
4443 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4444 return loc.result + 1;
4448 * mono_metadata_interfaces_from_typedef_full:
4449 * @meta: metadata context
4450 * @index: typedef token
4451 * @interfaces: Out parameter used to store the interface array
4452 * @count: Out parameter used to store the number of interfaces
4453 * @heap_alloc_result: if TRUE the result array will be g_malloc'd
4454 * @context: The generic context
4456 * The array of interfaces that the @index typedef token implements is returned in
4457 * @interfaces. The number of elements in the array is returned in @count.
4460 * Returns: TRUE on success, FALSE on failure.
4463 mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context, MonoError *error)
4465 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
4468 guint32 cols [MONO_INTERFACEIMPL_SIZE];
4479 loc.idx = mono_metadata_token_index (index);
4480 loc.col_idx = MONO_INTERFACEIMPL_CLASS;
4483 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4488 * We may end up in the middle of the rows...
4491 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_INTERFACEIMPL_CLASS))
4497 while (pos < tdef->rows) {
4498 mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
4499 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
4504 if (heap_alloc_result)
4505 result = g_new0 (MonoClass*, pos - start);
4507 result = (MonoClass **)mono_image_alloc0 (meta, sizeof (MonoClass*) * (pos - start));
4510 while (pos < tdef->rows) {
4513 mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
4514 if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
4516 iface = mono_class_get_and_inflate_typespec_checked (
4517 meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context, error);
4520 result [pos - start] = iface;
4523 *count = pos - start;
4524 *interfaces = result;
4529 * mono_metadata_interfaces_from_typedef:
4530 * \param meta metadata context
4531 * \param index typedef token
4532 * \param count Out parameter used to store the number of interfaces
4534 * The array of interfaces that the \p index typedef token implements is returned in
4535 * \p interfaces. The number of elements in the array is returned in \p count. The returned
4536 * array is allocated with \c g_malloc and the caller must free it.
4538 * LOCKING: Acquires the loader lock .
4540 * \returns the interface array on success, NULL on failure.
4543 mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
4546 MonoClass **interfaces = NULL;
4549 rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, TRUE, NULL, &error);
4550 g_assert (mono_error_ok (&error)); /* FIXME dont swallow the error */
4558 * mono_metadata_nested_in_typedef:
4559 * \param meta metadata context
4560 * \param index typedef token
4561 * \returns the 1-based index into the TypeDef table of the type
4562 * where the type described by \p index is nested.
4563 * Returns 0 if \p index describes a non-nested type.
4566 mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
4568 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
4574 loc.idx = mono_metadata_token_index (index);
4575 loc.col_idx = MONO_NESTED_CLASS_NESTED;
4578 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4581 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4582 return mono_metadata_decode_row_col (tdef, loc.result, MONO_NESTED_CLASS_ENCLOSING) | MONO_TOKEN_TYPE_DEF;
4586 * mono_metadata_nesting_typedef:
4587 * \param meta metadata context
4588 * \param index typedef token
4589 * \returns the 1-based index into the \c TypeDef table of the first type
4590 * that is nested inside the type described by \p index. The search starts at
4591 * \p start_index. Returns 0 if no such type is found.
4594 mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
4596 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
4598 guint32 class_index = mono_metadata_token_index (index);
4603 start = start_index;
4605 while (start <= tdef->rows) {
4606 if (class_index == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
4612 if (start > tdef->rows)
4619 * mono_metadata_packing_from_typedef:
4620 * \param meta metadata context
4621 * \param index token representing a type
4622 * \returns the info stored in the \c ClassLayout table for the given typedef token
4623 * into the \p packing and \p size pointers.
4624 * Returns 0 if the info is not found.
4627 mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *packing, guint32 *size)
4629 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CLASSLAYOUT];
4631 guint32 cols [MONO_CLASS_LAYOUT_SIZE];
4636 loc.idx = mono_metadata_token_index (index);
4637 loc.col_idx = MONO_CLASS_LAYOUT_PARENT;
4640 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4643 mono_metadata_decode_row (tdef, loc.result, cols, MONO_CLASS_LAYOUT_SIZE);
4645 *packing = cols [MONO_CLASS_LAYOUT_PACKING_SIZE];
4647 *size = cols [MONO_CLASS_LAYOUT_CLASS_SIZE];
4649 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4650 return loc.result + 1;
4654 * mono_metadata_custom_attrs_from_index:
4655 * \param meta metadata context
4656 * \param index token representing the parent
4657 * \returns: the 1-based index into the \c CustomAttribute table of the first
4658 * attribute which belongs to the metadata object described by \p index.
4659 * Returns 0 if no such attribute is found.
4662 mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
4664 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4671 loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
4674 /* FIXME: Index translation */
4676 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4679 /* Find the first entry by searching backwards */
4680 while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_CUSTOM_ATTR_PARENT) == index))
4683 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4684 return loc.result + 1;
4688 * mono_metadata_declsec_from_index:
4689 * \param meta metadata context
4690 * \param index token representing the parent
4691 * \returns the 0-based index into the \c DeclarativeSecurity table of the first
4692 * attribute which belongs to the metadata object described by \p index.
4693 * Returns \c -1 if no such attribute is found.
4696 mono_metadata_declsec_from_index (MonoImage *meta, guint32 index)
4698 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_DECLSECURITY];
4705 loc.col_idx = MONO_DECL_SECURITY_PARENT;
4708 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
4711 /* Find the first entry by searching backwards */
4712 while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_DECL_SECURITY_PARENT) == index))
4719 * mono_metadata_localscope_from_methoddef:
4720 * @meta: metadata context
4721 * @index: methoddef index
4723 * Returns: the 1-based index into the LocalScope table of the first
4724 * scope which belongs to the method described by @index.
4725 * Returns 0 if no such row is found.
4728 mono_metadata_localscope_from_methoddef (MonoImage *meta, guint32 index)
4730 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_LOCALSCOPE];
4737 loc.col_idx = MONO_LOCALSCOPE_METHOD;
4740 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4743 /* Find the first entry by searching backwards */
4744 while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_LOCALSCOPE_METHOD) == index))
4747 return loc.result + 1;
4752 mono_backtrace (int limit)
4757 backtrace (array, limit);
4758 names = backtrace_symbols (array, limit);
4759 for (i =0; i < limit; ++i) {
4760 g_print ("\t%s\n", names [i]);
4766 static int i8_align;
4769 * mono_type_set_alignment:
4771 * Set the alignment used by runtime to layout fields etc. of type TYPE to ALIGN.
4772 * This should only be used in AOT mode since the resulting layout will not match the
4776 mono_type_set_alignment (MonoTypeEnum type, int align)
4778 /* Support only a few types whose alignment is abi dependent */
4784 g_assert_not_reached ();
4791 * \param t the type to return the size of
4792 * \returns The number of bytes required to hold an instance of this
4796 mono_type_size (MonoType *t, int *align)
4798 MonoTypeEnum simple_type;
4805 *align = MONO_ABI_ALIGNOF (gpointer);
4806 return MONO_ABI_SIZEOF (gpointer);
4809 simple_type = t->type;
4811 switch (simple_type) {
4812 case MONO_TYPE_VOID:
4815 case MONO_TYPE_BOOLEAN:
4816 *align = MONO_ABI_ALIGNOF (gint8);
4820 *align = MONO_ABI_ALIGNOF (gint8);
4822 case MONO_TYPE_CHAR:
4825 *align = MONO_ABI_ALIGNOF (gint16);
4829 *align = MONO_ABI_ALIGNOF (gint32);
4832 *align = MONO_ABI_ALIGNOF (float);
4836 *align = MONO_ABI_ALIGNOF (gint64);
4839 *align = MONO_ABI_ALIGNOF (double);
4843 *align = MONO_ABI_ALIGNOF (gpointer);
4844 return MONO_ABI_SIZEOF (gpointer);
4845 case MONO_TYPE_VALUETYPE: {
4846 if (t->data.klass->enumtype)
4847 return mono_type_size (mono_class_enum_basetype (t->data.klass), align);
4849 return mono_class_value_size (t->data.klass, (guint32*)align);
4851 case MONO_TYPE_STRING:
4852 case MONO_TYPE_OBJECT:
4853 case MONO_TYPE_CLASS:
4854 case MONO_TYPE_SZARRAY:
4856 case MONO_TYPE_FNPTR:
4857 case MONO_TYPE_ARRAY:
4858 *align = MONO_ABI_ALIGNOF (gpointer);
4859 return MONO_ABI_SIZEOF (gpointer);
4860 case MONO_TYPE_TYPEDBYREF:
4861 return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align);
4862 case MONO_TYPE_GENERICINST: {
4863 MonoGenericClass *gclass = t->data.generic_class;
4864 MonoClass *container_class = gclass->container_class;
4866 // g_assert (!gclass->inst->is_open);
4868 if (container_class->valuetype) {
4869 if (container_class->enumtype)
4870 return mono_type_size (mono_class_enum_basetype (container_class), align);
4872 return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
4874 *align = MONO_ABI_ALIGNOF (gpointer);
4875 return MONO_ABI_SIZEOF (gpointer);
4879 case MONO_TYPE_MVAR:
4880 if (!t->data.generic_param->gshared_constraint || t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE) {
4881 *align = MONO_ABI_ALIGNOF (gpointer);
4882 return MONO_ABI_SIZEOF (gpointer);
4884 /* The gparam can only match types given by gshared_constraint */
4885 return mono_type_size (t->data.generic_param->gshared_constraint, align);
4889 g_error ("mono_type_size: type 0x%02x unknown", t->type);
4895 * mono_type_stack_size:
4896 * \param t the type to return the size it uses on the stack
4897 * \returns The number of bytes required to hold an instance of this
4898 * type on the runtime stack
4901 mono_type_stack_size (MonoType *t, int *align)
4903 return mono_type_stack_size_internal (t, align, FALSE);
4907 mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
4910 MonoTypeEnum simple_type;
4911 #if SIZEOF_VOID_P == SIZEOF_REGISTER
4912 int stack_slot_size = MONO_ABI_SIZEOF (gpointer);
4913 int stack_slot_align = MONO_ABI_ALIGNOF (gpointer);
4914 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
4915 int stack_slot_size = SIZEOF_REGISTER;
4916 int stack_slot_align = SIZEOF_REGISTER;
4919 g_assert (t != NULL);
4925 *align = stack_slot_align;
4926 return stack_slot_size;
4929 simple_type = t->type;
4930 switch (simple_type) {
4931 case MONO_TYPE_BOOLEAN:
4932 case MONO_TYPE_CHAR:
4941 case MONO_TYPE_STRING:
4942 case MONO_TYPE_OBJECT:
4943 case MONO_TYPE_CLASS:
4944 case MONO_TYPE_SZARRAY:
4946 case MONO_TYPE_FNPTR:
4947 case MONO_TYPE_ARRAY:
4948 *align = stack_slot_align;
4949 return stack_slot_size;
4951 case MONO_TYPE_MVAR:
4952 g_assert (allow_open);
4953 if (!t->data.generic_param->gshared_constraint || t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE) {
4954 *align = stack_slot_align;
4955 return stack_slot_size;
4957 /* The gparam can only match types given by gshared_constraint */
4958 return mono_type_stack_size_internal (t->data.generic_param->gshared_constraint, align, allow_open);
4960 case MONO_TYPE_TYPEDBYREF:
4961 *align = stack_slot_align;
4962 return stack_slot_size * 3;
4964 *align = MONO_ABI_ALIGNOF (float);
4965 return sizeof (float);
4968 *align = MONO_ABI_ALIGNOF (gint64);
4969 return sizeof (gint64);
4971 *align = MONO_ABI_ALIGNOF (double);
4972 return sizeof (double);
4973 case MONO_TYPE_VALUETYPE: {
4976 if (t->data.klass->enumtype)
4977 return mono_type_stack_size_internal (mono_class_enum_basetype (t->data.klass), align, allow_open);
4979 size = mono_class_value_size (t->data.klass, (guint32*)align);
4981 *align = *align + stack_slot_align - 1;
4982 *align &= ~(stack_slot_align - 1);
4984 size += stack_slot_size - 1;
4985 size &= ~(stack_slot_size - 1);
4990 case MONO_TYPE_GENERICINST: {
4991 MonoGenericClass *gclass = t->data.generic_class;
4992 MonoClass *container_class = gclass->container_class;
4995 g_assert (!gclass->context.class_inst->is_open);
4997 if (container_class->valuetype) {
4998 if (container_class->enumtype)
4999 return mono_type_stack_size_internal (mono_class_enum_basetype (container_class), align, allow_open);
5001 guint32 size = mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
5003 *align = *align + stack_slot_align - 1;
5004 *align &= ~(stack_slot_align - 1);
5006 size += stack_slot_size - 1;
5007 size &= ~(stack_slot_size - 1);
5012 *align = stack_slot_align;
5013 return stack_slot_size;
5017 g_error ("type 0x%02x unknown", t->type);
5023 mono_type_generic_inst_is_valuetype (MonoType *type)
5025 g_assert (type->type == MONO_TYPE_GENERICINST);
5026 return type->data.generic_class->container_class->valuetype;
5030 * mono_metadata_generic_class_is_valuetype:
5033 mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
5035 return gclass->container_class->valuetype;
5039 _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
5041 MonoGenericInst *i1 = g1->context.class_inst;
5042 MonoGenericInst *i2 = g2->context.class_inst;
5044 if (g1->is_dynamic != g2->is_dynamic)
5046 if (!mono_metadata_class_equal (g1->container_class, g2->container_class, signature_only))
5048 if (!mono_generic_inst_equal_full (i1, i2, signature_only))
5050 return g1->is_tb_open == g2->is_tb_open;
5054 _mono_metadata_generic_class_container_equal (const MonoGenericClass *g1, MonoClass *c2, gboolean signature_only)
5056 MonoGenericInst *i1 = g1->context.class_inst;
5057 MonoGenericInst *i2 = mono_class_get_generic_container (c2)->context.class_inst;
5059 if (!mono_metadata_class_equal (g1->container_class, c2, signature_only))
5061 if (!mono_generic_inst_equal_full (i1, i2, signature_only))
5063 return !g1->is_tb_open;
5067 mono_metadata_generic_context_hash (const MonoGenericContext *context)
5069 /* FIXME: check if this seed is good enough */
5070 guint hash = 0xc01dfee7;
5071 if (context->class_inst)
5072 hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->class_inst);
5073 if (context->method_inst)
5074 hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->method_inst);
5079 mono_metadata_generic_context_equal (const MonoGenericContext *g1, const MonoGenericContext *g2)
5081 return g1->class_inst == g2->class_inst && g1->method_inst == g2->method_inst;
5085 * mono_metadata_str_hash:
5087 * This should be used instead of g_str_hash for computing hash codes visible
5088 * outside this module, since g_str_hash () is not guaranteed to be stable
5089 * (its not the same in eglib for example).
5092 mono_metadata_str_hash (gconstpointer v1)
5094 /* Same as g_str_hash () in glib */
5095 char *p = (char *) v1;
5100 hash = (hash << 5) - hash + *p;
5107 * mono_metadata_type_hash:
5109 * Computes a hash value for \p t1 to be used in \c GHashTable.
5110 * The returned hash is guaranteed to be the same across executions.
5113 mono_metadata_type_hash (MonoType *t1)
5115 guint hash = t1->type;
5117 hash |= t1->byref << 6; /* do not collide with t1->type values */
5119 case MONO_TYPE_VALUETYPE:
5120 case MONO_TYPE_CLASS:
5121 case MONO_TYPE_SZARRAY: {
5122 MonoClass *klass = t1->data.klass;
5124 * Dynamic classes must not be hashed on their type since it can change
5125 * during runtime. For example, if we hash a reference type that is
5126 * later made into a valuetype.
5128 * This is specially problematic with generic instances since they are
5129 * inserted in a bunch of hash tables before been finished.
5131 if (image_is_dynamic (klass->image))
5132 return (t1->byref << 6) | mono_metadata_str_hash (klass->name);
5133 return ((hash << 5) - hash) ^ mono_metadata_str_hash (klass->name);
5136 return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
5137 case MONO_TYPE_ARRAY:
5138 return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
5139 case MONO_TYPE_GENERICINST:
5140 return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
5142 case MONO_TYPE_MVAR:
5143 return ((hash << 5) - hash) ^ mono_metadata_generic_param_hash (t1->data.generic_param);
5150 mono_metadata_generic_param_hash (MonoGenericParam *p)
5153 MonoGenericParamInfo *info;
5155 hash = (mono_generic_param_num (p) << 2);
5156 if (p->gshared_constraint)
5157 hash = ((hash << 5) - hash) ^ mono_metadata_type_hash (p->gshared_constraint);
5158 info = mono_generic_param_info (p);
5159 /* Can't hash on the owner klass/method, since those might not be set when this is called */
5161 hash = ((hash << 5) - hash) ^ info->token;
5166 mono_metadata_generic_param_equal_internal (MonoGenericParam *p1, MonoGenericParam *p2, gboolean signature_only)
5170 if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
5172 if (p1->gshared_constraint && p2->gshared_constraint) {
5173 if (!mono_metadata_type_equal (p1->gshared_constraint, p2->gshared_constraint))
5176 if (p1->gshared_constraint != p2->gshared_constraint)
5181 * We have to compare the image as well because if we didn't,
5182 * the generic_inst_cache lookup wouldn't care about the image
5183 * of generic params, so what could happen is that a generic
5184 * inst with params from image A is put into the cache, then
5185 * image B gets that generic inst from the cache, image A is
5186 * unloaded, so the inst is deleted, but image B still retains
5189 if (mono_generic_param_owner (p1) == mono_generic_param_owner (p2))
5193 * If `signature_only' is true, we're comparing two (method) signatures.
5194 * In this case, the owner of two type parameters doesn't need to match.
5197 return signature_only;
5201 mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2)
5203 return mono_metadata_generic_param_equal_internal (p1, p2, TRUE);
5207 mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only)
5211 if (mono_class_is_ginst (c1) && mono_class_is_ginst (c2))
5212 return _mono_metadata_generic_class_equal (mono_class_get_generic_class (c1), mono_class_get_generic_class (c2), signature_only);
5213 if (mono_class_is_ginst (c1) && mono_class_is_gtd (c2))
5214 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c1), c2, signature_only);
5215 if (mono_class_is_gtd (c1) && mono_class_is_ginst (c2))
5216 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c2), c1, signature_only);
5217 if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
5218 return mono_metadata_generic_param_equal_internal (
5219 c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
5220 if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR))
5221 return mono_metadata_generic_param_equal_internal (
5222 c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
5223 if (signature_only &&
5224 (c1->byval_arg.type == MONO_TYPE_SZARRAY) && (c2->byval_arg.type == MONO_TYPE_SZARRAY))
5225 return mono_metadata_class_equal (c1->byval_arg.data.klass, c2->byval_arg.data.klass, signature_only);
5226 if (signature_only &&
5227 (c1->byval_arg.type == MONO_TYPE_ARRAY) && (c2->byval_arg.type == MONO_TYPE_ARRAY))
5228 return do_mono_metadata_type_equal (&c1->byval_arg, &c2->byval_arg, signature_only);
5233 mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only)
5235 gpointer iter1 = 0, iter2 = 0;
5239 if (s1->call_convention != s2->call_convention)
5241 if (s1->sentinelpos != s2->sentinelpos)
5243 if (s1->hasthis != s2->hasthis)
5245 if (s1->explicit_this != s2->explicit_this)
5247 if (! do_mono_metadata_type_equal (s1->ret, s2->ret, signature_only))
5249 if (s1->param_count != s2->param_count)
5253 MonoType *t1 = mono_signature_get_params (s1, &iter1);
5254 MonoType *t2 = mono_signature_get_params (s2, &iter2);
5256 if (t1 == NULL || t2 == NULL)
5258 if (! do_mono_metadata_type_equal (t1, t2, signature_only))
5264 * mono_metadata_type_equal:
5267 * @signature_only: If true, treat ginsts as equal which are instantiated separately but have equal positional value
5269 * Determine if @t1 and @t2 represent the same type.
5270 * Returns: #TRUE if @t1 and @t2 are equal.
5273 do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only)
5275 if (t1->type != t2->type || t1->byref != t2->byref)
5279 case MONO_TYPE_VOID:
5280 case MONO_TYPE_BOOLEAN:
5281 case MONO_TYPE_CHAR:
5292 case MONO_TYPE_STRING:
5295 case MONO_TYPE_OBJECT:
5296 case MONO_TYPE_TYPEDBYREF:
5298 case MONO_TYPE_VALUETYPE:
5299 case MONO_TYPE_CLASS:
5300 case MONO_TYPE_SZARRAY:
5301 return mono_metadata_class_equal (t1->data.klass, t2->data.klass, signature_only);
5303 return do_mono_metadata_type_equal (t1->data.type, t2->data.type, signature_only);
5304 case MONO_TYPE_ARRAY:
5305 if (t1->data.array->rank != t2->data.array->rank)
5307 return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass, signature_only);
5308 case MONO_TYPE_GENERICINST:
5309 return _mono_metadata_generic_class_equal (
5310 t1->data.generic_class, t2->data.generic_class, signature_only);
5312 return mono_metadata_generic_param_equal_internal (
5313 t1->data.generic_param, t2->data.generic_param, signature_only);
5314 case MONO_TYPE_MVAR:
5315 return mono_metadata_generic_param_equal_internal (
5316 t1->data.generic_param, t2->data.generic_param, signature_only);
5317 case MONO_TYPE_FNPTR:
5318 return mono_metadata_fnptr_equal (t1->data.method, t2->data.method, signature_only);
5320 g_error ("implement type compare for %0x!", t1->type);
5328 * mono_metadata_type_equal:
5331 mono_metadata_type_equal (MonoType *t1, MonoType *t2)
5333 return do_mono_metadata_type_equal (t1, t2, FALSE);
5337 * mono_metadata_type_equal_full:
5339 * \param t2 another type
5340 * \param signature_only if signature only comparison should be made
5342 * Determine if \p t1 and \p t2 are signature compatible if \p signature_only is TRUE, otherwise
5343 * behaves the same way as mono_metadata_type_equal.
5344 * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
5345 * \returns TRUE if \p t1 and \p t2 are equal taking \p signature_only into account.
5348 mono_metadata_type_equal_full (MonoType *t1, MonoType *t2, gboolean signature_only)
5350 return do_mono_metadata_type_equal (t1, t2, signature_only);
5354 * mono_metadata_signature_equal:
5355 * \param sig1 a signature
5356 * \param sig2 another signature
5358 * Determine if \p sig1 and \p sig2 represent the same signature, with the
5359 * same number of arguments and the same types.
5360 * \returns TRUE if \p sig1 and \p sig2 are equal.
5363 mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
5367 if (sig1->hasthis != sig2->hasthis || sig1->param_count != sig2->param_count)
5370 if (sig1->generic_param_count != sig2->generic_param_count)
5374 * We're just comparing the signatures of two methods here:
5376 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
5377 * U and V are equal here.
5379 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
5382 for (i = 0; i < sig1->param_count; i++) {
5383 MonoType *p1 = sig1->params[i];
5384 MonoType *p2 = sig2->params[i];
5386 /* if (p1->attrs != p2->attrs)
5389 if (!do_mono_metadata_type_equal (p1, p2, TRUE))
5393 if (!do_mono_metadata_type_equal (sig1->ret, sig2->ret, TRUE))
5399 * mono_metadata_type_dup:
5400 * \param image image to alloc memory from
5401 * \param original type to duplicate
5402 * \returns copy of type allocated from the image's mempool (or from the heap, if \p image is null).
5405 mono_metadata_type_dup (MonoImage *image, const MonoType *o)
5408 int sizeof_o = MONO_SIZEOF_TYPE;
5410 sizeof_o += o->num_mods * sizeof (MonoCustomMod);
5412 r = image ? (MonoType *)mono_image_alloc0 (image, sizeof_o) : (MonoType *)g_malloc (sizeof_o);
5414 memcpy (r, o, sizeof_o);
5416 if (o->type == MONO_TYPE_PTR) {
5417 r->data.type = mono_metadata_type_dup (image, o->data.type);
5418 } else if (o->type == MONO_TYPE_ARRAY) {
5419 r->data.array = mono_dup_array_type (image, o->data.array);
5420 } else if (o->type == MONO_TYPE_FNPTR) {
5421 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
5422 r->data.method = mono_metadata_signature_deep_dup (image, o->data.method);
5428 * mono_signature_hash:
5431 mono_signature_hash (MonoMethodSignature *sig)
5433 guint i, res = sig->ret->type;
5435 for (i = 0; i < sig->param_count; i++)
5436 res = (res << 5) - res + mono_type_hash (sig->params[i]);
5442 * mono_metadata_encode_value:
5443 * @value: value to encode
5444 * @buf: buffer where to write the compressed representation
5445 * @endbuf: pointer updated to point at the end of the encoded output
5447 * Encodes the value @value in the compressed representation used
5448 * in metadata and stores the result in @buf. @buf needs to be big
5449 * enough to hold the data (4 bytes).
5452 mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
5458 else if (value < 0x4000) {
5459 p [0] = 0x80 | (value >> 8);
5460 p [1] = value & 0xff;
5463 p [0] = (value >> 24) | 0xc0;
5464 p [1] = (value >> 16) & 0xff;
5465 p [2] = (value >> 8) & 0xff;
5466 p [3] = value & 0xff;
5474 * mono_metadata_field_info:
5475 * \param meta the Image the field is defined in
5476 * \param index the index in the field table representing the field
5477 * \param offset a pointer to an integer where to store the offset that may have been specified for the field in a FieldLayout table
5478 * \param rva a pointer to the RVA of the field data in the image that may have been defined in a \c FieldRVA table
5479 * \param marshal_spec a pointer to the marshal spec that may have been defined for the field in a \c FieldMarshal table.
5481 * Gather info for field \p index that may have been defined in the \c FieldLayout,
5482 * \c FieldRVA and \c FieldMarshal tables.
5483 * Either of \p offset, \p rva and \p marshal_spec can be NULL if you're not interested
5487 mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
5488 MonoMarshalSpec **marshal_spec)
5490 mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, FALSE);
5494 mono_metadata_field_info_with_mempool (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
5495 MonoMarshalSpec **marshal_spec)
5497 mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, TRUE);
5501 mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
5502 MonoMarshalSpec **marshal_spec, gboolean alloc_from_image)
5504 MonoTableInfo *tdef;
5507 loc.idx = index + 1;
5508 if (meta->uncompressed_metadata)
5509 loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
5512 tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
5514 loc.col_idx = MONO_FIELD_LAYOUT_FIELD;
5517 if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
5518 *offset = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_LAYOUT_OFFSET);
5520 *offset = (guint32)-1;
5524 tdef = &meta->tables [MONO_TABLE_FIELDRVA];
5526 loc.col_idx = MONO_FIELD_RVA_FIELD;
5529 if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
5531 * LAMESPEC: There is no signature, no nothing, just the raw data.
5533 *rva = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_RVA_RVA);
5541 if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
5542 *marshal_spec = mono_metadata_parse_marshal_spec_full (alloc_from_image ? meta : NULL, meta, p);
5549 * mono_metadata_get_constant_index:
5550 * \param meta the Image the field is defined in
5551 * \param index the token that may have a row defined in the constants table
5552 * \param hint possible position for the row
5554 * \p token must be a \c FieldDef, \c ParamDef or \c PropertyDef token.
5556 * \returns the index into the \c Constants table or 0 if not found.
5559 mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
5561 MonoTableInfo *tdef;
5563 guint32 index = mono_metadata_token_index (token);
5565 tdef = &meta->tables [MONO_TABLE_CONSTANT];
5566 index <<= MONO_HASCONSTANT_BITS;
5567 switch (mono_metadata_token_table (token)) {
5568 case MONO_TABLE_FIELD:
5569 index |= MONO_HASCONSTANT_FIEDDEF;
5571 case MONO_TABLE_PARAM:
5572 index |= MONO_HASCONSTANT_PARAM;
5574 case MONO_TABLE_PROPERTY:
5575 index |= MONO_HASCONSTANT_PROPERTY;
5578 g_warning ("Not a valid token for the constant table: 0x%08x", token);
5582 loc.col_idx = MONO_CONSTANT_PARENT;
5585 /* FIXME: Index translation */
5587 if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
5590 if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
5591 return loc.result + 1;
5597 * mono_metadata_events_from_typedef:
5598 * \param meta metadata context
5599 * \param index 0-based index (in the \c TypeDef table) describing a type
5600 * \returns the 0-based index in the \c Event table for the events in the
5601 * type. The last event that belongs to the type (plus 1) is stored
5602 * in the \p end_idx pointer.
5605 mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
5609 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_EVENTMAP];
5617 loc.col_idx = MONO_EVENT_MAP_PARENT;
5618 loc.idx = index + 1;
5620 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5623 start = mono_metadata_decode_row_col (tdef, loc.result, MONO_EVENT_MAP_EVENTLIST);
5624 if (loc.result + 1 < tdef->rows) {
5625 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_EVENT_MAP_EVENTLIST) - 1;
5627 end = meta->tables [MONO_TABLE_EVENT].rows;
5635 * mono_metadata_methods_from_event:
5636 * \param meta metadata context
5637 * \param index 0-based index (in the \c Event table) describing a event
5638 * \returns the 0-based index in the \c MethodDef table for the methods in the
5639 * event. The last method that belongs to the event (plus 1) is stored
5640 * in the \p end_idx pointer.
5643 mono_metadata_methods_from_event (MonoImage *meta, guint32 index, guint *end_idx)
5647 guint32 cols [MONO_METHOD_SEMA_SIZE];
5648 MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
5654 if (meta->uncompressed_metadata)
5655 index = search_ptr_table (meta, MONO_TABLE_EVENT_POINTER, index + 1) - 1;
5658 loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
5659 loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
5661 if (!mono_binary_search (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
5666 * We may end up in the middle of the rows...
5669 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
5675 while (end < msemt->rows) {
5676 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
5677 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
5686 * mono_metadata_properties_from_typedef:
5687 * \param meta metadata context
5688 * \param index 0-based index (in the \c TypeDef table) describing a type
5689 * \returns the 0-based index in the \c Property table for the properties in the
5690 * type. The last property that belongs to the type (plus 1) is stored
5691 * in the \p end_idx pointer.
5694 mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
5698 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_PROPERTYMAP];
5706 loc.col_idx = MONO_PROPERTY_MAP_PARENT;
5707 loc.idx = index + 1;
5709 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5712 start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST);
5713 if (loc.result + 1 < tdef->rows) {
5714 end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_PROPERTY_MAP_PROPERTY_LIST) - 1;
5716 end = meta->tables [MONO_TABLE_PROPERTY].rows;
5724 * mono_metadata_methods_from_property:
5725 * \param meta metadata context
5726 * \param index 0-based index (in the \c PropertyDef table) describing a property
5727 * \returns the 0-based index in the \c MethodDef table for the methods in the
5728 * property. The last method that belongs to the property (plus 1) is stored
5729 * in the \p end_idx pointer.
5732 mono_metadata_methods_from_property (MonoImage *meta, guint32 index, guint *end_idx)
5736 guint32 cols [MONO_METHOD_SEMA_SIZE];
5737 MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
5743 if (meta->uncompressed_metadata)
5744 index = search_ptr_table (meta, MONO_TABLE_PROPERTY_POINTER, index + 1) - 1;
5747 loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
5748 loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
5750 if (!mono_binary_search (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
5755 * We may end up in the middle of the rows...
5758 if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
5764 while (end < msemt->rows) {
5765 mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
5766 if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
5775 * mono_metadata_implmap_from_method:
5778 mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
5781 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_IMPLMAP];
5786 /* No index translation seems to be needed */
5789 loc.col_idx = MONO_IMPLMAP_MEMBER;
5790 loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
5792 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5795 return loc.result + 1;
5799 * mono_type_create_from_typespec:
5800 * \param image context where the image is created
5801 * \param type_spec typespec token
5802 * \deprecated use \c mono_type_create_from_typespec_checked that has proper error handling
5804 * Creates a \c MonoType representing the \c TypeSpec indexed by the \p type_spec
5808 mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
5811 MonoType *type = mono_type_create_from_typespec_checked (image, type_spec, &error);
5813 g_error ("Could not create typespec %x due to %s", type_spec, mono_error_get_message (&error));
5818 mono_type_create_from_typespec_checked (MonoImage *image, guint32 type_spec, MonoError *error)
5821 guint32 idx = mono_metadata_token_index (type_spec);
5823 guint32 cols [MONO_TYPESPEC_SIZE];
5825 MonoType *type, *type2;
5829 type = (MonoType *)mono_conc_hashtable_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
5833 t = &image->tables [MONO_TABLE_TYPESPEC];
5835 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
5836 ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
5838 if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], type_spec, NULL)) {
5839 mono_error_set_bad_image (error, image, "Could not verify type spec %08x.", type_spec);
5843 mono_metadata_decode_value (ptr, &ptr);
5845 type = mono_metadata_parse_type_checked (image, NULL, 0, TRUE, ptr, &ptr, error);
5849 type2 = mono_metadata_type_dup (image, type);
5850 mono_metadata_free_type (type);
5852 mono_image_lock (image);
5854 /* We might leak some data in the image mempool if found */
5855 type = mono_conc_hashtable_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
5859 mono_image_unlock (image);
5866 mono_image_strndup (MonoImage *image, const char *data, guint len)
5870 return g_strndup (data, len);
5871 res = (char *)mono_image_alloc (image, len + 1);
5872 memcpy (res, data, len);
5878 * mono_metadata_parse_marshal_spec:
5881 mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
5883 return mono_metadata_parse_marshal_spec_full (NULL, image, ptr);
5887 * If IMAGE is non-null, memory will be allocated from its mempool, otherwise it will be allocated using malloc.
5888 * PARENT_IMAGE is the image containing the marshal spec.
5891 mono_metadata_parse_marshal_spec_full (MonoImage *image, MonoImage *parent_image, const char *ptr)
5893 MonoMarshalSpec *res;
5895 const char *start = ptr;
5897 /* fixme: this is incomplete, but I cant find more infos in the specs */
5900 res = (MonoMarshalSpec *)mono_image_alloc0 (image, sizeof (MonoMarshalSpec));
5902 res = g_new0 (MonoMarshalSpec, 1);
5904 len = mono_metadata_decode_value (ptr, &ptr);
5905 res->native = (MonoMarshalNative)*ptr++;
5907 if (res->native == MONO_NATIVE_LPARRAY) {
5908 res->data.array_data.param_num = -1;
5909 res->data.array_data.num_elem = -1;
5910 res->data.array_data.elem_mult = -1;
5912 if (ptr - start <= len)
5913 res->data.array_data.elem_type = (MonoMarshalNative)*ptr++;
5914 if (ptr - start <= len)
5915 res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr);
5916 if (ptr - start <= len)
5917 res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5918 if (ptr - start <= len) {
5920 * LAMESPEC: Older spec versions say this parameter comes before
5921 * num_elem. Never spec versions don't talk about elem_mult at
5922 * all, but csc still emits it, and it is used to distinguish
5923 * between param_num being 0, and param_num being omitted.
5924 * So if (param_num == 0) && (num_elem > 0), then
5925 * elem_mult == 0 -> the array size is num_elem
5926 * elem_mult == 1 -> the array size is @param_num + num_elem
5928 res->data.array_data.elem_mult = mono_metadata_decode_value (ptr, &ptr);
5932 if (res->native == MONO_NATIVE_BYVALTSTR) {
5933 if (ptr - start <= len)
5934 res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5937 if (res->native == MONO_NATIVE_BYVALARRAY) {
5938 if (ptr - start <= len)
5939 res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5942 if (res->native == MONO_NATIVE_CUSTOM) {
5943 /* skip unused type guid */
5944 len = mono_metadata_decode_value (ptr, &ptr);
5946 /* skip unused native type name */
5947 len = mono_metadata_decode_value (ptr, &ptr);
5949 /* read custom marshaler type name */
5950 len = mono_metadata_decode_value (ptr, &ptr);
5951 res->data.custom_data.custom_name = mono_image_strndup (image, ptr, len);
5953 /* read cookie string */
5954 len = mono_metadata_decode_value (ptr, &ptr);
5955 res->data.custom_data.cookie = mono_image_strndup (image, ptr, len);
5956 res->data.custom_data.image = parent_image;
5959 if (res->native == MONO_NATIVE_SAFEARRAY) {
5960 res->data.safearray_data.elem_type = (MonoMarshalVariant)0;
5961 res->data.safearray_data.num_elem = 0;
5962 if (ptr - start <= len)
5963 res->data.safearray_data.elem_type = (MonoMarshalVariant)*ptr++;
5964 if (ptr - start <= len)
5965 res->data.safearray_data.num_elem = *ptr++;
5971 * mono_metadata_free_marshal_spec:
5974 mono_metadata_free_marshal_spec (MonoMarshalSpec *spec)
5976 if (spec->native == MONO_NATIVE_CUSTOM) {
5977 g_free (spec->data.custom_data.custom_name);
5978 g_free (spec->data.custom_data.cookie);
5984 * mono_type_to_unmanaged:
5985 * The value pointed to by \p conv will contain the kind of marshalling required for this
5986 * particular type one of the \c MONO_MARSHAL_CONV_ enumeration values.
5987 * \returns A \c MonoMarshalNative enumeration value (<code>MONO_NATIVE_</code>) value
5988 * describing the underlying native reprensetation of the type.
5991 mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_field,
5992 gboolean unicode, MonoMarshalConv *conv)
5994 MonoMarshalConv dummy_conv;
6000 *conv = MONO_MARSHAL_CONV_NONE;
6003 return MONO_NATIVE_UINT;
6007 case MONO_TYPE_BOOLEAN:
6009 switch (mspec->native) {
6010 case MONO_NATIVE_VARIANTBOOL:
6011 *conv = MONO_MARSHAL_CONV_BOOL_VARIANTBOOL;
6012 return MONO_NATIVE_VARIANTBOOL;
6013 case MONO_NATIVE_BOOLEAN:
6014 *conv = MONO_MARSHAL_CONV_BOOL_I4;
6015 return MONO_NATIVE_BOOLEAN;
6016 case MONO_NATIVE_I1:
6017 case MONO_NATIVE_U1:
6018 return mspec->native;
6020 g_error ("cant marshal bool to native type %02x", mspec->native);
6023 *conv = MONO_MARSHAL_CONV_BOOL_I4;
6024 return MONO_NATIVE_BOOLEAN;
6025 case MONO_TYPE_CHAR:
6027 switch (mspec->native) {
6028 case MONO_NATIVE_U2:
6029 case MONO_NATIVE_U1:
6030 return mspec->native;
6032 g_error ("cant marshal char to native type %02x", mspec->native);
6035 return unicode ? MONO_NATIVE_U2 : MONO_NATIVE_U1;
6036 case MONO_TYPE_I1: return MONO_NATIVE_I1;
6037 case MONO_TYPE_U1: return MONO_NATIVE_U1;
6038 case MONO_TYPE_I2: return MONO_NATIVE_I2;
6039 case MONO_TYPE_U2: return MONO_NATIVE_U2;
6040 case MONO_TYPE_I4: return MONO_NATIVE_I4;
6041 case MONO_TYPE_U4: return MONO_NATIVE_U4;
6042 case MONO_TYPE_I8: return MONO_NATIVE_I8;
6043 case MONO_TYPE_U8: return MONO_NATIVE_U8;
6044 case MONO_TYPE_R4: return MONO_NATIVE_R4;
6045 case MONO_TYPE_R8: return MONO_NATIVE_R8;
6046 case MONO_TYPE_STRING:
6048 switch (mspec->native) {
6049 case MONO_NATIVE_BSTR:
6050 *conv = MONO_MARSHAL_CONV_STR_BSTR;
6051 return MONO_NATIVE_BSTR;
6052 case MONO_NATIVE_LPSTR:
6053 *conv = MONO_MARSHAL_CONV_STR_LPSTR;
6054 return MONO_NATIVE_LPSTR;
6055 case MONO_NATIVE_LPWSTR:
6056 *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
6057 return MONO_NATIVE_LPWSTR;
6058 case MONO_NATIVE_LPTSTR:
6059 *conv = MONO_MARSHAL_CONV_STR_LPTSTR;
6060 return MONO_NATIVE_LPTSTR;
6061 case MONO_NATIVE_ANSIBSTR:
6062 *conv = MONO_MARSHAL_CONV_STR_ANSIBSTR;
6063 return MONO_NATIVE_ANSIBSTR;
6064 case MONO_NATIVE_TBSTR:
6065 *conv = MONO_MARSHAL_CONV_STR_TBSTR;
6066 return MONO_NATIVE_TBSTR;
6067 case MONO_NATIVE_UTF8STR:
6068 *conv = MONO_MARSHAL_CONV_STR_UTF8STR;
6069 return MONO_NATIVE_UTF8STR;
6070 case MONO_NATIVE_BYVALTSTR:
6072 *conv = MONO_MARSHAL_CONV_STR_BYVALWSTR;
6074 *conv = MONO_MARSHAL_CONV_STR_BYVALSTR;
6075 return MONO_NATIVE_BYVALTSTR;
6077 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);
6081 *conv = MONO_MARSHAL_CONV_STR_LPWSTR;
6082 return MONO_NATIVE_LPWSTR;
6085 *conv = MONO_MARSHAL_CONV_STR_LPSTR;
6086 return MONO_NATIVE_LPSTR;
6088 case MONO_TYPE_PTR: return MONO_NATIVE_UINT;
6089 case MONO_TYPE_VALUETYPE: /*FIXME*/
6090 if (type->data.klass->enumtype) {
6091 t = mono_class_enum_basetype (type->data.klass)->type;
6094 if (type->data.klass == mono_defaults.handleref_class){
6095 *conv = MONO_MARSHAL_CONV_HANDLEREF;
6096 return MONO_NATIVE_INT;
6098 return MONO_NATIVE_STRUCT;
6099 case MONO_TYPE_SZARRAY:
6100 case MONO_TYPE_ARRAY:
6102 switch (mspec->native) {
6103 case MONO_NATIVE_BYVALARRAY:
6104 if ((type->data.klass->element_class == mono_defaults.char_class) && !unicode)
6105 *conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY;
6107 *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
6108 return MONO_NATIVE_BYVALARRAY;
6109 case MONO_NATIVE_SAFEARRAY:
6110 *conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY;
6111 return MONO_NATIVE_SAFEARRAY;
6112 case MONO_NATIVE_LPARRAY:
6113 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
6114 return MONO_NATIVE_LPARRAY;
6116 g_error ("cant marshal array as native type %02x", mspec->native);
6120 *conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
6121 return MONO_NATIVE_LPARRAY;
6122 case MONO_TYPE_I: return MONO_NATIVE_INT;
6123 case MONO_TYPE_U: return MONO_NATIVE_UINT;
6124 case MONO_TYPE_CLASS:
6125 case MONO_TYPE_OBJECT: {
6126 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
6128 switch (mspec->native) {
6129 case MONO_NATIVE_STRUCT:
6130 return MONO_NATIVE_STRUCT;
6131 case MONO_NATIVE_CUSTOM:
6132 return MONO_NATIVE_CUSTOM;
6133 case MONO_NATIVE_INTERFACE:
6134 *conv = MONO_MARSHAL_CONV_OBJECT_INTERFACE;
6135 return MONO_NATIVE_INTERFACE;
6136 case MONO_NATIVE_IDISPATCH:
6137 *conv = MONO_MARSHAL_CONV_OBJECT_IDISPATCH;
6138 return MONO_NATIVE_IDISPATCH;
6139 case MONO_NATIVE_IUNKNOWN:
6140 *conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN;
6141 return MONO_NATIVE_IUNKNOWN;
6142 case MONO_NATIVE_FUNC:
6143 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
6144 type->data.klass == mono_defaults.delegate_class ||
6145 type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
6146 *conv = MONO_MARSHAL_CONV_DEL_FTN;
6147 return MONO_NATIVE_FUNC;
6151 g_error ("cant marshal object as native type %02x", mspec->native);
6154 if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
6155 type->data.klass == mono_defaults.delegate_class ||
6156 type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
6157 *conv = MONO_MARSHAL_CONV_DEL_FTN;
6158 return MONO_NATIVE_FUNC;
6160 if (mono_class_try_get_safehandle_class () && type->data.klass == mono_class_try_get_safehandle_class ()){
6161 *conv = MONO_MARSHAL_CONV_SAFEHANDLE;
6162 return MONO_NATIVE_INT;
6164 *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT;
6165 return MONO_NATIVE_STRUCT;
6167 case MONO_TYPE_FNPTR: return MONO_NATIVE_FUNC;
6168 case MONO_TYPE_GENERICINST:
6169 type = &type->data.generic_class->container_class->byval_arg;
6172 case MONO_TYPE_TYPEDBYREF:
6174 g_error ("type 0x%02x not handled in marshal", t);
6176 return MONO_NATIVE_MAX;
6180 * mono_metadata_get_marshal_info:
6183 mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
6186 MonoTableInfo *tdef = &meta->tables [MONO_TABLE_FIELDMARSHAL];
6192 loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
6193 loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
6195 /* FIXME: Index translation */
6197 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
6200 return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
6204 method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context, MonoError *error)
6206 MonoMethod *result = NULL;
6207 guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
6211 switch (tok & MONO_METHODDEFORREF_MASK) {
6212 case MONO_METHODDEFORREF_METHODDEF:
6213 result = mono_get_method_checked (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context, error);
6215 case MONO_METHODDEFORREF_METHODREF:
6216 result = mono_get_method_checked (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context, error);
6219 mono_error_set_bad_image (error, m, "Invalid MethodDefOfRef token %x", tok);
6226 * mono_class_get_overrides_full:
6228 * Return the method overrides belonging to class @type_token in @overrides, and
6229 * the number of overrides in @num_overrides.
6231 * Returns: TRUE on success, FALSE on failure.
6234 mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides,
6235 MonoGenericContext *generic_context)
6239 MonoTableInfo *tdef = &image->tables [MONO_TABLE_METHODIMPL];
6242 guint32 cols [MONO_METHODIMPL_SIZE];
6243 MonoMethod **result;
6254 loc.col_idx = MONO_METHODIMPL_CLASS;
6255 loc.idx = mono_metadata_token_index (type_token);
6257 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
6263 * We may end up in the middle of the rows...
6266 if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_METHODIMPL_CLASS))
6271 while (end < tdef->rows) {
6272 if (loc.idx == mono_metadata_decode_row_col (tdef, end, MONO_METHODIMPL_CLASS))
6278 result = g_new (MonoMethod*, num * 2);
6279 for (i = 0; i < num; ++i) {
6282 if (!mono_verifier_verify_methodimpl_row (image, start + i, &error)) {
6283 mono_error_cleanup (&error); /* FIXME don't swallow the error */
6288 mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
6289 method = method_from_method_def_or_ref (
6290 image, cols [MONO_METHODIMPL_DECLARATION], generic_context, &error);
6291 if (method == NULL) {
6292 mono_error_cleanup (&error); /* FIXME don't swallow the error */
6295 result [i * 2] = method;
6296 method = method_from_method_def_or_ref (
6297 image, cols [MONO_METHODIMPL_BODY], generic_context, &error);
6298 if (method == NULL) {
6299 mono_error_cleanup (&error); /* FIXME don't swallow the error */
6302 result [i * 2 + 1] = method;
6305 *overrides = result;
6307 *num_overrides = num;
6312 * mono_guid_to_string:
6314 * Converts a 16 byte Microsoft GUID to the standard string representation.
6317 mono_guid_to_string (const guint8 *guid)
6319 return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
6320 guid[3], guid[2], guid[1], guid[0],
6324 guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
6328 * mono_guid_to_string_minimal:
6330 * Converts a 16 byte Microsoft GUID to lower case no '-' representation..
6333 mono_guid_to_string_minimal (const guint8 *guid)
6335 return g_strdup_printf ("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
6336 guid[3], guid[2], guid[1], guid[0],
6340 guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
6343 get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container, MonoError *error)
6345 MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
6346 guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
6347 guint32 i, token, found;
6348 MonoClass *klass, **res;
6349 GSList *cons = NULL, *tmp;
6350 MonoGenericContext *context = &container->context;
6354 *constraints = NULL;
6356 for (i = 0; i < tdef->rows; ++i) {
6357 mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
6358 if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
6359 token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
6360 klass = mono_class_get_and_inflate_typespec_checked (image, token, context, error);
6362 g_slist_free (cons);
6365 cons = g_slist_append (cons, klass);
6368 /* contiguous list finished */
6375 res = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * (found + 1));
6376 for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
6377 res [i] = (MonoClass *)tmp->data;
6379 g_slist_free (cons);
6385 * mono_metadata_get_generic_param_row:
6388 * @token: TypeOrMethodDef token, owner for GenericParam
6389 * @owner: coded token, set on return
6391 * Returns: 1-based row-id in the GenericParam table whose
6392 * owner is @token. 0 if not found.
6395 mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *owner)
6397 MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM];
6404 if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
6405 *owner = MONO_TYPEORMETHOD_TYPE;
6406 else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
6407 *owner = MONO_TYPEORMETHOD_METHOD;
6409 g_error ("wrong token %x to get_generic_param_row", token);
6412 *owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
6415 loc.col_idx = MONO_GENERICPARAM_OWNER;
6418 if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
6421 /* Find the first entry by searching backwards */
6422 while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_GENERICPARAM_OWNER) == loc.idx))
6425 return loc.result + 1;
6429 mono_metadata_has_generic_params (MonoImage *image, guint32 token)
6432 return mono_metadata_get_generic_param_row (image, token, &owner);
6436 * Memory is allocated from IMAGE's mempool.
6439 mono_metadata_load_generic_param_constraints_checked (MonoImage *image, guint32 token,
6440 MonoGenericContainer *container, MonoError *error)
6443 guint32 start_row, i, owner;
6446 if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
6448 for (i = 0; i < container->type_argc; i++) {
6449 if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container, error)) {
6457 * mono_metadata_load_generic_params:
6459 * Load the type parameters from the type or method definition @token.
6461 * Use this method after parsing a type or method definition to figure out whether it's a generic
6462 * type / method. When parsing a method definition, @parent_container points to the generic container
6463 * of the current class, if any.
6465 * Note: This method does not load the constraints: for typedefs, this has to be done after fully
6466 * creating the type.
6468 * Returns: NULL if @token is not a generic type or method definition or the new generic container.
6470 * LOCKING: Acquires the loader lock
6473 MonoGenericContainer *
6474 mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
6476 MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM];
6477 guint32 cols [MONO_GENERICPARAM_SIZE];
6478 guint32 i, owner = 0, n;
6479 MonoGenericContainer *container;
6480 MonoGenericParamFull *params;
6481 MonoGenericContext *context;
6483 if (!(i = mono_metadata_get_generic_param_row (image, token, &owner)))
6485 mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
6488 container = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
6489 container->owner.image = image; // Temporarily mark as anonymous, but this will be overriden by caller
6490 container->is_anonymous = TRUE;
6493 params = (MonoGenericParamFull *)g_realloc (params, sizeof (MonoGenericParamFull) * n);
6494 memset (¶ms [n - 1], 0, sizeof (MonoGenericParamFull));
6495 params [n - 1].param.owner = container;
6496 params [n - 1].param.num = cols [MONO_GENERICPARAM_NUMBER];
6497 params [n - 1].info.token = i | MONO_TOKEN_GENERIC_PARAM;
6498 params [n - 1].info.flags = cols [MONO_GENERICPARAM_FLAGS];
6499 params [n - 1].info.name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
6500 if (params [n - 1].param.num != n - 1)
6501 g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i);
6502 if (++i > tdef->rows)
6504 mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
6505 } while (cols [MONO_GENERICPARAM_OWNER] == owner);
6507 container->type_argc = n;
6508 container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (image, sizeof (MonoGenericParamFull) * n);
6509 memcpy (container->type_params, params, sizeof (MonoGenericParamFull) * n);
6511 container->parent = parent_container;
6513 if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
6514 container->is_method = 1;
6516 g_assert (container->parent == NULL || container->is_method);
6518 context = &container->context;
6519 if (container->is_method) {
6520 context->class_inst = container->parent ? container->parent->context.class_inst : NULL;
6521 context->method_inst = mono_get_shared_generic_inst (container);
6523 context->class_inst = mono_get_shared_generic_inst (container);
6530 mono_get_shared_generic_inst (MonoGenericContainer *container)
6532 MonoType **type_argv;
6534 MonoGenericInst *nginst;
6537 type_argv = g_new0 (MonoType *, container->type_argc);
6538 helper = g_new0 (MonoType, container->type_argc);
6540 for (i = 0; i < container->type_argc; i++) {
6541 MonoType *t = &helper [i];
6543 t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6544 t->data.generic_param = mono_generic_container_get_param (container, i);
6549 nginst = mono_metadata_get_generic_inst (container->type_argc, type_argv);
6558 * mono_type_is_byref:
6559 * \param type the \c MonoType operated on
6560 * \returns TRUE if \p type represents a type passed by reference,
6564 mono_type_is_byref (MonoType *type)
6570 * mono_type_get_type:
6571 * \param type the \c MonoType operated on
6572 * \returns the IL type value for \p type. This is one of the \c MonoTypeEnum
6573 * enum members like \c MONO_TYPE_I4 or \c MONO_TYPE_STRING.
6576 mono_type_get_type (MonoType *type)
6582 * mono_type_get_signature:
6583 * \param type the \c MonoType operated on
6584 * It is only valid to call this function if \p type is a \c MONO_TYPE_FNPTR .
6585 * \returns the \c MonoMethodSignature pointer that describes the signature
6586 * of the function pointer \p type represents.
6588 MonoMethodSignature*
6589 mono_type_get_signature (MonoType *type)
6591 g_assert (type->type == MONO_TYPE_FNPTR);
6592 return type->data.method;
6596 * mono_type_get_class:
6597 * \param type the \c MonoType operated on
6598 * It is only valid to call this function if \p type is a \c MONO_TYPE_CLASS or a
6599 * \c MONO_TYPE_VALUETYPE . For more general functionality, use \c mono_class_from_mono_type,
6601 * \returns the \c MonoClass pointer that describes the class that \p type represents.
6604 mono_type_get_class (MonoType *type)
6606 /* FIXME: review the runtime users before adding the assert here */
6607 return type->data.klass;
6611 * mono_type_get_array_type:
6612 * \param type the \c MonoType operated on
6613 * It is only valid to call this function if \p type is a \c MONO_TYPE_ARRAY .
6614 * \returns a \c MonoArrayType struct describing the array type that \p type
6615 * represents. The info includes details such as rank, array element type
6616 * and the sizes and bounds of multidimensional arrays.
6619 mono_type_get_array_type (MonoType *type)
6621 return type->data.array;
6625 * mono_type_get_ptr_type:
6626 * \pararm type the \c MonoType operated on
6627 * It is only valid to call this function if \p type is a \c MONO_TYPE_PTR .
6628 * \returns the \c MonoType pointer that describes the type that \p type
6629 * represents a pointer to.
6632 mono_type_get_ptr_type (MonoType *type)
6634 g_assert (type->type == MONO_TYPE_PTR);
6635 return type->data.type;
6639 * mono_type_get_modifiers:
6642 mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
6644 /* FIXME: implement */
6649 * mono_type_is_struct:
6650 * \param type the \c MonoType operated on
6651 * \returns TRUE if \p type is a struct, that is a \c ValueType but not an enum
6652 * or a basic type like \c System.Int32 . FALSE otherwise.
6655 mono_type_is_struct (MonoType *type)
6657 return (!type->byref && ((type->type == MONO_TYPE_VALUETYPE &&
6658 !type->data.klass->enumtype) || (type->type == MONO_TYPE_TYPEDBYREF) ||
6659 ((type->type == MONO_TYPE_GENERICINST) &&
6660 mono_metadata_generic_class_is_valuetype (type->data.generic_class) &&
6661 !type->data.generic_class->container_class->enumtype)));
6665 * mono_type_is_void:
6666 * \param type the \c MonoType operated on
6667 * \returns TRUE if \p type is \c System.Void . FALSE otherwise.
6670 mono_type_is_void (MonoType *type)
6672 return (type && (type->type == MONO_TYPE_VOID) && !type->byref);
6676 * mono_type_is_pointer:
6677 * \param type the \c MonoType operated on
6678 * \returns TRUE if \p type is a managed or unmanaged pointer type. FALSE otherwise.
6681 mono_type_is_pointer (MonoType *type)
6683 return (type && ((type->byref || (type->type == MONO_TYPE_I) || type->type == MONO_TYPE_STRING)
6684 || (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
6685 (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_OBJECT) ||
6686 (type->type == MONO_TYPE_ARRAY) || (type->type == MONO_TYPE_PTR) ||
6687 (type->type == MONO_TYPE_FNPTR)));
6691 * mono_type_is_reference:
6692 * \param type the \c MonoType operated on
6693 * \returns TRUE if \p type represents an object reference. FALSE otherwise.
6696 mono_type_is_reference (MonoType *type)
6698 return (type && (((type->type == MONO_TYPE_STRING) ||
6699 (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
6700 (type->type == MONO_TYPE_OBJECT) || (type->type == MONO_TYPE_ARRAY)) ||
6701 ((type->type == MONO_TYPE_GENERICINST) &&
6702 !mono_metadata_generic_class_is_valuetype (type->data.generic_class))));
6706 mono_type_is_generic_parameter (MonoType *type)
6708 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
6712 * mono_signature_get_return_type:
6713 * \param sig the method signature inspected
6714 * \returns the return type of the method signature \p sig
6717 mono_signature_get_return_type (MonoMethodSignature *sig)
6723 * mono_signature_get_params:
6724 * \param sig the method signature inspected
6725 * \param iter pointer to an iterator
6726 * Iterates over the parameters for the method signature \p sig.
6727 * A \c void* pointer must be initialized to NULL to start the iteration
6728 * and its address is passed to this function repeteadly until it returns
6730 * \returns the next parameter type of the method signature \p sig,
6731 * NULL when finished.
6734 mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
6740 /* start from the first */
6741 if (sig->param_count) {
6742 *iter = &sig->params [0];
6743 return sig->params [0];
6749 type = (MonoType **)*iter;
6751 if (type < &sig->params [sig->param_count]) {
6759 * mono_signature_get_param_count:
6760 * \param sig the method signature inspected
6761 * \returns the number of parameters in the method signature \p sig.
6764 mono_signature_get_param_count (MonoMethodSignature *sig)
6766 return sig->param_count;
6770 * mono_signature_get_call_conv:
6771 * \param sig the method signature inspected
6772 * \returns the call convention of the method signature \p sig.
6775 mono_signature_get_call_conv (MonoMethodSignature *sig)
6777 return sig->call_convention;
6781 * mono_signature_vararg_start:
6782 * \param sig the method signature inspected
6783 * \returns the number of the first vararg parameter in the
6784 * method signature \param sig. \c -1 if this is not a vararg signature.
6787 mono_signature_vararg_start (MonoMethodSignature *sig)
6789 return sig->sentinelpos;
6793 * mono_signature_is_instance:
6794 * \param sig the method signature inspected
6795 * \returns TRUE if this the method signature \p sig has an implicit
6796 * first instance argument. FALSE otherwise.
6799 mono_signature_is_instance (MonoMethodSignature *sig)
6801 return sig->hasthis;
6805 * mono_signature_param_is_out
6806 * \param sig the method signature inspected
6807 * \param param_num the 0-based index of the inspected parameter
6808 * \returns TRUE if the parameter is an out parameter, FALSE
6812 mono_signature_param_is_out (MonoMethodSignature *sig, int param_num)
6814 g_assert (param_num >= 0 && param_num < sig->param_count);
6815 return (sig->params [param_num]->attrs & PARAM_ATTRIBUTE_OUT) != 0;
6819 * mono_signature_explicit_this:
6820 * \param sig the method signature inspected
6821 * \returns TRUE if this the method signature \p sig has an explicit
6822 * instance argument. FALSE otherwise.
6825 mono_signature_explicit_this (MonoMethodSignature *sig)
6827 return sig->explicit_this;
6830 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
6832 mono_aligned_addr_hash (gconstpointer ptr)
6834 /* Same hashing we use for objects */
6835 return (GPOINTER_TO_UINT (ptr) >> 3) * 2654435761u;
6839 * If @field belongs to an inflated generic class, return the corresponding field of the
6840 * generic type definition class.
6843 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField *field)
6848 if (!mono_class_is_ginst (field->parent))
6851 gtd = mono_class_get_generic_class (field->parent)->container_class;
6852 offset = field - field->parent->fields;
6853 return gtd->fields + offset;
6857 * If @event belongs to an inflated generic class, return the corresponding event of the
6858 * generic type definition class.
6861 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent *event)
6866 if (!mono_class_is_ginst (event->parent))
6869 gtd = mono_class_get_generic_class (event->parent)->container_class;
6870 offset = event - mono_class_get_event_info (event->parent)->events;
6871 return mono_class_get_event_info (gtd)->events + offset;
6875 * If @property belongs to an inflated generic class, return the corresponding property of the
6876 * generic type definition class.
6879 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty *property)
6881 MonoClassPropertyInfo *info;
6885 if (!mono_class_is_ginst (property->parent))
6888 info = mono_class_get_property_info (property->parent);
6889 gtd = mono_class_get_generic_class (property->parent)->container_class;
6890 offset = property - info->properties;
6891 return mono_class_get_property_info (gtd)->properties + offset;
6895 mono_method_get_wrapper_cache (MonoMethod *method)
6897 if (method->is_inflated) {
6898 MonoMethodInflated *imethod = (MonoMethodInflated *)method;
6899 return &imethod->owner->wrapper_caches;
6901 return &method->klass->image->wrapper_caches;
6905 // 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.
6908 * mono_find_image_set_owner:
6910 * Find the imageset, if any, which a given pointer is located in the memory of.
6913 mono_find_image_set_owner (void *ptr)
6915 MonoImageSet *owner = NULL;
6922 for (i = 0; !owner && i < image_sets->len; ++i) {
6923 MonoImageSet *set = (MonoImageSet *)g_ptr_array_index (image_sets, i);
6924 if (mono_mempool_contains_addr (set->mempool, ptr))
6929 image_sets_unlock ();
6935 mono_loader_set_strict_strong_names (gboolean enabled)
6937 check_strong_names_strictly = enabled;
6941 mono_loader_get_strict_strong_names (void)
6943 return check_strong_names_strictly;