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/metadata/exception-internals.h>
32 #include <mono/utils/mono-error-internals.h>
33 #include <mono/utils/mono-memory-model.h>
34 #include <mono/utils/bsearch.h>
35 #include <mono/utils/atomic.h>
36 #include <mono/utils/unlocked.h>
37 #include <mono/utils/mono-counters.h>
39 static gint32 img_set_cache_hit
, img_set_cache_miss
, img_set_count
;
42 /* Auxiliary structure used for caching inflated signatures */
44 MonoMethodSignature
*sig
;
45 MonoGenericContext context
;
46 } MonoInflatedMethodSignature
;
48 static gboolean
do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
, gboolean transient
,
49 const char *ptr
, const char **rptr
, MonoError
*error
);
51 static gboolean
do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
);
52 static gboolean
mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
);
53 static gboolean
mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
);
54 static gboolean
_mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
,
55 gboolean signature_only
);
56 static void free_generic_inst (MonoGenericInst
*ginst
);
57 static void free_generic_class (MonoGenericClass
*ginst
);
58 static void free_inflated_method (MonoMethodInflated
*method
);
59 static void free_inflated_signature (MonoInflatedMethodSignature
*sig
);
60 static void mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
, MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
);
62 static MonoType
* mono_signature_get_params_internal (MonoMethodSignature
*sig
, gpointer
*iter
);
66 * This enumeration is used to describe the data types in the metadata
77 /* Index into Blob heap */
80 /* Index into String heap */
86 /* Pointer into a table */
89 /* HasConstant:Parent pointer (Param, Field or Property) */
92 /* HasCustomAttribute index. Indexes any table except CustomAttribute */
95 /* CustomAttributeType encoded index */
98 /* HasDeclSecurity index: TypeDef Method or Assembly */
101 /* Implementation coded index: File, Export AssemblyRef */
104 /* HasFieldMarshal coded index: Field or Param table */
107 /* MemberForwardedIndex: Field or Method */
110 /* TypeDefOrRef coded index: typedef, typeref, typespec */
113 /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
116 /* MethodDefOrRef coded index: Method or Member Ref table */
119 /* HasSemantic coded index: Event or Property */
122 /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
125 /* CustomDebugInformation parent encoded index */
126 MONO_MT_HASCUSTDEBUG_IDX
129 const static unsigned char TableSchemas
[] = {
130 #define ASSEMBLY_SCHEMA_OFFSET 0
131 MONO_MT_UINT32
, /* "HashId" }, */
132 MONO_MT_UINT16
, /* "Major" }, */
133 MONO_MT_UINT16
, /* "Minor" }, */
134 MONO_MT_UINT16
, /* "BuildNumber" }, */
135 MONO_MT_UINT16
, /* "RevisionNumber" }, */
136 MONO_MT_UINT32
, /* "Flags" }, */
137 MONO_MT_BLOB_IDX
, /* "PublicKey" }, */
138 MONO_MT_STRING_IDX
, /* "Name" }, */
139 MONO_MT_STRING_IDX
, /* "Culture" }, */
142 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
143 MONO_MT_UINT32
, /* "OSPlatformID" }, */
144 MONO_MT_UINT32
, /* "OSMajor" }, */
145 MONO_MT_UINT32
, /* "OSMinor" }, */
148 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
149 MONO_MT_UINT32
, /* "Processor" }, */
152 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
153 MONO_MT_UINT16
, /* "Major" }, */
154 MONO_MT_UINT16
, /* "Minor" }, */
155 MONO_MT_UINT16
, /* "Build" }, */
156 MONO_MT_UINT16
, /* "Revision" }, */
157 MONO_MT_UINT32
, /* "Flags" }, */
158 MONO_MT_BLOB_IDX
, /* "PublicKeyOrToken" }, */
159 MONO_MT_STRING_IDX
, /* "Name" }, */
160 MONO_MT_STRING_IDX
, /* "Culture" }, */
161 MONO_MT_BLOB_IDX
, /* "HashValue" }, */
164 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
165 MONO_MT_UINT32
, /* "OSPlatformID" }, */
166 MONO_MT_UINT32
, /* "OSMajorVersion" }, */
167 MONO_MT_UINT32
, /* "OSMinorVersion" }, */
168 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
171 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
172 MONO_MT_UINT32
, /* "Processor" }, */
173 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
176 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
177 MONO_MT_UINT16
, /* "PackingSize" }, */
178 MONO_MT_UINT32
, /* "ClassSize" }, */
179 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
182 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
183 MONO_MT_UINT8
, /* "Type" }, */
184 MONO_MT_UINT8
, /* "PaddingZero" }, */
185 MONO_MT_CONST_IDX
, /* "Parent" }, */
186 MONO_MT_BLOB_IDX
, /* "Value" }, */
189 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
190 MONO_MT_HASCAT_IDX
, /* "Parent" }, */
191 MONO_MT_CAT_IDX
, /* "Type" }, */
192 MONO_MT_BLOB_IDX
, /* "Value" }, */
195 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
196 MONO_MT_UINT16
, /* "Action" }, */
197 MONO_MT_HASDEC_IDX
, /* "Parent" }, */
198 MONO_MT_BLOB_IDX
, /* "PermissionSet" }, */
201 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
202 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
203 MONO_MT_TABLE_IDX
, /* "EventList:Event" }, */
206 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
207 MONO_MT_UINT16
, /* "EventFlags#EventAttribute" }, */
208 MONO_MT_STRING_IDX
, /* "Name" }, */
209 MONO_MT_TDOR_IDX
, /* "EventType" }, TypeDef or TypeRef or TypeSpec */
212 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
213 MONO_MT_TABLE_IDX
, /* "Event" }, */
216 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
217 MONO_MT_UINT32
, /* "Flags" }, */
218 MONO_MT_TABLE_IDX
, /* "TypeDefId" }, */
219 MONO_MT_STRING_IDX
, /* "TypeName" }, */
220 MONO_MT_STRING_IDX
, /* "TypeNameSpace" }, */
221 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
224 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
225 MONO_MT_UINT16
, /* "Flags" }, */
226 MONO_MT_STRING_IDX
, /* "Name" }, */
227 MONO_MT_BLOB_IDX
, /* "Signature" }, */
230 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
231 MONO_MT_UINT32
, /* "Offset" }, */
232 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
235 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
236 MONO_MT_HFM_IDX
, /* "Parent" }, */
237 MONO_MT_BLOB_IDX
, /* "NativeType" }, */
240 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
241 MONO_MT_UINT32
, /* "RVA" }, */
242 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
245 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
246 MONO_MT_TABLE_IDX
, /* "Field" }, */
249 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
250 MONO_MT_UINT32
, /* "Flags" }, */
251 MONO_MT_STRING_IDX
, /* "Name" }, */
252 MONO_MT_BLOB_IDX
, /* "Value" }, */
255 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
256 MONO_MT_UINT16
, /* "MappingFlag" }, */
257 MONO_MT_MF_IDX
, /* "MemberForwarded" }, */
258 MONO_MT_STRING_IDX
, /* "ImportName" }, */
259 MONO_MT_TABLE_IDX
, /* "ImportScope:ModuleRef" }, */
262 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
263 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
264 MONO_MT_TDOR_IDX
, /* "Interface=TypeDefOrRef" }, */
267 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
268 MONO_MT_UINT32
, /* "Offset" }, */
269 MONO_MT_UINT32
, /* "Flags" }, */
270 MONO_MT_STRING_IDX
, /* "Name" }, */
271 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
274 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
275 MONO_MT_MRP_IDX
, /* "Class" }, */
276 MONO_MT_STRING_IDX
, /* "Name" }, */
277 MONO_MT_BLOB_IDX
, /* "Signature" }, */
280 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
281 MONO_MT_UINT32
, /* "RVA" }, */
282 MONO_MT_UINT16
, /* "ImplFlags#MethodImplAttributes" }, */
283 MONO_MT_UINT16
, /* "Flags#MethodAttribute" }, */
284 MONO_MT_STRING_IDX
, /* "Name" }, */
285 MONO_MT_BLOB_IDX
, /* "Signature" }, */
286 MONO_MT_TABLE_IDX
, /* "ParamList:Param" }, */
289 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
290 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
291 MONO_MT_MDOR_IDX
, /* "MethodBody" }, */
292 MONO_MT_MDOR_IDX
, /* "MethodDeclaration" }, */
295 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
296 MONO_MT_UINT16
, /* "MethodSemantic" }, */
297 MONO_MT_TABLE_IDX
, /* "Method:Method" }, */
298 MONO_MT_HS_IDX
, /* "Association" }, */
301 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
302 MONO_MT_TABLE_IDX
, /* "Method" }, */
305 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
306 MONO_MT_UINT16
, /* "Generation" }, */
307 MONO_MT_STRING_IDX
, /* "Name" }, */
308 MONO_MT_GUID_IDX
, /* "MVID" }, */
309 MONO_MT_GUID_IDX
, /* "EncID" }, */
310 MONO_MT_GUID_IDX
, /* "EncBaseID" }, */
313 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
314 MONO_MT_STRING_IDX
, /* "Name" }, */
317 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
318 MONO_MT_TABLE_IDX
, /* "NestedClass:TypeDef" }, */
319 MONO_MT_TABLE_IDX
, /* "EnclosingClass:TypeDef" }, */
322 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
323 MONO_MT_UINT16
, /* "Flags" }, */
324 MONO_MT_UINT16
, /* "Sequence" }, */
325 MONO_MT_STRING_IDX
, /* "Name" }, */
328 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
329 MONO_MT_TABLE_IDX
, /* "Param" }, */
332 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
333 MONO_MT_UINT16
, /* "Flags" }, */
334 MONO_MT_STRING_IDX
, /* "Name" }, */
335 MONO_MT_BLOB_IDX
, /* "Type" }, */
338 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
339 MONO_MT_TABLE_IDX
, /* "Property" }, */
342 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
343 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
344 MONO_MT_TABLE_IDX
, /* "PropertyList:Property" }, */
347 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
348 MONO_MT_BLOB_IDX
, /* "Signature" }, */
351 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
352 MONO_MT_UINT32
, /* "Flags" }, */
353 MONO_MT_STRING_IDX
, /* "Name" }, */
354 MONO_MT_STRING_IDX
, /* "Namespace" }, */
355 MONO_MT_TDOR_IDX
, /* "Extends" }, */
356 MONO_MT_TABLE_IDX
, /* "FieldList:Field" }, */
357 MONO_MT_TABLE_IDX
, /* "MethodList:Method" }, */
360 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
361 MONO_MT_RS_IDX
, /* "ResolutionScope=ResolutionScope" }, */
362 MONO_MT_STRING_IDX
, /* "Name" }, */
363 MONO_MT_STRING_IDX
, /* "Namespace" }, */
366 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
367 MONO_MT_BLOB_IDX
, /* "Signature" }, */
370 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
371 MONO_MT_UINT16
, /* "Number" }, */
372 MONO_MT_UINT16
, /* "Flags" }, */
373 MONO_MT_TABLE_IDX
, /* "Owner" }, TypeDef or MethodDef */
374 MONO_MT_STRING_IDX
, /* "Name" }, */
377 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
378 MONO_MT_MDOR_IDX
, /* "Method" }, */
379 MONO_MT_BLOB_IDX
, /* "Signature" }, */
382 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
383 MONO_MT_TABLE_IDX
, /* "GenericParam" }, */
384 MONO_MT_TDOR_IDX
, /* "Constraint" }, */
387 #define DOCUMENT_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
388 MONO_MT_BLOB_IDX
, /* Name */
389 MONO_MT_GUID_IDX
, /* HashAlgorithm */
390 MONO_MT_BLOB_IDX
, /* Hash */
391 MONO_MT_GUID_IDX
, /* Language */
394 #define METHODBODY_SCHEMA_OFFSET DOCUMENT_SCHEMA_OFFSET + 5
395 MONO_MT_TABLE_IDX
, /* Document */
396 MONO_MT_BLOB_IDX
, /* SequencePoints */
399 #define LOCALSCOPE_SCHEMA_OFFSET METHODBODY_SCHEMA_OFFSET + 3
400 MONO_MT_TABLE_IDX
, /* Method */
401 MONO_MT_TABLE_IDX
, /* ImportScope */
402 MONO_MT_TABLE_IDX
, /* VariableList */
403 MONO_MT_TABLE_IDX
, /* ConstantList */
404 MONO_MT_UINT32
, /* StartOffset */
405 MONO_MT_UINT32
, /* Length */
408 #define LOCALVARIABLE_SCHEMA_OFFSET LOCALSCOPE_SCHEMA_OFFSET + 7
409 MONO_MT_UINT16
, /* Attributes */
410 MONO_MT_UINT16
, /* Index */
411 MONO_MT_STRING_IDX
, /* Name */
414 #define LOCALCONSTANT_SCHEMA_OFFSET LOCALVARIABLE_SCHEMA_OFFSET + 4
415 MONO_MT_STRING_IDX
, /* Name (String heap index) */
416 MONO_MT_BLOB_IDX
, /* Signature (Blob heap index, LocalConstantSig blob) */
419 #define IMPORTSCOPE_SCHEMA_OFFSET LOCALCONSTANT_SCHEMA_OFFSET + 3
420 MONO_MT_TABLE_IDX
, /* Parent (ImportScope row id or nil) */
421 MONO_MT_BLOB_IDX
, /* Imports (Blob index, encoding: Imports blob) */
424 #define ASYNCMETHOD_SCHEMA_OFFSET IMPORTSCOPE_SCHEMA_OFFSET + 3
425 MONO_MT_TABLE_IDX
, /* MoveNextMethod (MethodDef row id) */
426 MONO_MT_TABLE_IDX
, /* KickoffMethod (MethodDef row id) */
429 #define CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET ASYNCMETHOD_SCHEMA_OFFSET + 3
430 MONO_MT_HASCUSTDEBUG_IDX
, /* Parent (HasCustomDebugInformation coded index) */
431 MONO_MT_GUID_IDX
, /* Kind (Guid heap index) */
432 MONO_MT_BLOB_IDX
, /* Value (Blob heap index) */
435 #define NULL_SCHEMA_OFFSET CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET + 4
439 /* Must be the same order as MONO_TABLE_* */
440 const static unsigned char
441 table_description
[] = {
442 MODULE_SCHEMA_OFFSET
,
443 TYPEREF_SCHEMA_OFFSET
,
444 TYPEDEF_SCHEMA_OFFSET
,
445 FIELD_POINTER_SCHEMA_OFFSET
,
447 METHOD_POINTER_SCHEMA_OFFSET
,
448 METHOD_SCHEMA_OFFSET
,
449 PARAM_POINTER_SCHEMA_OFFSET
,
451 IFACEMAP_SCHEMA_OFFSET
,
452 MEMBERREF_SCHEMA_OFFSET
, /* 0xa */
453 CONSTANT_SCHEMA_OFFSET
,
454 CUSTOM_ATTR_SCHEMA_OFFSET
,
455 FIELD_MARSHAL_SCHEMA_OFFSET
,
456 DECL_SEC_SCHEMA_OFFSET
,
457 CLASS_LAYOUT_SCHEMA_OFFSET
,
458 FIELD_LAYOUT_SCHEMA_OFFSET
, /* 0x10 */
459 STDALON_SIG_SCHEMA_OFFSET
,
460 EVENTMAP_SCHEMA_OFFSET
,
461 EVENT_POINTER_SCHEMA_OFFSET
,
463 PROPERTY_MAP_SCHEMA_OFFSET
,
464 PROPERTY_POINTER_SCHEMA_OFFSET
,
465 PROPERTY_SCHEMA_OFFSET
,
466 METHOD_SEMA_SCHEMA_OFFSET
,
467 METHOD_IMPL_SCHEMA_OFFSET
,
468 MODULEREF_SCHEMA_OFFSET
, /* 0x1a */
469 TYPESPEC_SCHEMA_OFFSET
,
470 IMPLMAP_SCHEMA_OFFSET
,
471 FIELD_RVA_SCHEMA_OFFSET
,
474 ASSEMBLY_SCHEMA_OFFSET
, /* 0x20 */
475 ASSEMBLYPROC_SCHEMA_OFFSET
,
476 ASSEMBLYOS_SCHEMA_OFFSET
,
477 ASSEMBLYREF_SCHEMA_OFFSET
,
478 ASSEMBLYREFPROC_SCHEMA_OFFSET
,
479 ASSEMBLYREFOS_SCHEMA_OFFSET
,
481 EXPORTED_TYPE_SCHEMA_OFFSET
,
482 MANIFEST_SCHEMA_OFFSET
,
483 NESTED_CLASS_SCHEMA_OFFSET
,
484 GENPARAM_SCHEMA_OFFSET
, /* 0x2a */
485 METHOD_SPEC_SCHEMA_OFFSET
,
486 GEN_CONSTRAINT_SCHEMA_OFFSET
,
490 DOCUMENT_SCHEMA_OFFSET
, /* 0x30 */
491 METHODBODY_SCHEMA_OFFSET
,
492 LOCALSCOPE_SCHEMA_OFFSET
,
493 LOCALVARIABLE_SCHEMA_OFFSET
,
494 LOCALCONSTANT_SCHEMA_OFFSET
,
495 IMPORTSCOPE_SCHEMA_OFFSET
,
496 ASYNCMETHOD_SCHEMA_OFFSET
,
497 CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET
500 // This, instead of an array of pointers, to optimize away a pointer and a relocation per string.
501 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
502 #define MSGSTRFIELD1(line) str##line
503 static const struct msgstr_t
{
504 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
505 #include "mono/cil/tables.def"
508 #define TABLEDEF(a,b) b,
509 #include "mono/cil/tables.def"
512 static const gint16 tableidx
[] = {
513 #define TABLEDEF(a,b) offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
514 #include "mono/cil/tables.def"
518 /* If TRUE (but also see DISABLE_STICT_STRONG_NAMES #define), Mono will check
519 * that the public key token, culture and version of a candidate assembly matches
520 * the requested strong name. If FALSE, as long as the name matches, the candidate
523 static gboolean check_strong_names_strictly
= FALSE
;
525 // Amount initially reserved in each imageset's mempool.
526 // FIXME: This number is arbitrary, a more practical number should be found
527 #define INITIAL_IMAGE_SET_SIZE 1024
530 * mono_meta_table_name:
531 * \param table table index
533 * Returns the name of the given ECMA metadata logical format table
534 * as described in ECMA 335, Partition II, Section 22.
536 * \returns the name for the \p table index
539 mono_meta_table_name (int table
)
541 if ((table
< 0) || (table
> MONO_TABLE_LAST
))
544 return (const char*)&tablestr
+ tableidx
[table
];
547 /* The guy who wrote the spec for this should not be allowed near a
550 If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
551 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
552 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
553 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
554 inverse of this mapping.
557 #define rtsize(meta,s,b) (((s) < (1 << (b)) ? 2 : 4))
560 idx_size (MonoImage
*meta
, int idx
)
562 if (meta
->referenced_tables
&& (meta
->referenced_tables
& ((guint64
)1 << idx
)))
563 return meta
->referenced_table_rows
[idx
] < 65536 ? 2 : 4;
565 return meta
->tables
[idx
].rows
< 65536 ? 2 : 4;
569 get_nrows (MonoImage
*meta
, int idx
)
571 if (meta
->referenced_tables
&& (meta
->referenced_tables
& ((guint64
)1 << idx
)))
572 return meta
->referenced_table_rows
[idx
];
574 return meta
->tables
[idx
].rows
;
577 /* Reference: Partition II - 23.2.6 */
579 * mono_metadata_compute_size:
580 * \param meta metadata context
581 * \param tableindex metadata table number
582 * \param result_bitfield pointer to \c guint32 where to store additional info
584 * \c mono_metadata_compute_size computes the length in bytes of a single
585 * row in a metadata table. The size of each column is encoded in the
586 * \p result_bitfield return value along with the number of columns in the table.
587 * the resulting bitfield should be handed to the \c mono_metadata_table_size
588 * and \c mono_metadata_table_count macros.
589 * This is a Mono runtime internal only function.
592 mono_metadata_compute_size (MonoImage
*meta
, int tableindex
, guint32
*result_bitfield
)
594 guint32 bitfield
= 0;
595 int size
= 0, field_size
= 0;
598 const unsigned char *description
= TableSchemas
+ table_description
[tableindex
];
600 for (i
= 0; (code
= description
[i
]) != MONO_MT_END
; i
++){
603 field_size
= 4; break;
606 field_size
= 2; break;
609 field_size
= 1; break;
611 case MONO_MT_BLOB_IDX
:
612 field_size
= meta
->idx_blob_wide
? 4 : 2; break;
614 case MONO_MT_STRING_IDX
:
615 field_size
= meta
->idx_string_wide
? 4 : 2; break;
617 case MONO_MT_GUID_IDX
:
618 field_size
= meta
->idx_guid_wide
? 4 : 2; break;
620 case MONO_MT_TABLE_IDX
:
621 /* Uhm, a table index can point to other tables besides the current one
622 * so, it's not correct to use the rowcount of the current table to
623 * get the size for this column - lupus
625 switch (tableindex
) {
626 case MONO_TABLE_ASSEMBLYREFOS
:
628 field_size
= idx_size (meta
, MONO_TABLE_ASSEMBLYREF
); break;
629 case MONO_TABLE_ASSEMBLYREFPROCESSOR
:
631 field_size
= idx_size (meta
, MONO_TABLE_ASSEMBLYREF
); break;
632 case MONO_TABLE_CLASSLAYOUT
:
634 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
635 case MONO_TABLE_EVENTMAP
:
636 g_assert (i
== 0 || i
== 1);
637 field_size
= i
? idx_size (meta
, MONO_TABLE_EVENT
):
638 idx_size (meta
, MONO_TABLE_TYPEDEF
);
640 case MONO_TABLE_EVENT_POINTER
:
642 field_size
= idx_size (meta
, MONO_TABLE_EVENT
); break;
643 case MONO_TABLE_EXPORTEDTYPE
:
645 /* the index is in another metadata file, so it must be 4 */
646 field_size
= 4; break;
647 case MONO_TABLE_FIELDLAYOUT
:
649 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
650 case MONO_TABLE_FIELDRVA
:
652 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
653 case MONO_TABLE_FIELD_POINTER
:
655 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
656 case MONO_TABLE_IMPLMAP
:
658 field_size
= idx_size (meta
, MONO_TABLE_MODULEREF
); break;
659 case MONO_TABLE_INTERFACEIMPL
:
661 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
662 case MONO_TABLE_METHOD
:
664 field_size
= idx_size (meta
, MONO_TABLE_PARAM
); break;
665 case MONO_TABLE_METHODIMPL
:
667 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
668 case MONO_TABLE_METHODSEMANTICS
:
670 field_size
= idx_size (meta
, MONO_TABLE_METHOD
); break;
671 case MONO_TABLE_METHOD_POINTER
:
673 field_size
= idx_size (meta
, MONO_TABLE_METHOD
); break;
674 case MONO_TABLE_NESTEDCLASS
:
675 g_assert (i
== 0 || i
== 1);
676 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
677 case MONO_TABLE_PARAM_POINTER
:
679 field_size
= idx_size (meta
, MONO_TABLE_PARAM
); break;
680 case MONO_TABLE_PROPERTYMAP
:
681 g_assert (i
== 0 || i
== 1);
682 field_size
= i
? idx_size (meta
, MONO_TABLE_PROPERTY
):
683 idx_size (meta
, MONO_TABLE_TYPEDEF
);
685 case MONO_TABLE_PROPERTY_POINTER
:
687 field_size
= idx_size (meta
, MONO_TABLE_PROPERTY
); break;
688 case MONO_TABLE_TYPEDEF
:
689 g_assert (i
== 4 || i
== 5);
690 field_size
= i
== 4 ? idx_size (meta
, MONO_TABLE_FIELD
):
691 idx_size (meta
, MONO_TABLE_METHOD
);
693 case MONO_TABLE_GENERICPARAM
:
695 n
= MAX (get_nrows (meta
, MONO_TABLE_METHOD
), get_nrows (meta
, MONO_TABLE_TYPEDEF
));
696 /*This is a coded token for 2 tables, so takes 1 bit */
697 field_size
= rtsize (meta
, n
, 16 - MONO_TYPEORMETHOD_BITS
);
699 case MONO_TABLE_GENERICPARAMCONSTRAINT
:
701 field_size
= idx_size (meta
, MONO_TABLE_GENERICPARAM
);
703 case MONO_TABLE_LOCALSCOPE
:
706 // FIXME: This table is in another file
707 field_size
= idx_size (meta
, MONO_TABLE_METHOD
);
710 field_size
= idx_size (meta
, MONO_TABLE_IMPORTSCOPE
);
713 field_size
= idx_size (meta
, MONO_TABLE_LOCALVARIABLE
);
716 field_size
= idx_size (meta
, MONO_TABLE_LOCALCONSTANT
);
719 g_assert_not_reached ();
723 case MONO_TABLE_METHODBODY
:
725 field_size
= idx_size (meta
, MONO_TABLE_DOCUMENT
); break;
726 case MONO_TABLE_IMPORTSCOPE
:
728 field_size
= idx_size (meta
, MONO_TABLE_IMPORTSCOPE
); break;
729 case MONO_TABLE_STATEMACHINEMETHOD
:
730 g_assert(i
== 0 || i
== 1);
731 field_size
= idx_size(meta
, MONO_TABLE_METHOD
); break;
733 g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex
, i
);
738 * HasConstant: ParamDef, FieldDef, Property
740 case MONO_MT_CONST_IDX
:
741 n
= MAX (get_nrows (meta
, MONO_TABLE_PARAM
),
742 get_nrows (meta
, MONO_TABLE_FIELD
));
743 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_PROPERTY
));
745 /* 2 bits to encode tag */
746 field_size
= rtsize (meta
, n
, 16-2);
750 * HasCustomAttribute: points to any table but
753 case MONO_MT_HASCAT_IDX
:
755 * We believe that since the signature and
756 * permission are indexing the Blob heap,
757 * we should consider the blob size first
759 /* I'm not a believer - lupus
760 if (meta->idx_blob_wide){
765 n
= MAX (get_nrows (meta
, MONO_TABLE_METHOD
),
766 get_nrows (meta
, MONO_TABLE_FIELD
));
767 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPEREF
));
768 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPEDEF
));
769 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_PARAM
));
770 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_INTERFACEIMPL
));
771 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MEMBERREF
));
772 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MODULE
));
773 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_DECLSECURITY
));
774 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_PROPERTY
));
775 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_EVENT
));
776 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_STANDALONESIG
));
777 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MODULEREF
));
778 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
779 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLY
));
780 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
781 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_FILE
));
782 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_EXPORTEDTYPE
));
783 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MANIFESTRESOURCE
));
784 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_GENERICPARAM
));
785 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_GENERICPARAMCONSTRAINT
));
786 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_METHODSPEC
));
788 /* 5 bits to encode */
789 field_size
= rtsize (meta
, n
, 16-5);
793 * HasCustomAttribute: points to any table but
797 case MONO_MT_HASCUSTDEBUG_IDX
:
798 n
= MAX(get_nrows (meta
, MONO_TABLE_METHOD
),
799 get_nrows (meta
, MONO_TABLE_FIELD
));
800 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_TYPEREF
));
801 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_TYPEDEF
));
802 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_PARAM
));
803 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_INTERFACEIMPL
));
804 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MEMBERREF
));
805 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MODULE
));
806 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_DECLSECURITY
));
807 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_PROPERTY
));
808 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_EVENT
));
809 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_STANDALONESIG
));
810 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MODULEREF
));
811 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
812 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_ASSEMBLY
));
813 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
814 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_FILE
));
815 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_EXPORTEDTYPE
));
816 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_MANIFESTRESOURCE
));
817 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_GENERICPARAM
));
818 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_GENERICPARAMCONSTRAINT
));
819 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_METHODSPEC
));
820 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_DOCUMENT
));
821 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_LOCALSCOPE
));
822 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_LOCALVARIABLE
));
823 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_LOCALCONSTANT
));
824 n
= MAX(n
, get_nrows (meta
, MONO_TABLE_IMPORTSCOPE
));
826 /* 5 bits to encode */
827 field_size
= rtsize(meta
, n
, 16 - 5);
831 * CustomAttributeType: MethodDef, MemberRef.
833 case MONO_MT_CAT_IDX
:
834 n
= MAX (get_nrows (meta
, MONO_TABLE_METHOD
),
835 get_nrows (meta
, MONO_TABLE_MEMBERREF
));
837 /* 3 bits to encode */
838 field_size
= rtsize (meta
, n
, 16-3);
842 * HasDeclSecurity: Typedef, MethodDef, Assembly
844 case MONO_MT_HASDEC_IDX
:
845 n
= MAX (get_nrows (meta
, MONO_TABLE_TYPEDEF
),
846 get_nrows (meta
, MONO_TABLE_METHOD
));
847 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLY
));
849 /* 2 bits to encode */
850 field_size
= rtsize (meta
, n
, 16-2);
854 * Implementation: File, AssemblyRef, ExportedType
856 case MONO_MT_IMPL_IDX
:
857 n
= MAX (get_nrows (meta
, MONO_TABLE_FILE
),
858 get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
859 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_EXPORTEDTYPE
));
861 /* 2 bits to encode tag */
862 field_size
= rtsize (meta
, n
, 16-2);
866 * HasFieldMarshall: FieldDef, ParamDef
868 case MONO_MT_HFM_IDX
:
869 n
= MAX (get_nrows (meta
, MONO_TABLE_FIELD
),
870 get_nrows (meta
, MONO_TABLE_PARAM
));
872 /* 1 bit used to encode tag */
873 field_size
= rtsize (meta
, n
, 16-1);
877 * MemberForwarded: FieldDef, MethodDef
880 n
= MAX (get_nrows (meta
, MONO_TABLE_FIELD
),
881 get_nrows (meta
, MONO_TABLE_METHOD
));
883 /* 1 bit used to encode tag */
884 field_size
= rtsize (meta
, n
, 16-1);
888 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
890 * It is TypeDef, _TypeRef_, TypeSpec, instead.
892 case MONO_MT_TDOR_IDX
:
893 n
= MAX (get_nrows (meta
, MONO_TABLE_TYPEDEF
),
894 get_nrows (meta
, MONO_TABLE_TYPEREF
));
895 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
897 /* 2 bits to encode */
898 field_size
= rtsize (meta
, n
, 16-2);
902 * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
904 case MONO_MT_MRP_IDX
:
905 n
= MAX (get_nrows (meta
, MONO_TABLE_TYPEDEF
),
906 get_nrows (meta
, MONO_TABLE_TYPEREF
));
907 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_METHOD
));
908 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_MODULEREF
));
909 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPESPEC
));
911 /* 3 bits to encode */
912 field_size
= rtsize (meta
, n
, 16 - 3);
916 * MethodDefOrRef: MethodDef, MemberRef
918 case MONO_MT_MDOR_IDX
:
919 n
= MAX (get_nrows (meta
, MONO_TABLE_METHOD
),
920 get_nrows (meta
, MONO_TABLE_MEMBERREF
));
922 /* 1 bit used to encode tag */
923 field_size
= rtsize (meta
, n
, 16-1);
927 * HasSemantics: Property, Event
930 n
= MAX (get_nrows (meta
, MONO_TABLE_PROPERTY
),
931 get_nrows (meta
, MONO_TABLE_EVENT
));
933 /* 1 bit used to encode tag */
934 field_size
= rtsize (meta
, n
, 16-1);
938 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
941 n
= MAX (get_nrows (meta
, MONO_TABLE_MODULE
),
942 get_nrows (meta
, MONO_TABLE_MODULEREF
));
943 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_ASSEMBLYREF
));
944 n
= MAX (n
, get_nrows (meta
, MONO_TABLE_TYPEREF
));
946 /* 2 bits used to encode tag (ECMA spec claims 3) */
947 field_size
= rtsize (meta
, n
, 16 - 2);
952 * encode field size as follows (we just need to
959 bitfield
|= (field_size
-1) << shift
;
962 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
965 *result_bitfield
= (i
<< 24) | bitfield
;
970 * mono_metadata_compute_table_bases:
971 * \param meta metadata context to compute table values
973 * Computes the table bases for the metadata structure.
974 * This is an internal function used by the image loader code.
977 mono_metadata_compute_table_bases (MonoImage
*meta
)
980 const char *base
= meta
->tables_base
;
982 for (i
= 0; i
< MONO_TABLE_NUM
; i
++) {
983 MonoTableInfo
*table
= &meta
->tables
[i
];
984 if (table
->rows
== 0)
987 table
->row_size
= mono_metadata_compute_size (meta
, i
, &table
->size_bitfield
);
989 base
+= table
->rows
* table
->row_size
;
994 * mono_metadata_locate:
995 * \param meta metadata context
996 * \param table table code.
997 * \param idx index of element to retrieve from \p table.
999 * \returns a pointer to the \p idx element in the metadata table
1000 * whose code is \p table.
1003 mono_metadata_locate (MonoImage
*meta
, int table
, int idx
)
1005 /* idx == 0 refers always to NULL */
1006 g_return_val_if_fail (idx
> 0 && idx
<= meta
->tables
[table
].rows
, ""); /*FIXME shouldn't we return NULL here?*/
1008 return meta
->tables
[table
].base
+ (meta
->tables
[table
].row_size
* (idx
- 1));
1012 * mono_metadata_locate_token:
1013 * \param meta metadata context
1014 * \param token metadata token
1016 * \returns a pointer to the data in the metadata represented by the
1020 mono_metadata_locate_token (MonoImage
*meta
, guint32 token
)
1022 return mono_metadata_locate (meta
, token
>> 24, token
& 0xffffff);
1026 * mono_metadata_string_heap:
1027 * \param meta metadata context
1028 * \param index index into the string heap.
1029 * \returns an in-memory pointer to the \p index in the string heap.
1032 mono_metadata_string_heap (MonoImage
*meta
, guint32 index
)
1034 g_assert (index
< meta
->heap_strings
.size
);
1035 g_return_val_if_fail (index
< meta
->heap_strings
.size
, "");
1036 return meta
->heap_strings
.data
+ index
;
1040 * mono_metadata_string_heap_checked:
1041 * \param meta metadata context
1042 * \param index index into the string heap.
1043 * \param error set on error
1044 * \returns an in-memory pointer to the \p index in the string heap.
1045 * On failure returns NULL and sets \p error.
1048 mono_metadata_string_heap_checked (MonoImage
*meta
, guint32 index
, MonoError
*error
)
1050 if (G_UNLIKELY (!(index
< meta
->heap_strings
.size
))) {
1051 mono_error_set_bad_image_by_name (error
, meta
->name
? meta
->name
: "unknown image", "string heap index %ud out bounds %u", index
, meta
->heap_strings
.size
);
1054 return meta
->heap_strings
.data
+ index
;
1058 * mono_metadata_user_string:
1059 * \param meta metadata context
1060 * \param index index into the user string heap.
1061 * \returns an in-memory pointer to the \p index in the user string heap (<code>#US</code>).
1064 mono_metadata_user_string (MonoImage
*meta
, guint32 index
)
1066 g_assert (index
< meta
->heap_us
.size
);
1067 g_return_val_if_fail (index
< meta
->heap_us
.size
, "");
1068 return meta
->heap_us
.data
+ index
;
1072 * mono_metadata_blob_heap:
1073 * \param meta metadata context
1074 * \param index index into the blob.
1075 * \returns an in-memory pointer to the \p index in the Blob heap.
1078 mono_metadata_blob_heap (MonoImage
*meta
, guint32 index
)
1080 g_assert (index
< meta
->heap_blob
.size
);
1081 g_return_val_if_fail (index
< meta
->heap_blob
.size
, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
1082 return meta
->heap_blob
.data
+ index
;
1086 * mono_metadata_blob_heap_checked:
1087 * \param meta metadata context
1088 * \param index index into the blob.
1089 * \param error set on error
1090 * \returns an in-memory pointer to the \p index in the Blob heap. On failure sets \p error and returns NULL;
1094 mono_metadata_blob_heap_checked (MonoImage
*meta
, guint32 index
, MonoError
*error
)
1096 if (G_UNLIKELY (!(index
< meta
->heap_blob
.size
))) {
1097 mono_error_set_bad_image_by_name (error
, meta
->name
? meta
->name
: "unknown image", "blob heap index %u out of bounds %u", index
, meta
->heap_blob
.size
);
1100 return meta
->heap_blob
.data
+ index
;
1104 * mono_metadata_guid_heap:
1105 * \param meta metadata context
1106 * \param index index into the guid heap.
1107 * \returns an in-memory pointer to the \p index in the guid heap.
1110 mono_metadata_guid_heap (MonoImage
*meta
, guint32 index
)
1113 index
*= 16; /* adjust for guid size and 1-based index */
1114 g_return_val_if_fail (index
< meta
->heap_guid
.size
, "");
1115 return meta
->heap_guid
.data
+ index
;
1118 static const unsigned char *
1119 dword_align (const unsigned char *ptr
)
1121 return (const unsigned char *) (((gsize
) (ptr
+ 3)) & ~3);
1125 * mono_metadata_decode_row:
1126 * \param t table to extract information from.
1127 * \param idx index in table.
1128 * \param res array of \p res_size cols to store the results in
1130 * This decompresses the metadata element \p idx in table \p t
1131 * into the \c guint32 \p res array that has \p res_size elements
1134 mono_metadata_decode_row (const MonoTableInfo
*t
, int idx
, guint32
*res
, int res_size
)
1136 guint32 bitfield
= t
->size_bitfield
;
1137 int i
, count
= mono_metadata_table_count (bitfield
);
1140 g_assert (idx
< t
->rows
);
1141 g_assert (idx
>= 0);
1142 data
= t
->base
+ idx
* t
->row_size
;
1144 g_assert (res_size
== count
);
1146 for (i
= 0; i
< count
; i
++) {
1147 int n
= mono_metadata_table_size (bitfield
, i
);
1151 res
[i
] = *data
; break;
1153 res
[i
] = read16 (data
); break;
1155 res
[i
] = read32 (data
); break;
1157 g_assert_not_reached ();
1164 * mono_metadata_decode_row_checked:
1165 * \param image the \c MonoImage the table belongs to
1166 * \param t table to extract information from.
1167 * \param idx index in the table.
1168 * \param res array of \p res_size cols to store the results in
1169 * \param error set on bounds error
1172 * This decompresses the metadata element \p idx in the table \p t
1173 * into the \c guint32 \p res array that has \p res_size elements.
1175 * \returns TRUE if the read succeeded. Otherwise sets \p error and returns FALSE.
1178 mono_metadata_decode_row_checked (const MonoImage
*image
, const MonoTableInfo
*t
, int idx
, guint32
*res
, int res_size
, MonoError
*error
)
1180 guint32 bitfield
= t
->size_bitfield
;
1181 int i
, count
= mono_metadata_table_count (bitfield
);
1183 const char *image_name
= image
&& image
->name
? image
->name
: "unknown image";
1185 if (G_UNLIKELY (! (idx
< t
->rows
&& idx
>= 0))) {
1186 mono_error_set_bad_image_by_name (error
, image_name
, "row index %d out of bounds: %d rows", idx
, t
->rows
);
1189 const char *data
= t
->base
+ idx
* t
->row_size
;
1191 if (G_UNLIKELY (res_size
!= count
)) {
1192 mono_error_set_bad_image_by_name (error
, image_name
, "res_size %d != count %d", res_size
, count
);
1196 for (i
= 0; i
< count
; i
++) {
1197 int n
= mono_metadata_table_size (bitfield
, i
);
1201 res
[i
] = *data
; break;
1203 res
[i
] = read16 (data
); break;
1205 res
[i
] = read32 (data
); break;
1207 mono_error_set_bad_image_by_name (error
, image_name
, "unexpected table [%d] size %d", i
, n
);
1217 * mono_metadata_decode_row_col:
1218 * \param t table to extract information from.
1219 * \param idx index for row in table.
1220 * \param col column in the row.
1222 * This function returns the value of column \p col from the \p idx
1223 * row in the table \p t .
1226 mono_metadata_decode_row_col (const MonoTableInfo
*t
, int idx
, guint col
)
1228 guint32 bitfield
= t
->size_bitfield
;
1233 g_assert (idx
< t
->rows
);
1234 g_assert (col
< mono_metadata_table_count (bitfield
));
1235 data
= t
->base
+ idx
* t
->row_size
;
1237 n
= mono_metadata_table_size (bitfield
, 0);
1238 for (i
= 0; i
< col
; ++i
) {
1240 n
= mono_metadata_table_size (bitfield
, i
+ 1);
1246 return read16 (data
);
1248 return read32 (data
);
1250 g_assert_not_reached ();
1256 * mono_metadata_decode_blob_size:
1257 * \param ptr pointer to a blob object
1258 * \param rptr the new position of the pointer
1260 * This decodes a compressed size as described by 24.2.4 (#US and #Blob a blob or user string object)
1262 * \returns the size of the blob object
1265 mono_metadata_decode_blob_size (const char *xptr
, const char **rptr
)
1267 const unsigned char *ptr
= (const unsigned char *)xptr
;
1270 if ((*ptr
& 0x80) == 0){
1271 size
= ptr
[0] & 0x7f;
1273 } else if ((*ptr
& 0x40) == 0){
1274 size
= ((ptr
[0] & 0x3f) << 8) + ptr
[1];
1277 size
= ((ptr
[0] & 0x1f) << 24) +
1289 * mono_metadata_decode_value:
1290 * \param ptr pointer to decode from
1291 * \param rptr the new position of the pointer
1293 * This routine decompresses 32-bit values as specified in the "Blob and
1294 * Signature" section (23.2)
1296 * \returns the decoded value
1299 mono_metadata_decode_value (const char *_ptr
, const char **rptr
)
1301 const unsigned char *ptr
= (const unsigned char *) _ptr
;
1302 unsigned char b
= *ptr
;
1305 if ((b
& 0x80) == 0){
1308 } else if ((b
& 0x40) == 0){
1309 len
= ((b
& 0x3f) << 8 | ptr
[1]);
1312 len
= ((b
& 0x1f) << 24) |
1325 * mono_metadata_decode_signed_value:
1326 * \param ptr pointer to decode from
1327 * \param rptr the new position of the pointer
1329 * This routine decompresses 32-bit signed values
1330 * (not specified in the spec)
1332 * \returns the decoded value
1335 mono_metadata_decode_signed_value (const char *ptr
, const char **rptr
)
1337 guint32 uval
= mono_metadata_decode_value (ptr
, rptr
);
1338 gint32 ival
= uval
>> 1;
1341 /* ival is a truncated 2's complement negative number. */
1343 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1346 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1347 return ival
- 0x2000;
1348 if (ival
< 0x10000000)
1349 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1350 return ival
- 0x10000000;
1351 g_assert (ival
< 0x20000000);
1352 g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival
, uval
);
1353 return ival
- 0x20000000;
1357 * mono_metadata_translate_token_index:
1358 * Translates the given 1-based index into the \c Method, \c Field, \c Event, or \c Param tables
1359 * using the \c *Ptr tables in uncompressed metadata, if they are available.
1361 * FIXME: The caller is not forced to call this function, which is error-prone, since
1362 * forgetting to call it would only show up as a bug on uncompressed metadata.
1365 mono_metadata_translate_token_index (MonoImage
*image
, int table
, guint32 idx
)
1367 if (!image
->uncompressed_metadata
)
1371 case MONO_TABLE_METHOD
:
1372 if (image
->tables
[MONO_TABLE_METHOD_POINTER
].rows
)
1373 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_METHOD_POINTER
], idx
- 1, MONO_METHOD_POINTER_METHOD
);
1376 case MONO_TABLE_FIELD
:
1377 if (image
->tables
[MONO_TABLE_FIELD_POINTER
].rows
)
1378 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_FIELD_POINTER
], idx
- 1, MONO_FIELD_POINTER_FIELD
);
1381 case MONO_TABLE_EVENT
:
1382 if (image
->tables
[MONO_TABLE_EVENT_POINTER
].rows
)
1383 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_EVENT_POINTER
], idx
- 1, MONO_EVENT_POINTER_EVENT
);
1386 case MONO_TABLE_PROPERTY
:
1387 if (image
->tables
[MONO_TABLE_PROPERTY_POINTER
].rows
)
1388 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PROPERTY_POINTER
], idx
- 1, MONO_PROPERTY_POINTER_PROPERTY
);
1391 case MONO_TABLE_PARAM
:
1392 if (image
->tables
[MONO_TABLE_PARAM_POINTER
].rows
)
1393 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PARAM_POINTER
], idx
- 1, MONO_PARAM_POINTER_PARAM
);
1402 * mono_metadata_decode_table_row:
1404 * Same as \c mono_metadata_decode_row, but takes an \p image + \p table ID pair, and takes
1405 * uncompressed metadata into account, so it should be used to access the
1406 * \c Method, \c Field, \c Param and \c Event tables when the access is made from metadata, i.e.
1407 * \p idx is retrieved from a metadata table, like \c MONO_TYPEDEF_FIELD_LIST.
1410 mono_metadata_decode_table_row (MonoImage
*image
, int table
, int idx
, guint32
*res
, int res_size
)
1412 if (image
->uncompressed_metadata
)
1413 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1415 mono_metadata_decode_row (&image
->tables
[table
], idx
, res
, res_size
);
1419 * mono_metadata_decode_table_row_col:
1421 * Same as \c mono_metadata_decode_row_col, but takes an \p image + \p table ID pair, and takes
1422 * uncompressed metadata into account, so it should be used to access the
1423 * \c Method, \c Field, \c Param and \c Event tables.
1425 guint32
mono_metadata_decode_table_row_col (MonoImage
*image
, int table
, int idx
, guint col
)
1427 if (image
->uncompressed_metadata
)
1428 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1430 return mono_metadata_decode_row_col (&image
->tables
[table
], idx
, col
);
1434 * mono_metadata_parse_typedef_or_ref:
1435 * \param m a metadata context.
1436 * \param ptr a pointer to an encoded TypedefOrRef in \p m
1437 * \param rptr pointer updated to match the end of the decoded stream
1438 * \returns a token valid in the \p m metadata decoded from
1439 * the compressed representation.
1442 mono_metadata_parse_typedef_or_ref (MonoImage
*m
, const char *ptr
, const char **rptr
)
1445 token
= mono_metadata_decode_value (ptr
, &ptr
);
1448 return mono_metadata_token_from_dor (token
);
1452 * mono_metadata_parse_custom_mod:
1453 * \param m a metadata context.
1454 * \param dest storage where the info about the custom modifier is stored (may be NULL)
1455 * \param ptr a pointer to (possibly) the start of a custom modifier list
1456 * \param rptr pointer updated to match the end of the decoded stream
1458 * Checks if \p ptr points to a type custom modifier compressed representation.
1460 * \returns TRUE if a custom modifier was found, FALSE if not.
1463 mono_metadata_parse_custom_mod (MonoImage
*m
, MonoCustomMod
*dest
, const char *ptr
, const char **rptr
)
1465 MonoCustomMod local
;
1466 if ((*ptr
== MONO_TYPE_CMOD_OPT
) || (*ptr
== MONO_TYPE_CMOD_REQD
)) {
1469 dest
->required
= *ptr
== MONO_TYPE_CMOD_REQD
? 1 : 0;
1470 dest
->token
= mono_metadata_parse_typedef_or_ref (m
, ptr
+ 1, rptr
);
1477 * mono_metadata_parse_array_internal:
1478 * @m: a metadata context.
1479 * @transient: whenever to allocate data from the heap
1480 * @ptr: a pointer to an encoded array description.
1481 * @rptr: pointer updated to match the end of the decoded stream
1483 * Decodes the compressed array description found in the metadata @m at @ptr.
1485 * Returns: a #MonoArrayType structure describing the array type
1486 * and dimensions. Memory is allocated from the heap or from the image mempool, depending
1487 * on the value of @transient.
1489 * LOCKING: Acquires the loader lock
1491 static MonoArrayType
*
1492 mono_metadata_parse_array_internal (MonoImage
*m
, MonoGenericContainer
*container
,
1493 gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1496 MonoArrayType
*array
;
1499 etype
= mono_metadata_parse_type_checked (m
, container
, 0, FALSE
, ptr
, &ptr
, error
); //FIXME this doesn't respect @transient
1503 array
= transient
? (MonoArrayType
*)g_malloc0 (sizeof (MonoArrayType
)) : (MonoArrayType
*)mono_image_alloc0 (m
, sizeof (MonoArrayType
));
1504 array
->eklass
= mono_class_from_mono_type_internal (etype
);
1505 array
->rank
= mono_metadata_decode_value (ptr
, &ptr
);
1507 array
->numsizes
= mono_metadata_decode_value (ptr
, &ptr
);
1508 if (array
->numsizes
)
1509 array
->sizes
= transient
? (int *)g_malloc0 (sizeof (int) * array
->numsizes
) : (int *)mono_image_alloc0 (m
, sizeof (int) * array
->numsizes
);
1510 for (i
= 0; i
< array
->numsizes
; ++i
)
1511 array
->sizes
[i
] = mono_metadata_decode_value (ptr
, &ptr
);
1513 array
->numlobounds
= mono_metadata_decode_value (ptr
, &ptr
);
1514 if (array
->numlobounds
)
1515 array
->lobounds
= transient
? (int *)g_malloc0 (sizeof (int) * array
->numlobounds
) : (int *)mono_image_alloc0 (m
, sizeof (int) * array
->numlobounds
);
1516 for (i
= 0; i
< array
->numlobounds
; ++i
)
1517 array
->lobounds
[i
] = mono_metadata_decode_signed_value (ptr
, &ptr
);
1525 * mono_metadata_parse_array:
1528 mono_metadata_parse_array (MonoImage
*m
, const char *ptr
, const char **rptr
)
1531 MonoArrayType
*ret
= mono_metadata_parse_array_internal (m
, NULL
, FALSE
, ptr
, rptr
, error
);
1532 mono_error_cleanup (error
);
1538 * mono_metadata_free_array:
1539 * \param array array description
1541 * Frees the array description returned from \c mono_metadata_parse_array.
1544 mono_metadata_free_array (MonoArrayType
*array
)
1546 g_free (array
->sizes
);
1547 g_free (array
->lobounds
);
1552 * need to add common field and param attributes combinations:
1555 * public static literal
1558 * private static literal
1560 static const MonoType
1562 /* data, attrs, type, nmods, byref, pinned */
1563 {{NULL
}, 0, MONO_TYPE_VOID
, 0, 0, 0},
1564 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 0, 0},
1565 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 1, 0},
1566 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 0, 0},
1567 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 1, 0},
1568 {{NULL
}, 0, MONO_TYPE_I1
, 0, 0, 0},
1569 {{NULL
}, 0, MONO_TYPE_I1
, 0, 1, 0},
1570 {{NULL
}, 0, MONO_TYPE_U1
, 0, 0, 0},
1571 {{NULL
}, 0, MONO_TYPE_U1
, 0, 1, 0},
1572 {{NULL
}, 0, MONO_TYPE_I2
, 0, 0, 0},
1573 {{NULL
}, 0, MONO_TYPE_I2
, 0, 1, 0},
1574 {{NULL
}, 0, MONO_TYPE_U2
, 0, 0, 0},
1575 {{NULL
}, 0, MONO_TYPE_U2
, 0, 1, 0},
1576 {{NULL
}, 0, MONO_TYPE_I4
, 0, 0, 0},
1577 {{NULL
}, 0, MONO_TYPE_I4
, 0, 1, 0},
1578 {{NULL
}, 0, MONO_TYPE_U4
, 0, 0, 0},
1579 {{NULL
}, 0, MONO_TYPE_U4
, 0, 1, 0},
1580 {{NULL
}, 0, MONO_TYPE_I8
, 0, 0, 0},
1581 {{NULL
}, 0, MONO_TYPE_I8
, 0, 1, 0},
1582 {{NULL
}, 0, MONO_TYPE_U8
, 0, 0, 0},
1583 {{NULL
}, 0, MONO_TYPE_U8
, 0, 1, 0},
1584 {{NULL
}, 0, MONO_TYPE_R4
, 0, 0, 0},
1585 {{NULL
}, 0, MONO_TYPE_R4
, 0, 1, 0},
1586 {{NULL
}, 0, MONO_TYPE_R8
, 0, 0, 0},
1587 {{NULL
}, 0, MONO_TYPE_R8
, 0, 1, 0},
1588 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 0, 0},
1589 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 1, 0},
1590 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 0, 0},
1591 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 1, 0},
1592 {{NULL
}, 0, MONO_TYPE_TYPEDBYREF
, 0, 0, 0},
1593 {{NULL
}, 0, MONO_TYPE_I
, 0, 0, 0},
1594 {{NULL
}, 0, MONO_TYPE_I
, 0, 1, 0},
1595 {{NULL
}, 0, MONO_TYPE_U
, 0, 0, 0},
1596 {{NULL
}, 0, MONO_TYPE_U
, 0, 1, 0},
1599 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1601 static GHashTable
*type_cache
= NULL
;
1602 static gint32 next_generic_inst_id
= 0;
1604 /* Protected by image_sets_mutex */
1605 static MonoImageSet
*mscorlib_image_set
;
1606 /* Protected by image_sets_mutex */
1607 static GPtrArray
*image_sets
;
1608 static mono_mutex_t image_sets_mutex
;
1610 static guint
mono_generic_class_hash (gconstpointer data
);
1613 * MonoTypes with modifies are never cached, so we never check or use that field.
1616 mono_type_hash (gconstpointer data
)
1618 const MonoType
*type
= (const MonoType
*) data
;
1619 if (type
->type
== MONO_TYPE_GENERICINST
)
1620 return mono_generic_class_hash (type
->data
.generic_class
);
1622 return type
->type
| (type
->byref
<< 8) | (type
->attrs
<< 9);
1626 mono_type_equal (gconstpointer ka
, gconstpointer kb
)
1628 const MonoType
*a
= (const MonoType
*) ka
;
1629 const MonoType
*b
= (const MonoType
*) kb
;
1631 if (a
->type
!= b
->type
|| a
->byref
!= b
->byref
|| a
->attrs
!= b
->attrs
|| a
->pinned
!= b
->pinned
)
1633 /* need other checks */
1638 mono_metadata_generic_inst_hash (gconstpointer data
)
1640 const MonoGenericInst
*ginst
= (const MonoGenericInst
*) data
;
1644 g_assert (ginst
->type_argv
);
1646 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
1648 g_assert (ginst
->type_argv
[i
]);
1649 hash
+= mono_metadata_type_hash (ginst
->type_argv
[i
]);
1652 return hash
^ (ginst
->is_open
<< 8);
1656 mono_generic_inst_equal_full (const MonoGenericInst
*a
, const MonoGenericInst
*b
, gboolean signature_only
)
1660 // An optimization: if the ids of two insts are the same, we know they are the same inst and don't check contents.
1661 // Furthermore, because we perform early de-duping, if the ids differ, we know the contents differ.
1662 #ifndef MONO_SMALL_CONFIG // Optimization does not work in MONO_SMALL_CONFIG: There are no IDs
1663 if (a
->id
&& b
->id
) { // "id 0" means "object has no id"-- de-duping hasn't been performed yet, must check contents.
1666 // In signature-comparison mode id equality implies object equality, but this is not true for inequality.
1667 // Two separate objects could have signature-equavalent contents.
1668 if (!signature_only
)
1673 if (a
->is_open
!= b
->is_open
|| a
->type_argc
!= b
->type_argc
)
1675 for (i
= 0; i
< a
->type_argc
; ++i
) {
1676 if (!do_mono_metadata_type_equal (a
->type_argv
[i
], b
->type_argv
[i
], signature_only
))
1683 mono_metadata_generic_inst_equal (gconstpointer ka
, gconstpointer kb
)
1685 const MonoGenericInst
*a
= (const MonoGenericInst
*) ka
;
1686 const MonoGenericInst
*b
= (const MonoGenericInst
*) kb
;
1688 return mono_generic_inst_equal_full (a
, b
, FALSE
);
1692 mono_generic_class_hash (gconstpointer data
)
1694 const MonoGenericClass
*gclass
= (const MonoGenericClass
*) data
;
1695 guint hash
= mono_metadata_type_hash (m_class_get_byval_arg (gclass
->container_class
));
1698 hash
+= gclass
->is_tb_open
;
1699 hash
+= mono_metadata_generic_context_hash (&gclass
->context
);
1705 mono_generic_class_equal (gconstpointer ka
, gconstpointer kb
)
1707 const MonoGenericClass
*a
= (const MonoGenericClass
*) ka
;
1708 const MonoGenericClass
*b
= (const MonoGenericClass
*) kb
;
1710 return _mono_metadata_generic_class_equal (a
, b
, FALSE
);
1714 * mono_metadata_init:
1716 * Initialize the global variables of this module.
1717 * This is a Mono runtime internal function.
1720 mono_metadata_init (void)
1724 /* We guard against double initialization due to how pedump in verification mode works.
1725 Until runtime initialization is properly factored to work with what it needs we need workarounds like this.
1726 FIXME: https://bugzilla.xamarin.com/show_bug.cgi?id=58793
1728 static gboolean inited
;
1734 type_cache
= g_hash_table_new (mono_type_hash
, mono_type_equal
);
1736 for (i
= 0; i
< NBUILTIN_TYPES (); ++i
)
1737 g_hash_table_insert (type_cache
, (gpointer
) &builtin_types
[i
], (gpointer
) &builtin_types
[i
]);
1739 mono_os_mutex_init_recursive (&image_sets_mutex
);
1741 mono_counters_register ("ImgSet Cache Hit", MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &img_set_cache_hit
);
1742 mono_counters_register ("ImgSet Cache Miss", MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &img_set_cache_miss
);
1743 mono_counters_register ("ImgSet Count", MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &img_set_count
);
1747 * mono_metadata_cleanup:
1749 * Free all resources used by this module.
1750 * This is a Mono runtime internal function.
1753 mono_metadata_cleanup (void)
1755 g_hash_table_destroy (type_cache
);
1757 g_ptr_array_free (image_sets
, TRUE
);
1759 mono_os_mutex_destroy (&image_sets_mutex
);
1763 * mono_metadata_parse_type:
1764 * \param m metadata context
1765 * \param mode kind of type that may be found at \p ptr
1766 * \param opt_attrs optional attributes to store in the returned type
1767 * \param ptr pointer to the type representation
1768 * \param rptr pointer updated to match the end of the decoded stream
1769 * \param transient whenever to allocate the result from the heap or from a mempool
1771 * Decode a compressed type description found at \p ptr in \p m .
1772 * \p mode can be one of \c MONO_PARSE_MOD_TYPE, \c MONO_PARSE_PARAM, \c MONO_PARSE_RET,
1773 * \c MONO_PARSE_FIELD, \c MONO_PARSE_LOCAL, \c MONO_PARSE_TYPE.
1774 * This function can be used to decode type descriptions in method signatures,
1775 * field signatures, locals signatures etc.
1777 * To parse a generic type, \c generic_container points to the current class'es
1778 * (the \c generic_container field in the <code>MonoClass</code>) or the current generic method's
1779 * (stored in <code>image->property_hash</code>) generic container.
1780 * When we encounter a \c MONO_TYPE_VAR or \c MONO_TYPE_MVAR, it's looked up in
1781 * this \c MonoGenericContainer.
1783 * LOCKING: Acquires the loader lock.
1785 * \returns a \c MonoType structure representing the decoded type.
1788 mono_metadata_parse_type_internal (MonoImage
*m
, MonoGenericContainer
*container
,
1789 short opt_attrs
, gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1791 MonoType
*type
, *cached
;
1793 gboolean byref
= FALSE
;
1794 gboolean pinned
= FALSE
;
1795 const char *tmp_ptr
;
1796 int count
= 0; // Number of mod arguments
1802 * According to the spec, custom modifiers should come before the byref
1803 * flag, but the IL produced by ilasm from the following signature:
1804 * object modopt(...) &
1805 * starts with a byref flag, followed by the modifiers. (bug #49802)
1806 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1807 * it would be better to treat byref as real type constructor instead of
1809 * Also, pinned should come before anything else, but some MSV++ produced
1810 * assemblies violate this (#bug 61990).
1813 /* Count the modifiers first */
1818 case MONO_TYPE_PINNED
:
1819 case MONO_TYPE_BYREF
:
1822 case MONO_TYPE_CMOD_REQD
:
1823 case MONO_TYPE_CMOD_OPT
:
1825 mono_metadata_parse_custom_mod (m
, NULL
, tmp_ptr
, &tmp_ptr
);
1832 MonoCustomModContainer
*cmods
= NULL
;
1834 if (count
) { // There are mods, so the MonoType will be of nonstandard size.
1836 mono_error_set_bad_image (error
, m
, "Invalid type with more than 64 modifiers");
1840 size_t size
= mono_sizeof_type_with_mods (count
);
1841 type
= transient
? (MonoType
*)g_malloc0 (size
) : (MonoType
*)mono_image_alloc0 (m
, size
);
1842 type
->has_cmods
= TRUE
;
1844 cmods
= mono_type_get_cmods (type
);
1845 cmods
->count
= count
;
1847 } else { // The type is of standard size, so we can allocate it on the stack.
1849 memset (type
, 0, MONO_SIZEOF_TYPE
);
1852 /* Iterate again, but now parse pinned, byref and custom modifiers */
1857 case MONO_TYPE_PINNED
:
1861 case MONO_TYPE_BYREF
:
1865 case MONO_TYPE_CMOD_REQD
:
1866 case MONO_TYPE_CMOD_OPT
:
1867 mono_metadata_parse_custom_mod (m
, &(cmods
->modifiers
[count
]), ptr
, &ptr
);
1875 type
->attrs
= opt_attrs
;
1876 type
->byref
= byref
;
1877 type
->pinned
= pinned
? 1 : 0;
1879 if (!do_mono_metadata_parse_type (type
, m
, container
, transient
, ptr
, &ptr
, error
))
1885 // Possibly we can return an already-allocated type instead of the one we decoded
1886 if (!type
->has_cmods
&& !transient
) {
1887 /* no need to free type here, because it is on the stack */
1888 if ((type
->type
== MONO_TYPE_CLASS
|| type
->type
== MONO_TYPE_VALUETYPE
) && !type
->pinned
&& !type
->attrs
) {
1889 MonoType
*ret
= type
->byref
? m_class_get_this_arg (type
->data
.klass
) : m_class_get_byval_arg (type
->data
.klass
);
1891 /* Consider the case:
1893 class Foo<T> { class Bar {} }
1894 class Test : Foo<Test>.Bar {}
1896 When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
1897 a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1899 We ensure that the MonoClass is in a state that we can canonicalize to:
1901 klass->_byval_arg.data.klass == klass
1902 klass->this_arg.data.klass == klass
1904 If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1906 LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1907 of a MonoClass which currently holds the loader lock. 'type' is local.
1909 if (ret
->data
.klass
== type
->data
.klass
) {
1913 /* No need to use locking since nobody is modifying the hash table */
1914 if ((cached
= (MonoType
*)g_hash_table_lookup (type_cache
, type
))) {
1919 /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1921 if (type
== &stype
) { // Type was allocated on the stack, so we need to copy it to safety
1922 type
= transient
? (MonoType
*)g_malloc (MONO_SIZEOF_TYPE
) : (MonoType
*)mono_image_alloc (m
, MONO_SIZEOF_TYPE
);
1923 memcpy (type
, &stype
, MONO_SIZEOF_TYPE
);
1930 mono_metadata_parse_type_checked (MonoImage
*m
, MonoGenericContainer
*container
,
1931 short opt_attrs
, gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1933 return mono_metadata_parse_type_internal (m
, container
, opt_attrs
, transient
, ptr
, rptr
, error
);
1937 * LOCKING: Acquires the loader lock.
1940 mono_metadata_parse_type (MonoImage
*m
, MonoParseTypeMode mode
, short opt_attrs
,
1941 const char *ptr
, const char **rptr
)
1944 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, opt_attrs
, FALSE
, ptr
, rptr
, error
);
1945 mono_error_cleanup (error
);
1950 mono_metadata_method_has_param_attrs (MonoImage
*m
, int def
)
1952 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1953 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1954 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1956 if (def
< methodt
->rows
)
1957 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1959 lastp
= m
->tables
[MONO_TABLE_PARAM
].rows
+ 1;
1961 for (i
= param_index
; i
< lastp
; ++i
) {
1962 guint32 flags
= mono_metadata_decode_row_col (paramt
, i
- 1, MONO_PARAM_FLAGS
);
1971 * mono_metadata_get_param_attrs:
1973 * @m The image to loader parameter attributes from
1974 * @def method def token (one based)
1975 * @param_count number of params to decode including the return value
1977 * Return the parameter attributes for the method whose MethodDef index is DEF. The
1978 * returned memory needs to be freed by the caller. If all the param attributes are
1979 * 0, then NULL is returned.
1982 mono_metadata_get_param_attrs (MonoImage
*m
, int def
, int param_count
)
1984 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1985 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1986 guint32 cols
[MONO_PARAM_SIZE
];
1987 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1990 if (def
< methodt
->rows
)
1991 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1993 lastp
= paramt
->rows
+ 1;
1995 for (i
= param_index
; i
< lastp
; ++i
) {
1996 mono_metadata_decode_row (paramt
, i
- 1, cols
, MONO_PARAM_SIZE
);
1997 if (cols
[MONO_PARAM_FLAGS
]) {
1999 pattrs
= g_new0 (int, param_count
);
2000 /* at runtime we just ignore this kind of malformed file:
2001 * the verifier can signal the error to the user
2003 if (cols
[MONO_PARAM_SEQUENCE
] >= param_count
)
2005 pattrs
[cols
[MONO_PARAM_SEQUENCE
]] = cols
[MONO_PARAM_FLAGS
];
2014 * mono_metadata_parse_signature:
2015 * \param image metadata context
2016 * \param token metadata token
2018 * Decode a method signature stored in the \c StandAloneSig table
2020 * \returns a \c MonoMethodSignature describing the signature.
2022 MonoMethodSignature
*
2023 mono_metadata_parse_signature (MonoImage
*image
, guint32 token
)
2026 MonoMethodSignature
*ret
;
2027 ret
= mono_metadata_parse_signature_checked (image
, token
, error
);
2028 mono_error_cleanup (error
);
2033 * mono_metadata_parse_signature_checked:
2034 * @image: metadata context
2035 * @token: metadata token
2036 * @error: set on error
2038 * Decode a method signature stored in the STANDALONESIG table
2040 * Returns: a MonoMethodSignature describing the signature. On failure
2041 * returns NULL and sets @error.
2043 MonoMethodSignature
*
2044 mono_metadata_parse_signature_checked (MonoImage
*image
, guint32 token
, MonoError
*error
)
2048 MonoTableInfo
*tables
= image
->tables
;
2049 guint32 idx
= mono_metadata_token_index (token
);
2053 if (image_is_dynamic (image
)) {
2054 return (MonoMethodSignature
*)mono_lookup_dynamic_token (image
, token
, NULL
, error
);
2057 g_assert (mono_metadata_token_table(token
) == MONO_TABLE_STANDALONESIG
);
2059 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
2061 ptr
= mono_metadata_blob_heap (image
, sig
);
2062 mono_metadata_decode_blob_size (ptr
, &ptr
);
2064 return mono_metadata_parse_method_signature_full (image
, NULL
, 0, ptr
, NULL
, error
);
2068 * mono_metadata_signature_alloc:
2069 * \param image metadata context
2070 * \param nparams number of parameters in the signature
2072 * Allocate a \c MonoMethodSignature structure with the specified number of params.
2073 * The return type and the params types need to be filled later.
2074 * This is a Mono runtime internal function.
2076 * LOCKING: Assumes the loader lock is held.
2078 * \returns the new \c MonoMethodSignature structure.
2080 MonoMethodSignature
*
2081 mono_metadata_signature_alloc (MonoImage
*m
, guint32 nparams
)
2083 MonoMethodSignature
*sig
;
2085 sig
= (MonoMethodSignature
*)mono_image_alloc0 (m
, MONO_SIZEOF_METHOD_SIGNATURE
+ ((gint32
)nparams
) * sizeof (MonoType
*));
2086 sig
->param_count
= nparams
;
2087 sig
->sentinelpos
= -1;
2092 static MonoMethodSignature
*
2093 mono_metadata_signature_dup_internal_with_padding (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
, size_t padding
)
2095 int sigsize
, sig_header_size
;
2096 MonoMethodSignature
*ret
;
2097 sigsize
= sig_header_size
= MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*) + padding
;
2099 sigsize
+= mono_sizeof_type (sig
->ret
);
2102 ret
= (MonoMethodSignature
*)mono_image_alloc (image
, sigsize
);
2104 ret
= (MonoMethodSignature
*)mono_mempool_alloc (mp
, sigsize
);
2106 ret
= (MonoMethodSignature
*)g_malloc (sigsize
);
2109 memcpy (ret
, sig
, sig_header_size
- padding
);
2111 // Copy return value because of ownership semantics.
2113 // Danger! Do not alter padding use without changing the dup_add_this below
2114 intptr_t end_of_header
= (intptr_t)( (char*)(ret
) + sig_header_size
);
2115 ret
->ret
= (MonoType
*)end_of_header
;
2116 memcpy (ret
->ret
, sig
->ret
, mono_sizeof_type (sig
->ret
));
2122 static MonoMethodSignature
*
2123 mono_metadata_signature_dup_internal (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
)
2125 return mono_metadata_signature_dup_internal_with_padding (image
, mp
, sig
, 0);
2128 * signature_dup_add_this:
2130 * Make a copy of @sig, adding an explicit this argument.
2132 MonoMethodSignature
*
2133 mono_metadata_signature_dup_add_this (MonoImage
*image
, MonoMethodSignature
*sig
, MonoClass
*klass
)
2135 MonoMethodSignature
*ret
;
2136 ret
= mono_metadata_signature_dup_internal_with_padding (image
, NULL
, sig
, sizeof (MonoType
*));
2138 ret
->param_count
= sig
->param_count
+ 1;
2139 ret
->hasthis
= FALSE
;
2141 for (int i
= sig
->param_count
- 1; i
>= 0; i
--)
2142 ret
->params
[i
+ 1] = sig
->params
[i
];
2143 ret
->params
[0] = m_class_is_valuetype (klass
) ? m_class_get_this_arg (klass
) : m_class_get_byval_arg (klass
);
2145 for (int i
= sig
->param_count
- 1; i
>= 0; i
--)
2146 g_assert(ret
->params
[i
+ 1]->type
== sig
->params
[i
]->type
&& ret
->params
[i
+1]->type
!= MONO_TYPE_END
);
2147 g_assert (ret
->ret
->type
== sig
->ret
->type
&& ret
->ret
->type
!= MONO_TYPE_END
);
2154 MonoMethodSignature
*
2155 mono_metadata_signature_dup_full (MonoImage
*image
, MonoMethodSignature
*sig
)
2157 MonoMethodSignature
*ret
= mono_metadata_signature_dup_internal (image
, NULL
, sig
);
2159 for (int i
= 0 ; i
< sig
->param_count
; i
++)
2160 g_assert(ret
->params
[i
]->type
== sig
->params
[i
]->type
);
2161 g_assert (ret
->ret
->type
== sig
->ret
->type
);
2166 /*The mempool is accessed without synchronization*/
2167 MonoMethodSignature
*
2168 mono_metadata_signature_dup_mempool (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
2170 return mono_metadata_signature_dup_internal (NULL
, mp
, sig
);
2174 * mono_metadata_signature_dup:
2175 * \param sig method signature
2177 * Duplicate an existing \c MonoMethodSignature so it can be modified.
2178 * This is a Mono runtime internal function.
2180 * \returns the new \c MonoMethodSignature structure.
2182 MonoMethodSignature
*
2183 mono_metadata_signature_dup (MonoMethodSignature
*sig
)
2185 return mono_metadata_signature_dup_full (NULL
, sig
);
2189 * mono_metadata_signature_size:
2191 * Return the amount of memory allocated to SIG.
2194 mono_metadata_signature_size (MonoMethodSignature
*sig
)
2196 return MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*);
2200 * mono_metadata_parse_method_signature_full:
2201 * \param m metadata context
2202 * \param generic_container: generics container
2203 * \param def the \c MethodDef index or 0 for \c Ref signatures.
2204 * \param ptr pointer to the signature metadata representation
2205 * \param rptr pointer updated to match the end of the decoded stream
2206 * \param error set on error
2209 * Decode a method signature stored at \p ptr.
2210 * This is a Mono runtime internal function.
2212 * LOCKING: Assumes the loader lock is held.
2214 * \returns a \c MonoMethodSignature describing the signature. On error sets
2215 * \p error and returns \c NULL.
2217 MonoMethodSignature
*
2218 mono_metadata_parse_method_signature_full (MonoImage
*m
, MonoGenericContainer
*container
,
2219 int def
, const char *ptr
, const char **rptr
, MonoError
*error
)
2221 MonoMethodSignature
*method
;
2222 int i
, *pattrs
= NULL
;
2223 guint32 hasthis
= 0, explicit_this
= 0, call_convention
, param_count
;
2224 guint32 gen_param_count
= 0;
2225 gboolean is_open
= FALSE
;
2230 gen_param_count
= 1;
2235 call_convention
= *ptr
& 0x0F;
2237 if (gen_param_count
)
2238 gen_param_count
= mono_metadata_decode_value (ptr
, &ptr
);
2239 param_count
= mono_metadata_decode_value (ptr
, &ptr
);
2242 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 */
2244 method
= mono_metadata_signature_alloc (m
, param_count
);
2245 method
->hasthis
= hasthis
;
2246 method
->explicit_this
= explicit_this
;
2247 method
->call_convention
= call_convention
;
2248 method
->generic_param_count
= gen_param_count
;
2250 if (call_convention
!= 0xa) {
2251 method
->ret
= mono_metadata_parse_type_checked (m
, container
, pattrs
? pattrs
[0] : 0, FALSE
, ptr
, &ptr
, error
);
2253 mono_metadata_free_method_signature (method
);
2257 is_open
= mono_class_is_open_constructed_type (method
->ret
);
2260 for (i
= 0; i
< method
->param_count
; ++i
) {
2261 if (*ptr
== MONO_TYPE_SENTINEL
) {
2262 if (method
->call_convention
!= MONO_CALL_VARARG
|| def
) {
2263 mono_error_set_bad_image (error
, m
, "Found sentinel for methoddef or no vararg");
2267 if (method
->sentinelpos
>= 0) {
2268 mono_error_set_bad_image (error
, m
, "Found sentinel twice in the same signature.");
2272 method
->sentinelpos
= i
;
2275 method
->params
[i
] = mono_metadata_parse_type_checked (m
, container
, pattrs
? pattrs
[i
+1] : 0, FALSE
, ptr
, &ptr
, error
);
2276 if (!method
->params
[i
]) {
2277 mono_metadata_free_method_signature (method
);
2282 is_open
= mono_class_is_open_constructed_type (method
->params
[i
]);
2285 /* The sentinel could be missing if the caller does not pass any additional arguments */
2286 if (!def
&& method
->call_convention
== MONO_CALL_VARARG
&& method
->sentinelpos
< 0)
2287 method
->sentinelpos
= method
->param_count
;
2289 method
->has_type_parameters
= is_open
;
2291 if (def
&& (method
->call_convention
== MONO_CALL_VARARG
))
2292 method
->sentinelpos
= method
->param_count
;
2299 * Add signature to a cache and increase ref count...
2306 * mono_metadata_parse_method_signature:
2307 * \param m metadata context
2308 * \param def the \c MethodDef index or 0 for \c Ref signatures.
2309 * \param ptr pointer to the signature metadata representation
2310 * \param rptr pointer updated to match the end of the decoded stream
2312 * Decode a method signature stored at \p ptr.
2313 * This is a Mono runtime internal function.
2315 * LOCKING: Assumes the loader lock is held.
2317 * \returns a \c MonoMethodSignature describing the signature.
2319 MonoMethodSignature
*
2320 mono_metadata_parse_method_signature (MonoImage
*m
, int def
, const char *ptr
, const char **rptr
)
2323 * This function MUST NOT be called by runtime code as it does error handling incorrectly.
2324 * Use mono_metadata_parse_method_signature_full instead.
2325 * It's ok to asser on failure as we no longer use it.
2328 MonoMethodSignature
*ret
;
2329 ret
= mono_metadata_parse_method_signature_full (m
, NULL
, def
, ptr
, rptr
, error
);
2330 mono_error_assert_ok (error
);
2336 * mono_metadata_free_method_signature:
2337 * \param sig signature to destroy
2339 * Free the memory allocated in the signature \p sig.
2340 * This method needs to be robust and work also on partially-built
2341 * signatures, so it does extra checks.
2344 mono_metadata_free_method_signature (MonoMethodSignature
*sig
)
2346 /* Everything is allocated from mempools */
2350 mono_metadata_free_type (sig->ret);
2351 for (i = 0; i < sig->param_count; ++i) {
2352 if (sig->params [i])
2353 mono_metadata_free_type (sig->params [i]);
2359 mono_metadata_free_inflated_signature (MonoMethodSignature
*sig
)
2363 /* Allocated in inflate_generic_signature () */
2365 mono_metadata_free_type (sig
->ret
);
2366 for (i
= 0; i
< sig
->param_count
; ++i
) {
2367 if (sig
->params
[i
])
2368 mono_metadata_free_type (sig
->params
[i
]);
2374 inflated_method_equal (gconstpointer a
, gconstpointer b
)
2376 const MonoMethodInflated
*ma
= (const MonoMethodInflated
*)a
;
2377 const MonoMethodInflated
*mb
= (const MonoMethodInflated
*)b
;
2378 if (ma
->declaring
!= mb
->declaring
)
2380 return mono_metadata_generic_context_equal (&ma
->context
, &mb
->context
);
2384 inflated_method_hash (gconstpointer a
)
2386 const MonoMethodInflated
*ma
= (const MonoMethodInflated
*)a
;
2387 return (mono_metadata_generic_context_hash (&ma
->context
) ^ mono_aligned_addr_hash (ma
->declaring
));
2391 inflated_signature_equal (gconstpointer a
, gconstpointer b
)
2393 const MonoInflatedMethodSignature
*sig1
= (const MonoInflatedMethodSignature
*)a
;
2394 const MonoInflatedMethodSignature
*sig2
= (const MonoInflatedMethodSignature
*)b
;
2396 /* sig->sig is assumed to be canonized */
2397 if (sig1
->sig
!= sig2
->sig
)
2399 /* The generic instances are canonized */
2400 return mono_metadata_generic_context_equal (&sig1
->context
, &sig2
->context
);
2404 inflated_signature_hash (gconstpointer a
)
2406 const MonoInflatedMethodSignature
*sig
= (const MonoInflatedMethodSignature
*)a
;
2408 /* sig->sig is assumed to be canonized */
2409 return mono_metadata_generic_context_hash (&sig
->context
) ^ mono_aligned_addr_hash (sig
->sig
);
2413 dump_ginst (MonoGenericInst *ginst)
2418 g_print ("Ginst: <");
2419 for (i = 0; i < ginst->type_argc; ++i) {
2422 name = mono_type_get_name (ginst->type_argv [i]);
2423 g_print ("%s", name);
2429 static gboolean
type_in_image (MonoType
*type
, MonoImage
*image
);
2432 signature_in_image (MonoMethodSignature
*sig
, MonoImage
*image
)
2434 gpointer iter
= NULL
;
2437 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2438 if (type_in_image (p
, image
))
2441 return type_in_image (mono_signature_get_return_type (sig
), image
);
2445 ginst_in_image (MonoGenericInst
*ginst
, MonoImage
*image
)
2449 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2450 if (type_in_image (ginst
->type_argv
[i
], image
))
2458 gclass_in_image (MonoGenericClass
*gclass
, MonoImage
*image
)
2460 return m_class_get_image (gclass
->container_class
) == image
||
2461 ginst_in_image (gclass
->context
.class_inst
, image
);
2465 type_in_image (MonoType
*type
, MonoImage
*image
)
2468 switch (type
->type
) {
2469 case MONO_TYPE_GENERICINST
:
2470 return gclass_in_image (type
->data
.generic_class
, image
);
2472 type
= type
->data
.type
;
2474 case MONO_TYPE_SZARRAY
:
2475 type
= m_class_get_byval_arg (type
->data
.klass
);
2477 case MONO_TYPE_ARRAY
:
2478 type
= m_class_get_byval_arg (type
->data
.array
->eklass
);
2480 case MONO_TYPE_FNPTR
:
2481 return signature_in_image (type
->data
.method
, image
);
2483 case MONO_TYPE_MVAR
:
2484 return image
== mono_get_image_for_generic_param (type
->data
.generic_param
);
2486 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type_internal () */
2487 return image
== m_class_get_image (mono_class_from_mono_type_internal (type
));
2492 mono_type_in_image (MonoType
*type
, MonoImage
*image
)
2494 return type_in_image (type
, image
);
2498 image_sets_lock (void)
2500 mono_os_mutex_lock (&image_sets_mutex
);
2504 image_sets_unlock (void)
2506 mono_os_mutex_unlock (&image_sets_mutex
);
2510 compare_pointers (const void *a
, const void *b
)
2512 return (size_t)a
- (size_t)b
;
2516 #define HASH_TABLE_SIZE 1103
2517 static MonoImageSet
*img_set_cache
[HASH_TABLE_SIZE
];
2520 mix_hash (uintptr_t source
)
2522 unsigned int hash
= source
;
2525 hash
= (((hash
* 215497) >> 16) ^ ((hash
* 1823231) + hash
));
2527 // Mix in highest bits on 64-bit systems only
2528 if (sizeof (source
) > 4)
2529 hash
= hash
^ (source
>> 32);
2535 hash_images (MonoImage
**images
, int nimages
)
2539 for (i
= 0; i
< nimages
; ++i
)
2540 res
+= mix_hash ((size_t)images
[i
]);
2546 compare_img_set (MonoImageSet
*set
, MonoImage
**images
, int nimages
)
2550 if (set
->nimages
!= nimages
)
2553 for (j
= 0; j
< nimages
; ++j
) {
2554 for (k
= 0; k
< nimages
; ++k
)
2555 if (set
->images
[k
] == images
[j
])
2556 break; // Break on match
2558 // If we iterated all the way through set->images, images[j] was *not* found.
2560 break; // Break on "image not found"
2563 // If we iterated all the way through images without breaking, all items in images were found in set->images
2564 return j
== nimages
;
2568 static MonoImageSet
*
2569 img_set_cache_get (MonoImage
**images
, int nimages
)
2571 guint32 hash_code
= hash_images (images
, nimages
);
2572 int index
= hash_code
% HASH_TABLE_SIZE
;
2573 MonoImageSet
*img
= img_set_cache
[index
];
2574 if (!img
|| !compare_img_set (img
, images
, nimages
)) {
2575 UnlockedIncrement (&img_set_cache_miss
);
2578 UnlockedIncrement (&img_set_cache_hit
);
2583 img_set_cache_add (MonoImageSet
*set
)
2585 guint32 hash_code
= hash_images (set
->images
, set
->nimages
);
2586 int index
= hash_code
% HASH_TABLE_SIZE
;
2587 img_set_cache
[index
] = set
;
2591 img_set_cache_remove (MonoImageSet
*is
)
2593 guint32 hash_code
= hash_images (is
->images
, is
->nimages
);
2594 int index
= hash_code
% HASH_TABLE_SIZE
;
2595 if (img_set_cache
[index
] == is
)
2596 img_set_cache
[index
] = NULL
;
2601 * Return a MonoImageSet representing the set of images in IMAGES.
2603 static MonoImageSet
*
2604 get_image_set (MonoImage
**images
, int nimages
)
2610 /* Common case: Image set contains corlib only. If we've seen that case before, we cached the set. */
2611 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
&& mscorlib_image_set
)
2612 return mscorlib_image_set
;
2614 /* Happens with empty generic instances */
2615 // 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.
2617 return mscorlib_image_set
;
2619 set
= img_set_cache_get (images
, nimages
);
2626 image_sets
= g_ptr_array_new ();
2628 // Before we go on, we should check to see whether a MonoImageSet with these images already exists.
2629 // We can search the referred-by imagesets of any one of our images to do this. Arbitrarily pick one here:
2630 if (images
[0] == mono_defaults
.corlib
&& nimages
> 1)
2631 l
= images
[1]->image_sets
; // Prefer not to search the imagesets of corlib-- that will be a long list.
2633 l
= images
[0]->image_sets
;
2636 while (l
) // Iterate over selected list, looking for an imageset with members equal to our target one
2638 set
= (MonoImageSet
*)l
->data
;
2640 if (set
->nimages
== nimages
) { // Member count differs, this can't be it
2641 // Compare all members to all members-- order might be different
2642 for (j
= 0; j
< nimages
; ++j
) {
2643 for (k
= 0; k
< nimages
; ++k
)
2644 if (set
->images
[k
] == images
[j
])
2645 break; // Break on match
2647 // If we iterated all the way through set->images, images[j] was *not* found.
2649 break; // Break on "image not found"
2652 // If we iterated all the way through images without breaking, all items in images were found in set->images
2654 // Break on "found a set with equal members".
2655 // This happens in case of a hash collision with a previously cached set.
2663 // If we iterated all the way through l without breaking, the imageset does not already exist and we should create it
2665 set
= g_new0 (MonoImageSet
, 1);
2666 set
->nimages
= nimages
;
2667 set
->images
= g_new0 (MonoImage
*, nimages
);
2668 mono_os_mutex_init_recursive (&set
->lock
);
2669 for (i
= 0; i
< nimages
; ++i
)
2670 set
->images
[i
] = images
[i
];
2671 set
->gclass_cache
= mono_conc_hashtable_new_full (mono_generic_class_hash
, mono_generic_class_equal
, NULL
, (GDestroyNotify
)free_generic_class
);
2672 set
->ginst_cache
= g_hash_table_new_full (mono_metadata_generic_inst_hash
, mono_metadata_generic_inst_equal
, NULL
, (GDestroyNotify
)free_generic_inst
);
2673 set
->gmethod_cache
= g_hash_table_new_full (inflated_method_hash
, inflated_method_equal
, NULL
, (GDestroyNotify
)free_inflated_method
);
2674 set
->gsignature_cache
= g_hash_table_new_full (inflated_signature_hash
, inflated_signature_equal
, NULL
, (GDestroyNotify
)free_inflated_signature
);
2676 set
->szarray_cache
= g_hash_table_new_full (mono_aligned_addr_hash
, NULL
, NULL
, NULL
);
2677 set
->array_cache
= g_hash_table_new_full (mono_aligned_addr_hash
, NULL
, NULL
, NULL
);
2679 for (i
= 0; i
< nimages
; ++i
)
2680 set
->images
[i
]->image_sets
= g_slist_prepend (set
->images
[i
]->image_sets
, set
);
2682 g_ptr_array_add (image_sets
, set
);
2683 UnlockedIncrement (&img_set_count
); /* locked by image_sets_lock () */
2686 /* Cache the set. If there was a cache collision, the previously cached value will be replaced. */
2687 img_set_cache_add (set
);
2689 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
) {
2690 mono_memory_barrier ();
2691 mscorlib_image_set
= set
;
2694 image_sets_unlock ();
2700 delete_image_set (MonoImageSet
*set
)
2704 mono_conc_hashtable_destroy (set
->gclass_cache
);
2705 g_hash_table_destroy (set
->ginst_cache
);
2706 g_hash_table_destroy (set
->gmethod_cache
);
2707 g_hash_table_destroy (set
->gsignature_cache
);
2709 g_hash_table_destroy (set
->szarray_cache
);
2710 g_hash_table_destroy (set
->array_cache
);
2712 g_hash_table_destroy (set
->ptr_cache
);
2714 mono_wrapper_caches_free (&set
->wrapper_caches
);
2718 for (i
= 0; i
< set
->nimages
; ++i
)
2719 set
->images
[i
]->image_sets
= g_slist_remove (set
->images
[i
]->image_sets
, set
);
2721 g_ptr_array_remove (image_sets
, set
);
2723 image_sets_unlock ();
2725 img_set_cache_remove (set
);
2728 mono_mempool_destroy (set
->mempool
);
2729 g_free (set
->images
);
2730 mono_os_mutex_destroy (&set
->lock
);
2735 mono_image_set_lock (MonoImageSet
*set
)
2737 mono_os_mutex_lock (&set
->lock
);
2741 mono_image_set_unlock (MonoImageSet
*set
)
2743 mono_os_mutex_unlock (&set
->lock
);
2747 mono_image_set_alloc (MonoImageSet
*set
, guint size
)
2751 mono_image_set_lock (set
);
2753 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2754 res
= mono_mempool_alloc (set
->mempool
, size
);
2755 mono_image_set_unlock (set
);
2761 mono_image_set_alloc0 (MonoImageSet
*set
, guint size
)
2765 mono_image_set_lock (set
);
2767 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2768 res
= mono_mempool_alloc0 (set
->mempool
, size
);
2769 mono_image_set_unlock (set
);
2775 mono_image_set_strdup (MonoImageSet
*set
, const char *s
)
2779 mono_image_set_lock (set
);
2781 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2782 res
= mono_mempool_strdup (set
->mempool
, s
);
2783 mono_image_set_unlock (set
);
2788 // Get a descriptive string for a MonoImageSet
2789 // Callers are obligated to free buffer with g_free after use
2791 mono_image_set_description (MonoImageSet
*set
)
2793 GString
*result
= g_string_new (NULL
);
2795 g_string_append (result
, "[");
2796 for (img
= 0; img
< set
->nimages
; img
++)
2799 g_string_append (result
, ", ");
2800 g_string_append (result
, set
->images
[img
]->name
);
2802 g_string_append (result
, "]");
2803 return g_string_free (result
, FALSE
);
2807 * Structure used by the collect_..._images functions to store the image list.
2810 MonoImage
*image_buf
[64];
2812 int nimages
, images_len
;
2816 collect_data_init (CollectData
*data
)
2818 data
->images
= data
->image_buf
;
2819 data
->images_len
= 64;
2824 collect_data_free (CollectData
*data
)
2826 if (data
->images
!= data
->image_buf
)
2827 g_free (data
->images
);
2831 enlarge_data (CollectData
*data
)
2833 int new_len
= data
->images_len
< 16 ? 16 : data
->images_len
* 2;
2834 MonoImage
**d
= g_new (MonoImage
*, new_len
);
2837 g_assert_not_reached ();
2838 memcpy (d
, data
->images
, data
->images_len
);
2839 if (data
->images
!= data
->image_buf
)
2840 g_free (data
->images
);
2842 data
->images_len
= new_len
;
2846 add_image (MonoImage
*image
, CollectData
*data
)
2850 /* The arrays are small, so use a linear search instead of a hash table */
2851 for (i
= 0; i
< data
->nimages
; ++i
)
2852 if (data
->images
[i
] == image
)
2855 if (data
->nimages
== data
->images_len
)
2856 enlarge_data (data
);
2858 data
->images
[data
->nimages
++] = image
;
2862 collect_type_images (MonoType
*type
, CollectData
*data
);
2865 collect_ginst_images (MonoGenericInst
*ginst
, CollectData
*data
)
2869 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2870 collect_type_images (ginst
->type_argv
[i
], data
);
2875 collect_gclass_images (MonoGenericClass
*gclass
, CollectData
*data
)
2877 add_image (m_class_get_image (gclass
->container_class
), data
);
2878 if (gclass
->context
.class_inst
)
2879 collect_ginst_images (gclass
->context
.class_inst
, data
);
2883 collect_signature_images (MonoMethodSignature
*sig
, CollectData
*data
)
2885 gpointer iter
= NULL
;
2888 collect_type_images (mono_signature_get_return_type (sig
), data
);
2889 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2890 collect_type_images (p
, data
);
2894 collect_inflated_signature_images (MonoInflatedMethodSignature
*sig
, CollectData
*data
)
2896 collect_signature_images (sig
->sig
, data
);
2897 if (sig
->context
.class_inst
)
2898 collect_ginst_images (sig
->context
.class_inst
, data
);
2899 if (sig
->context
.method_inst
)
2900 collect_ginst_images (sig
->context
.method_inst
, data
);
2904 collect_method_images (MonoMethodInflated
*method
, CollectData
*data
)
2906 MonoMethod
*m
= method
->declaring
;
2908 add_image (m_class_get_image (method
->declaring
->klass
), data
);
2909 if (method
->context
.class_inst
)
2910 collect_ginst_images (method
->context
.class_inst
, data
);
2911 if (method
->context
.method_inst
)
2912 collect_ginst_images (method
->context
.method_inst
, data
);
2914 * Dynamic assemblies have no references, so the images they depend on can be unloaded before them.
2916 if (image_is_dynamic (m_class_get_image (m
->klass
)))
2917 collect_signature_images (mono_method_signature_internal (m
), data
);
2921 collect_type_images (MonoType
*type
, CollectData
*data
)
2924 switch (type
->type
) {
2925 case MONO_TYPE_GENERICINST
:
2926 collect_gclass_images (type
->data
.generic_class
, data
);
2929 type
= type
->data
.type
;
2931 case MONO_TYPE_SZARRAY
:
2932 type
= m_class_get_byval_arg (type
->data
.klass
);
2934 case MONO_TYPE_ARRAY
:
2935 type
= m_class_get_byval_arg (type
->data
.array
->eklass
);
2937 case MONO_TYPE_FNPTR
:
2938 //return signature_in_image (type->data.method, image);
2939 g_assert_not_reached ();
2941 case MONO_TYPE_MVAR
:
2943 MonoImage
*image
= mono_get_image_for_generic_param (type
->data
.generic_param
);
2944 add_image (image
, data
);
2947 case MONO_TYPE_CLASS
:
2948 case MONO_TYPE_VALUETYPE
:
2949 add_image (m_class_get_image (mono_class_from_mono_type_internal (type
)), data
);
2952 add_image (mono_defaults
.corlib
, data
);
2959 } CleanForImageUserData
;
2962 steal_gclass_in_image (gpointer key
, gpointer value
, gpointer data
)
2964 MonoGenericClass
*gclass
= (MonoGenericClass
*)key
;
2965 CleanForImageUserData
*user_data
= (CleanForImageUserData
*)data
;
2967 g_assert (gclass_in_image (gclass
, user_data
->image
));
2969 user_data
->list
= g_slist_prepend (user_data
->list
, gclass
);
2974 steal_ginst_in_image (gpointer key
, gpointer value
, gpointer data
)
2976 MonoGenericInst
*ginst
= (MonoGenericInst
*)key
;
2977 CleanForImageUserData
*user_data
= (CleanForImageUserData
*)data
;
2979 // This doesn't work during corlib compilation
2980 //g_assert (ginst_in_image (ginst, user_data->image));
2982 user_data
->list
= g_slist_prepend (user_data
->list
, ginst
);
2987 inflated_method_in_image (gpointer key
, gpointer value
, gpointer data
)
2989 MonoImage
*image
= (MonoImage
*)data
;
2990 MonoMethodInflated
*method
= (MonoMethodInflated
*)key
;
2993 // https://bugzilla.novell.com/show_bug.cgi?id=458168
2994 g_assert (m_class_get_image (method
->declaring
->klass
) == image
||
2995 (method
->context
.class_inst
&& ginst_in_image (method
->context
.class_inst
, image
)) ||
2996 (method
->context
.method_inst
&& ginst_in_image (method
->context
.method_inst
, image
)) || (((MonoMethod
*)method
)->signature
&& signature_in_image (mono_method_signature_internal ((MonoMethod
*)method
), image
)));
3002 inflated_signature_in_image (gpointer key
, gpointer value
, gpointer data
)
3004 MonoImage
*image
= (MonoImage
*)data
;
3005 MonoInflatedMethodSignature
*sig
= (MonoInflatedMethodSignature
*)key
;
3007 return signature_in_image (sig
->sig
, image
) ||
3008 (sig
->context
.class_inst
&& ginst_in_image (sig
->context
.class_inst
, image
)) ||
3009 (sig
->context
.method_inst
&& ginst_in_image (sig
->context
.method_inst
, image
));
3013 class_in_image (gpointer key
, gpointer value
, gpointer data
)
3015 MonoImage
*image
= (MonoImage
*)data
;
3016 MonoClass
*klass
= (MonoClass
*)key
;
3018 g_assert (type_in_image (m_class_get_byval_arg (klass
), image
));
3024 check_gmethod (gpointer key
, gpointer value
, gpointer data
)
3026 MonoMethodInflated
*method
= (MonoMethodInflated
*)key
;
3027 MonoImage
*image
= (MonoImage
*)data
;
3029 if (method
->context
.class_inst
)
3030 g_assert (!ginst_in_image (method
->context
.class_inst
, image
));
3031 if (method
->context
.method_inst
)
3032 g_assert (!ginst_in_image (method
->context
.method_inst
, image
));
3033 if (((MonoMethod
*)method
)->signature
)
3034 g_assert (!signature_in_image (mono_method_signature_internal ((MonoMethod
*)method
), image
));
3040 * Run a consistency check on the image set data structures.
3042 static G_GNUC_UNUSED
void
3043 check_image_sets (MonoImage
*image
)
3046 GSList
*l
= image
->image_sets
;
3051 for (i
= 0; i
< image_sets
->len
; ++i
) {
3052 MonoImageSet
*set
= (MonoImageSet
*)g_ptr_array_index (image_sets
, i
);
3054 if (!g_slist_find (l
, set
)) {
3055 g_hash_table_foreach (set
->gmethod_cache
, check_gmethod
, image
);
3061 mono_metadata_clean_for_image (MonoImage
*image
)
3063 CleanForImageUserData ginst_data
, gclass_data
;
3064 GSList
*l
, *set_list
;
3066 //check_image_sets (image);
3069 * The data structures could reference each other so we delete them in two phases.
3070 * This is required because of the hashing functions in gclass/ginst_cache.
3072 ginst_data
.image
= gclass_data
.image
= image
;
3073 ginst_data
.list
= gclass_data
.list
= NULL
;
3075 /* Collect the items to delete */
3076 /* delete_image_set () modifies the lists so make a copy */
3077 for (l
= image
->image_sets
; l
; l
= l
->next
) {
3078 MonoImageSet
*set
= (MonoImageSet
*)l
->data
;
3080 mono_image_set_lock (set
);
3081 mono_conc_hashtable_foreach_steal (set
->gclass_cache
, steal_gclass_in_image
, &gclass_data
);
3082 g_hash_table_foreach_steal (set
->ginst_cache
, steal_ginst_in_image
, &ginst_data
);
3083 g_hash_table_foreach_remove (set
->gmethod_cache
, inflated_method_in_image
, image
);
3084 g_hash_table_foreach_remove (set
->gsignature_cache
, inflated_signature_in_image
, image
);
3086 g_hash_table_foreach_steal (set
->szarray_cache
, class_in_image
, image
);
3087 g_hash_table_foreach_steal (set
->array_cache
, class_in_image
, image
);
3089 g_hash_table_foreach_steal (set
->ptr_cache
, class_in_image
, image
);
3090 mono_image_set_unlock (set
);
3093 /* Delete the removed items */
3094 for (l
= ginst_data
.list
; l
; l
= l
->next
)
3095 free_generic_inst ((MonoGenericInst
*)l
->data
);
3096 for (l
= gclass_data
.list
; l
; l
= l
->next
)
3097 free_generic_class ((MonoGenericClass
*)l
->data
);
3098 g_slist_free (ginst_data
.list
);
3099 g_slist_free (gclass_data
.list
);
3100 /* delete_image_set () modifies the lists so make a copy */
3101 set_list
= g_slist_copy (image
->image_sets
);
3102 for (l
= set_list
; l
; l
= l
->next
) {
3103 MonoImageSet
*set
= (MonoImageSet
*)l
->data
;
3105 delete_image_set (set
);
3107 g_slist_free (set_list
);
3111 free_inflated_method (MonoMethodInflated
*imethod
)
3113 MonoMethod
*method
= (MonoMethod
*)imethod
;
3115 if (method
->signature
)
3116 mono_metadata_free_inflated_signature (method
->signature
);
3118 if (method
->wrapper_type
)
3119 g_free (((MonoMethodWrapper
*)method
)->method_data
);
3125 free_generic_inst (MonoGenericInst
*ginst
)
3129 /* The ginst itself is allocated from the image set mempool */
3130 for (i
= 0; i
< ginst
->type_argc
; ++i
)
3131 mono_metadata_free_type (ginst
->type_argv
[i
]);
3135 free_generic_class (MonoGenericClass
*gclass
)
3137 /* The gclass itself is allocated from the image set mempool */
3138 if (gclass
->cached_class
&& m_class_get_interface_id (gclass
->cached_class
))
3139 mono_unload_interface_id (gclass
->cached_class
);
3143 free_inflated_signature (MonoInflatedMethodSignature
*sig
)
3145 mono_metadata_free_inflated_signature (sig
->sig
);
3150 * mono_metadata_get_inflated_signature:
3152 * Given an inflated signature and a generic context, return a canonical copy of the
3153 * signature. The returned signature might be equal to SIG or it might be a cached copy.
3155 MonoMethodSignature
*
3156 mono_metadata_get_inflated_signature (MonoMethodSignature
*sig
, MonoGenericContext
*context
)
3158 MonoInflatedMethodSignature helper
;
3159 MonoInflatedMethodSignature
*res
;
3164 helper
.context
.class_inst
= context
->class_inst
;
3165 helper
.context
.method_inst
= context
->method_inst
;
3167 collect_data_init (&data
);
3169 collect_inflated_signature_images (&helper
, &data
);
3171 set
= get_image_set (data
.images
, data
.nimages
);
3173 collect_data_free (&data
);
3175 mono_image_set_lock (set
);
3177 res
= (MonoInflatedMethodSignature
*)g_hash_table_lookup (set
->gsignature_cache
, &helper
);
3179 res
= g_new0 (MonoInflatedMethodSignature
, 1);
3181 res
->context
.class_inst
= context
->class_inst
;
3182 res
->context
.method_inst
= context
->method_inst
;
3183 g_hash_table_insert (set
->gsignature_cache
, res
, res
);
3186 mono_image_set_unlock (set
);
3192 mono_metadata_get_image_set_for_class (MonoClass
*klass
)
3195 CollectData image_set_data
;
3197 collect_data_init (&image_set_data
);
3198 collect_type_images (m_class_get_byval_arg (klass
), &image_set_data
);
3199 set
= get_image_set (image_set_data
.images
, image_set_data
.nimages
);
3200 collect_data_free (&image_set_data
);
3206 mono_metadata_get_image_set_for_method (MonoMethodInflated
*method
)
3209 CollectData image_set_data
;
3211 collect_data_init (&image_set_data
);
3212 collect_method_images (method
, &image_set_data
);
3213 set
= get_image_set (image_set_data
.images
, image_set_data
.nimages
);
3214 collect_data_free (&image_set_data
);
3220 type_is_gtd (MonoType
*type
)
3222 switch (type
->type
) {
3223 case MONO_TYPE_CLASS
:
3224 case MONO_TYPE_VALUETYPE
:
3225 return mono_class_is_gtd (type
->data
.klass
);
3232 * mono_metadata_get_generic_inst:
3234 * Given a list of types, return a MonoGenericInst that represents that list.
3235 * The returned MonoGenericInst has its own copy of the list of types. The list
3236 * passed in the argument can be freed, modified or disposed of.
3240 mono_metadata_get_generic_inst (int type_argc
, MonoType
**type_argv
)
3242 MonoGenericInst
*ginst
;
3245 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
3247 for (i
= 0; i
< type_argc
; ++i
)
3248 if (mono_class_is_open_constructed_type (type_argv
[i
]))
3250 is_open
= (i
< type_argc
);
3252 ginst
= (MonoGenericInst
*)g_alloca (size
);
3253 memset (ginst
, 0, sizeof (MonoGenericInst
));
3254 ginst
->is_open
= is_open
;
3255 ginst
->type_argc
= type_argc
;
3256 memcpy (ginst
->type_argv
, type_argv
, type_argc
* sizeof (MonoType
*));
3258 for (i
= 0; i
< type_argc
; ++i
) {
3259 MonoType
*t
= ginst
->type_argv
[i
];
3260 if (type_is_gtd (t
)) {
3261 ginst
->type_argv
[i
] = mono_class_gtd_get_canonical_inst (t
->data
.klass
);
3265 return mono_metadata_get_canonical_generic_inst (ginst
);
3270 * mono_metadata_get_canonical_generic_inst:
3271 * \param candidate an arbitrary generic instantiation
3273 * \returns the canonical generic instantiation that represents the given
3274 * candidate by identifying the image set for the candidate instantiation and
3275 * finding the instance in the image set or adding a copy of the given instance
3278 * The returned MonoGenericInst has its own copy of the list of types. The list
3279 * passed in the argument can be freed, modified or disposed of.
3283 mono_metadata_get_canonical_generic_inst (MonoGenericInst
*candidate
)
3286 int type_argc
= candidate
->type_argc
;
3287 gboolean is_open
= candidate
->is_open
;
3290 collect_data_init (&data
);
3292 collect_ginst_images (candidate
, &data
);
3294 set
= get_image_set (data
.images
, data
.nimages
);
3296 collect_data_free (&data
);
3298 mono_image_set_lock (set
);
3300 MonoGenericInst
*ginst
= (MonoGenericInst
*)g_hash_table_lookup (set
->ginst_cache
, candidate
);
3302 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
3303 ginst
= (MonoGenericInst
*)mono_image_set_alloc0 (set
, size
);
3304 #ifndef MONO_SMALL_CONFIG
3305 ginst
->id
= mono_atomic_inc_i32 (&next_generic_inst_id
);
3307 ginst
->is_open
= is_open
;
3308 ginst
->type_argc
= type_argc
;
3310 for (int i
= 0; i
< type_argc
; ++i
)
3311 ginst
->type_argv
[i
] = mono_metadata_type_dup (NULL
, candidate
->type_argv
[i
]);
3313 g_hash_table_insert (set
->ginst_cache
, ginst
, ginst
);
3316 mono_image_set_unlock (set
);
3321 mono_metadata_is_type_builder_generic_type_definition (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
3323 MonoGenericContainer
*container
= mono_class_get_generic_container (container_class
);
3325 if (!is_dynamic
|| m_class_was_typebuilder (container_class
) || container
->type_argc
!= inst
->type_argc
)
3327 return inst
== container
->context
.class_inst
;
3331 * mono_metadata_lookup_generic_class:
3333 * Returns a MonoGenericClass with the given properties.
3337 mono_metadata_lookup_generic_class (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
3339 MonoGenericClass
*gclass
;
3340 MonoGenericClass helper
;
3341 gboolean is_tb_open
= mono_metadata_is_type_builder_generic_type_definition (container_class
, inst
, is_dynamic
);
3345 g_assert (mono_class_get_generic_container (container_class
)->type_argc
== inst
->type_argc
);
3347 memset (&helper
, 0, sizeof(helper
)); // act like g_new0
3348 helper
.container_class
= container_class
;
3349 helper
.context
.class_inst
= inst
;
3350 helper
.is_dynamic
= is_dynamic
; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
3351 helper
.is_tb_open
= is_tb_open
;
3353 collect_data_init (&data
);
3355 collect_gclass_images (&helper
, &data
);
3357 set
= get_image_set (data
.images
, data
.nimages
);
3359 collect_data_free (&data
);
3361 gclass
= (MonoGenericClass
*)mono_conc_hashtable_lookup (set
->gclass_cache
, &helper
);
3363 /* A tripwire just to keep us honest */
3364 g_assert (!helper
.cached_class
);
3369 gclass
= mono_image_set_new0 (set
, MonoGenericClass
, 1);
3371 gclass
->is_dynamic
= 1;
3373 gclass
->is_tb_open
= is_tb_open
;
3374 gclass
->container_class
= container_class
;
3375 gclass
->context
.class_inst
= inst
;
3376 gclass
->context
.method_inst
= NULL
;
3377 gclass
->owner
= set
;
3378 if (inst
== mono_class_get_generic_container (container_class
)->context
.class_inst
&& !is_tb_open
)
3379 gclass
->cached_class
= container_class
;
3381 mono_image_set_lock (set
);
3383 MonoGenericClass
*gclass2
= (MonoGenericClass
*)mono_conc_hashtable_insert (set
->gclass_cache
, gclass
, gclass
);
3387 // g_hash_table_insert (set->gclass_cache, gclass, gclass);
3389 mono_image_set_unlock (set
);
3395 * mono_metadata_inflate_generic_inst:
3397 * Instantiate the generic instance @ginst with the context @context.
3398 * Check @error for success.
3402 mono_metadata_inflate_generic_inst (MonoGenericInst
*ginst
, MonoGenericContext
*context
, MonoError
*error
)
3404 MonoType
**type_argv
;
3405 MonoGenericInst
*nginst
= NULL
;
3410 if (!ginst
->is_open
)
3413 type_argv
= g_new0 (MonoType
*, ginst
->type_argc
);
3415 for (i
= 0; i
< ginst
->type_argc
; i
++) {
3416 type_argv
[i
] = mono_class_inflate_generic_type_checked (ginst
->type_argv
[i
], context
, error
);
3417 if (!mono_error_ok (error
))
3422 nginst
= mono_metadata_get_generic_inst (ginst
->type_argc
, type_argv
);
3425 for (i
= 0; i
< count
; i
++)
3426 mono_metadata_free_type (type_argv
[i
]);
3433 mono_metadata_parse_generic_inst (MonoImage
*m
, MonoGenericContainer
*container
,
3434 int count
, const char *ptr
, const char **rptr
, MonoError
*error
)
3436 MonoType
**type_argv
;
3437 MonoGenericInst
*ginst
= NULL
;
3438 int i
, parse_count
= 0;
3441 type_argv
= g_new0 (MonoType
*, count
);
3443 for (i
= 0; i
< count
; i
++) {
3444 /* this can be a transient type, mono_metadata_get_generic_inst will allocate
3445 * a canonical one, if needed.
3447 MonoType
*t
= mono_metadata_parse_type_checked (m
, container
, 0, TRUE
, ptr
, &ptr
, error
);
3457 g_assert (parse_count
== count
);
3458 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
3461 for (i
= 0; i
< parse_count
; i
++)
3462 mono_metadata_free_type (type_argv
[i
]);
3469 do_mono_metadata_parse_generic_class (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
3470 const char *ptr
, const char **rptr
, MonoError
*error
)
3472 MonoGenericInst
*inst
;
3479 // XXX how about transient?
3480 gtype
= mono_metadata_parse_type_checked (m
, NULL
, 0, FALSE
, ptr
, &ptr
, error
);
3484 gklass
= mono_class_from_mono_type_internal (gtype
);
3485 if (!mono_class_is_gtd (gklass
)) {
3486 mono_error_set_bad_image (error
, m
, "Generic instance with non-generic definition");
3490 count
= mono_metadata_decode_value (ptr
, &ptr
);
3491 inst
= mono_metadata_parse_generic_inst (m
, container
, count
, ptr
, &ptr
, error
);
3498 type
->data
.generic_class
= mono_metadata_lookup_generic_class (gklass
, inst
, FALSE
);
3504 * @gc: The generic container to normalize
3505 * @type: The kind of generic parameters the resulting generic-container should contain
3508 static MonoGenericContainer
*
3509 select_container (MonoGenericContainer
*gc
, MonoTypeEnum type
)
3511 gboolean is_var
= (type
== MONO_TYPE_VAR
);
3515 g_assert (is_var
|| type
== MONO_TYPE_MVAR
);
3518 if (gc
->is_method
|| gc
->parent
)
3520 * The current MonoGenericContainer is a generic method -> its `parent'
3521 * points to the containing class'es container.
3529 MonoGenericContainer
*
3530 mono_get_anonymous_container_for_image (MonoImage
*image
, gboolean is_mvar
)
3532 MonoGenericContainer
**container_pointer
;
3534 container_pointer
= &image
->anonymous_generic_method_container
;
3536 container_pointer
= &image
->anonymous_generic_class_container
;
3537 MonoGenericContainer
*result
= *container_pointer
;
3539 // This container has never been created; make it now.
3542 // Note this is never deallocated anywhere-- it exists for the lifetime of the image it's allocated from
3543 result
= (MonoGenericContainer
*)mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
3544 result
->owner
.image
= image
;
3545 result
->is_anonymous
= TRUE
;
3546 result
->is_method
= is_mvar
;
3548 // If another thread already made a container, use that and leak this new one.
3549 // (Technically it would currently be safe to just assign instead of CASing.)
3550 MonoGenericContainer
*exchange
= (MonoGenericContainer
*)mono_atomic_cas_ptr ((volatile gpointer
*)container_pointer
, result
, NULL
);
3557 #define FAST_GPARAM_CACHE_SIZE 16
3559 static MonoGenericParam
*
3560 lookup_anon_gparam (MonoImage
*image
, MonoGenericContainer
*container
, gint32 param_num
, gboolean is_mvar
)
3562 if (param_num
>= 0 && param_num
< FAST_GPARAM_CACHE_SIZE
) {
3563 MonoGenericParam
*cache
= is_mvar
? image
->mvar_gparam_cache_fast
: image
->var_gparam_cache_fast
;
3566 return &cache
[param_num
];
3568 MonoGenericParam key
;
3569 memset (&key
, 0, sizeof (key
));
3570 key
.owner
= container
;
3571 key
.num
= param_num
;
3572 key
.gshared_constraint
= NULL
;
3573 MonoConcurrentHashTable
*cache
= is_mvar
? image
->mvar_gparam_cache
: image
->var_gparam_cache
;
3576 return (MonoGenericParam
*)mono_conc_hashtable_lookup (cache
, &key
);
3580 static MonoGenericParam
*
3581 publish_anon_gparam_fast (MonoImage
*image
, MonoGenericContainer
*container
, gint32 param_num
)
3583 g_assert (param_num
>= 0 && param_num
< FAST_GPARAM_CACHE_SIZE
);
3584 MonoGenericParam
**cache
= container
->is_method
? &image
->mvar_gparam_cache_fast
: &image
->var_gparam_cache_fast
;
3586 mono_image_lock (image
);
3588 *cache
= (MonoGenericParam
*)mono_image_alloc0 (image
, sizeof (MonoGenericParam
) * FAST_GPARAM_CACHE_SIZE
);
3589 for (gint32 i
= 0; i
< FAST_GPARAM_CACHE_SIZE
; ++i
) {
3590 MonoGenericParam
*param
= &(*cache
)[i
];
3591 param
->owner
= container
;
3595 mono_image_unlock (image
);
3597 return &(*cache
)[param_num
];
3601 * publish_anon_gparam_slow:
3603 * Publish \p gparam anonymous generic parameter to the anon gparam cache for \p image.
3605 * LOCKING: takes the image lock.
3607 static MonoGenericParam
*
3608 publish_anon_gparam_slow (MonoImage
*image
, MonoGenericParam
*gparam
)
3610 MonoConcurrentHashTable
**cache
= gparam
->owner
->is_method
? &image
->mvar_gparam_cache
: &image
->var_gparam_cache
;
3612 mono_image_lock (image
);
3614 MonoConcurrentHashTable
*ht
= mono_conc_hashtable_new ((GHashFunc
)mono_metadata_generic_param_hash
,
3615 (GEqualFunc
) mono_metadata_generic_param_equal
);
3616 mono_atomic_store_release (cache
, ht
);
3618 mono_image_unlock (image
);
3620 MonoGenericParam
*other
= (MonoGenericParam
*)mono_conc_hashtable_insert (*cache
, gparam
, gparam
);
3621 // If another thread published first return their param, otherwise return ours.
3622 return other
? other
: gparam
;
3626 * mono_metadata_create_anon_gparam:
3627 * \param image the MonoImage that owns the anonymous generic parameter
3628 * \param param_num the parameter number
3629 * \param is_mvar TRUE if this is a method generic parameter, FALSE if it's a class generic parameter.
3631 * Returns: a new, or exisisting \c MonoGenericParam for an anonymous generic parameter with the given properties.
3633 * LOCKING: takes the image lock.
3636 mono_metadata_create_anon_gparam (MonoImage
*image
, gint32 param_num
, gboolean is_mvar
)
3638 MonoGenericContainer
*container
= mono_get_anonymous_container_for_image (image
, is_mvar
);
3639 MonoGenericParam
*gparam
= lookup_anon_gparam (image
, container
, param_num
, is_mvar
);
3642 if (param_num
>= 0 && param_num
< FAST_GPARAM_CACHE_SIZE
) {
3643 return publish_anon_gparam_fast (image
, container
, param_num
);
3645 // Create a candidate generic param and try to insert it in the cache.
3646 // If multiple threads both try to publish the same param, all but one
3647 // will leak, but that's okay.
3648 gparam
= (MonoGenericParam
*)mono_image_alloc0 (image
, sizeof (MonoGenericParam
));
3649 gparam
->owner
= container
;
3650 gparam
->num
= param_num
;
3652 return publish_anon_gparam_slow (image
, gparam
);
3657 * mono_metadata_parse_generic_param:
3658 * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3659 * see mono_metadata_parse_type_checked() for details.
3660 * Internal routine to parse a generic type parameter.
3661 * LOCKING: Acquires the loader lock
3663 static MonoGenericParam
*
3664 mono_metadata_parse_generic_param (MonoImage
*m
, MonoGenericContainer
*generic_container
,
3665 MonoTypeEnum type
, const char *ptr
, const char **rptr
, MonoError
*error
)
3667 int index
= mono_metadata_decode_value (ptr
, &ptr
);
3673 generic_container
= select_container (generic_container
, type
);
3674 if (!generic_container
) {
3675 gboolean is_mvar
= FALSE
;
3680 case MONO_TYPE_MVAR
:
3684 g_error ("Cerating generic param object with invalid MonoType"); // This is not a generic param
3687 return mono_metadata_create_anon_gparam (m
, index
, is_mvar
);
3690 if (index
>= generic_container
->type_argc
) {
3691 mono_error_set_bad_image (error
, m
, "Invalid generic %s parameter index %d, max index is %d",
3692 generic_container
->is_method
? "method" : "type",
3693 index
, generic_container
->type_argc
);
3697 //This can't return NULL
3698 return mono_generic_container_get_param (generic_container
, index
);
3702 * mono_metadata_get_shared_type:
3704 * Return a shared instance of TYPE, if available, NULL otherwise.
3705 * Shared MonoType instances help save memory. Their contents should not be modified
3706 * by the caller. They do not need to be freed as their lifetime is bound by either
3707 * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3708 * instance they are embedded in. If they are freed, they should be freed using
3709 * mono_metadata_free_type () instead of g_free ().
3712 mono_metadata_get_shared_type (MonoType
*type
)
3716 /* No need to use locking since nobody is modifying the hash table */
3717 if ((cached
= (MonoType
*)g_hash_table_lookup (type_cache
, type
)))
3720 switch (type
->type
){
3721 case MONO_TYPE_CLASS
:
3722 case MONO_TYPE_VALUETYPE
:
3723 if (type
== m_class_get_byval_arg (type
->data
.klass
))
3725 if (type
== m_class_get_this_arg (type
->data
.klass
))
3736 compare_type_literals (MonoImage
*image
, int class_type
, int type_type
, MonoError
*error
)
3740 /* _byval_arg.type can be zero if we're decoding a type that references a class been loading.
3741 * See mcs/test/gtest-440. and #650936.
3742 * FIXME This better be moved to the metadata verifier as it can catch more cases.
3746 /* NET 1.1 assemblies might encode string and object in a denormalized way.
3749 if (class_type
== type_type
)
3752 if (type_type
== MONO_TYPE_CLASS
) {
3753 if (class_type
== MONO_TYPE_STRING
|| class_type
== MONO_TYPE_OBJECT
)
3755 //XXX stringify this argument
3756 mono_error_set_bad_image (error
, image
, "Expected reference type but got type kind %d", class_type
);
3760 g_assert (type_type
== MONO_TYPE_VALUETYPE
);
3761 switch (class_type
) {
3762 case MONO_TYPE_BOOLEAN
:
3763 case MONO_TYPE_CHAR
:
3776 case MONO_TYPE_CLASS
:
3779 //XXX stringify this argument
3780 mono_error_set_bad_image (error
, image
, "Expected value type but got type kind %d", class_type
);
3786 verify_var_type_and_container (MonoImage
*image
, int var_type
, MonoGenericContainer
*container
, MonoError
*error
)
3789 if (var_type
== MONO_TYPE_MVAR
) {
3790 if (!container
->is_method
) { //MVAR and a method container
3791 mono_error_set_bad_image (error
, image
, "MVAR parsed in a context without a method container");
3795 if (!(!container
->is_method
|| //VAR and class container
3796 (container
->is_method
&& container
->parent
))) { //VAR and method container with parent
3797 mono_error_set_bad_image (error
, image
, "VAR parsed in a context without a class container");
3805 * do_mono_metadata_parse_type:
3806 * @type: MonoType to be filled in with the return value
3808 * @generic_context: generics_context
3809 * @transient: whenever to allocate data from the heap
3810 * @ptr: pointer to the encoded type
3811 * @rptr: pointer where the end of the encoded type is saved
3813 * Internal routine used to "fill" the contents of @type from an
3814 * allocated pointer. This is done this way to avoid doing too
3815 * many mini-allocations (particularly for the MonoFieldType which
3816 * most of the time is just a MonoType, but sometimes might be augmented).
3818 * This routine is used by mono_metadata_parse_type and
3819 * mono_metadata_parse_field_type
3821 * This extracts a Type as specified in Partition II (22.2.12)
3823 * Returns: FALSE if the type could not be loaded
3826 do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
3827 gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
3831 type
->type
= (MonoTypeEnum
)mono_metadata_decode_value (ptr
, &ptr
);
3833 switch (type
->type
){
3834 case MONO_TYPE_VOID
:
3835 case MONO_TYPE_BOOLEAN
:
3836 case MONO_TYPE_CHAR
:
3849 case MONO_TYPE_STRING
:
3850 case MONO_TYPE_OBJECT
:
3851 case MONO_TYPE_TYPEDBYREF
:
3853 case MONO_TYPE_VALUETYPE
:
3854 case MONO_TYPE_CLASS
: {
3857 token
= mono_metadata_parse_typedef_or_ref (m
, ptr
, &ptr
);
3858 klass
= mono_class_get_checked (m
, token
, error
);
3859 type
->data
.klass
= klass
;
3863 if (!compare_type_literals (m
, m_class_get_byval_arg (klass
)->type
, type
->type
, error
))
3868 case MONO_TYPE_SZARRAY
: {
3869 MonoType
*etype
= mono_metadata_parse_type_checked (m
, container
, 0, transient
, ptr
, &ptr
, error
);
3873 type
->data
.klass
= mono_class_from_mono_type_internal (etype
);
3876 mono_metadata_free_type (etype
);
3878 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.
3881 case MONO_TYPE_PTR
: {
3882 type
->data
.type
= mono_metadata_parse_type_checked (m
, container
, 0, transient
, ptr
, &ptr
, error
);
3883 if (!type
->data
.type
)
3887 case MONO_TYPE_FNPTR
: {
3888 type
->data
.method
= mono_metadata_parse_method_signature_full (m
, container
, 0, ptr
, &ptr
, error
);
3889 if (!type
->data
.method
)
3893 case MONO_TYPE_ARRAY
: {
3894 type
->data
.array
= mono_metadata_parse_array_internal (m
, container
, transient
, ptr
, &ptr
, error
);
3895 if (!type
->data
.array
)
3899 case MONO_TYPE_MVAR
:
3900 case MONO_TYPE_VAR
: {
3901 if (container
&& !verify_var_type_and_container (m
, type
->type
, container
, error
))
3904 type
->data
.generic_param
= mono_metadata_parse_generic_param (m
, container
, type
->type
, ptr
, &ptr
, error
);
3905 if (!type
->data
.generic_param
)
3910 case MONO_TYPE_GENERICINST
: {
3911 if (!do_mono_metadata_parse_generic_class (type
, m
, container
, ptr
, &ptr
, error
))
3916 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
);
3926 * mono_metadata_free_type:
3927 * \param type type to free
3929 * Free the memory allocated for type \p type which is allocated on the heap.
3932 mono_metadata_free_type (MonoType
*type
)
3934 if (type
>= builtin_types
&& type
< builtin_types
+ NBUILTIN_TYPES ())
3937 switch (type
->type
){
3938 case MONO_TYPE_OBJECT
:
3939 case MONO_TYPE_STRING
:
3940 if (!type
->data
.klass
)
3943 case MONO_TYPE_CLASS
:
3944 case MONO_TYPE_VALUETYPE
:
3945 if (type
== m_class_get_byval_arg (type
->data
.klass
) || type
== m_class_get_this_arg (type
->data
.klass
))
3949 mono_metadata_free_type (type
->data
.type
);
3951 case MONO_TYPE_FNPTR
:
3952 mono_metadata_free_method_signature (type
->data
.method
);
3954 case MONO_TYPE_ARRAY
:
3955 mono_metadata_free_array (type
->data
.array
);
3966 hex_dump (const char *buffer
, int base
, int count
)
3968 int show_header
= 1;
3976 for (i
= 0; i
< count
; i
++){
3979 printf ("\n0x%08x: ", (unsigned char) base
+ i
);
3981 printf ("%02x ", (unsigned char) (buffer
[i
]));
3988 * @ptr: Points to the beginning of the Section Data (25.3)
3990 static MonoExceptionClause
*
3991 parse_section_data (MonoImage
*m
, int *num_clauses
, const unsigned char *ptr
, MonoError
*error
)
3993 unsigned char sect_data_flags
;
3995 guint32 sect_data_len
;
3996 MonoExceptionClause
* clauses
= NULL
;
4001 /* align on 32-bit boundary */
4002 ptr
= dword_align (ptr
);
4003 sect_data_flags
= *ptr
;
4006 is_fat
= sect_data_flags
& METHOD_HEADER_SECTION_FAT_FORMAT
;
4008 sect_data_len
= (ptr
[2] << 16) | (ptr
[1] << 8) | ptr
[0];
4011 sect_data_len
= ptr
[0];
4015 if (sect_data_flags
& METHOD_HEADER_SECTION_EHTABLE
) {
4016 const unsigned char *p
= dword_align (ptr
);
4018 *num_clauses
= is_fat
? sect_data_len
/ 24: sect_data_len
/ 12;
4019 /* we could just store a pointer if we don't need to byteswap */
4020 clauses
= (MonoExceptionClause
*)g_malloc0 (sizeof (MonoExceptionClause
) * (*num_clauses
));
4021 for (i
= 0; i
< *num_clauses
; ++i
) {
4022 MonoExceptionClause
*ec
= &clauses
[i
];
4025 ec
->flags
= read32 (p
);
4026 ec
->try_offset
= read32 (p
+ 4);
4027 ec
->try_len
= read32 (p
+ 8);
4028 ec
->handler_offset
= read32 (p
+ 12);
4029 ec
->handler_len
= read32 (p
+ 16);
4030 tof_value
= read32 (p
+ 20);
4033 ec
->flags
= read16 (p
);
4034 ec
->try_offset
= read16 (p
+ 2);
4035 ec
->try_len
= *(p
+ 4);
4036 ec
->handler_offset
= read16 (p
+ 5);
4037 ec
->handler_len
= *(p
+ 7);
4038 tof_value
= read32 (p
+ 8);
4041 if (ec
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
) {
4042 ec
->data
.filter_offset
= tof_value
;
4043 } else if (ec
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) {
4044 ec
->data
.catch_class
= NULL
;
4046 ec
->data
.catch_class
= mono_class_get_checked (m
, tof_value
, error
);
4047 if (!is_ok (error
)) {
4053 ec
->data
.catch_class
= NULL
;
4055 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
4059 if (sect_data_flags
& METHOD_HEADER_SECTION_MORE_SECTS
)
4060 ptr
+= sect_data_len
- 4; /* LAMESPEC: it seems the size includes the header */
4067 * mono_method_get_header_summary:
4068 * @method: The method to get the header.
4069 * @summary: Where to store the header
4072 * Returns: TRUE if the header was properly decoded.
4075 mono_method_get_header_summary (MonoMethod
*method
, MonoMethodHeaderSummary
*summary
)
4081 unsigned char flags
, format
;
4085 /*Only the GMD has a pointer to the metadata.*/
4086 while (method
->is_inflated
)
4087 method
= ((MonoMethodInflated
*)method
)->declaring
;
4089 summary
->code
= NULL
;
4090 summary
->code_size
= 0;
4091 summary
->max_stack
= 0;
4092 summary
->has_clauses
= FALSE
;
4093 summary
->has_locals
= FALSE
;
4095 /*FIXME extract this into a MACRO and share it with mono_method_get_header*/
4096 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
))
4099 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| method
->sre_method
) {
4100 MonoMethodHeader
*header
= ((MonoMethodWrapper
*)method
)->header
;
4103 summary
->code
= header
->code
;
4104 summary
->code_size
= header
->code_size
;
4105 summary
->max_stack
= header
->max_stack
;
4106 summary
->has_clauses
= header
->num_clauses
> 0;
4107 summary
->has_locals
= header
->num_locals
> 0;
4112 idx
= mono_metadata_token_index (method
->token
);
4113 img
= m_class_get_image (method
->klass
);
4114 rva
= mono_metadata_decode_row_col (&img
->tables
[MONO_TABLE_METHOD
], idx
- 1, MONO_METHOD_RVA
);
4116 /*We must run the verifier since we'll be decoding it.*/
4117 if (!mono_verifier_verify_method_header (img
, rva
, error
)) {
4118 mono_error_cleanup (error
);
4122 ptr
= mono_image_rva_map (img
, rva
);
4126 flags
= *(const unsigned char *)ptr
;
4127 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
4130 case METHOD_HEADER_TINY_FORMAT
:
4132 summary
->max_stack
= 8;
4133 summary
->code
= (unsigned char *) ptr
;
4134 summary
->code_size
= flags
>> 2;
4136 case METHOD_HEADER_FAT_FORMAT
:
4137 fat_flags
= read16 (ptr
);
4139 summary
->max_stack
= read16 (ptr
);
4141 summary
->code_size
= read32 (ptr
);
4143 summary
->has_locals
= !!read32 (ptr
);
4145 if (fat_flags
& METHOD_HEADER_MORE_SECTS
)
4146 summary
->has_clauses
= TRUE
;
4147 summary
->code
= (unsigned char *) ptr
;
4156 * mono_metadata_parse_mh_full:
4157 * @m: metadata context
4158 * @generic_context: generics context
4159 * @ptr: pointer to the method header.
4161 * Decode the method header at @ptr, including pointer to the IL code,
4162 * info about local variables and optional exception tables.
4163 * This is a Mono runtime internal function.
4165 * LOCKING: Acquires the loader lock.
4167 * Returns: a transient MonoMethodHeader allocated from the heap.
4170 mono_metadata_parse_mh_full (MonoImage
*m
, MonoGenericContainer
*container
, const char *ptr
, MonoError
*error
)
4172 MonoMethodHeader
*mh
= NULL
;
4173 unsigned char flags
= *(const unsigned char *) ptr
;
4174 unsigned char format
= flags
& METHOD_HEADER_FORMAT_MASK
;
4176 guint32 local_var_sig_tok
, max_stack
, code_size
, init_locals
;
4177 const unsigned char *code
;
4178 MonoExceptionClause
* clauses
= NULL
;
4179 int num_clauses
= 0;
4180 MonoTableInfo
*t
= &m
->tables
[MONO_TABLE_STANDALONESIG
];
4181 guint32 cols
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
4186 mono_error_set_bad_image (error
, m
, "Method header with null pointer");
4191 case METHOD_HEADER_TINY_FORMAT
:
4192 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
);
4195 mh
->is_transient
= TRUE
;
4196 local_var_sig_tok
= 0;
4197 mh
->code_size
= flags
>> 2;
4198 mh
->code
= (unsigned char*)ptr
;
4200 case METHOD_HEADER_FAT_FORMAT
:
4201 fat_flags
= read16 (ptr
);
4203 max_stack
= read16 (ptr
);
4205 code_size
= read32 (ptr
);
4207 local_var_sig_tok
= read32 (ptr
);
4210 if (fat_flags
& METHOD_HEADER_INIT_LOCALS
)
4215 code
= (unsigned char*)ptr
;
4217 if (!(fat_flags
& METHOD_HEADER_MORE_SECTS
))
4221 * There are more sections
4223 ptr
= (char*)code
+ code_size
;
4226 mono_error_set_bad_image (error
, m
, "Invalid method header format %d", format
);
4230 if (local_var_sig_tok
) {
4231 int idx
= (local_var_sig_tok
& 0xffffff)-1;
4232 if (idx
>= t
->rows
|| idx
< 0) {
4233 mono_error_set_bad_image (error
, m
, "Invalid method header local vars signature token 0x%8x", idx
);
4236 mono_metadata_decode_row (t
, idx
, cols
, 1);
4238 if (!mono_verifier_verify_standalone_signature (m
, cols
[MONO_STAND_ALONE_SIGNATURE
], error
))
4241 if (fat_flags
& METHOD_HEADER_MORE_SECTS
) {
4242 clauses
= parse_section_data (m
, &num_clauses
, (const unsigned char*)ptr
, error
);
4243 goto_if_nok (error
, fail
);
4245 if (local_var_sig_tok
) {
4246 const char *locals_ptr
;
4249 locals_ptr
= mono_metadata_blob_heap (m
, cols
[MONO_STAND_ALONE_SIGNATURE
]);
4250 mono_metadata_decode_blob_size (locals_ptr
, &locals_ptr
);
4251 if (*locals_ptr
!= 0x07)
4252 g_warning ("wrong signature for locals blob");
4254 len
= mono_metadata_decode_value (locals_ptr
, &locals_ptr
);
4255 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ len
* sizeof (MonoType
*) + num_clauses
* sizeof (MonoExceptionClause
));
4256 mh
->num_locals
= len
;
4257 for (i
= 0; i
< len
; ++i
) {
4258 mh
->locals
[i
] = mono_metadata_parse_type_internal (m
, container
, 0, TRUE
, locals_ptr
, &locals_ptr
, error
);
4259 goto_if_nok (error
, fail
);
4262 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ num_clauses
* sizeof (MonoExceptionClause
));
4265 mh
->code_size
= code_size
;
4266 mh
->max_stack
= max_stack
;
4267 mh
->is_transient
= TRUE
;
4268 mh
->init_locals
= init_locals
;
4270 MonoExceptionClause
* clausesp
= (MonoExceptionClause
*)&mh
->locals
[mh
->num_locals
];
4271 memcpy (clausesp
, clauses
, num_clauses
* sizeof (MonoExceptionClause
));
4273 mh
->clauses
= clausesp
;
4274 mh
->num_clauses
= num_clauses
;
4285 * mono_metadata_parse_mh:
4286 * \param generic_context generics context
4287 * \param ptr pointer to the method header.
4289 * Decode the method header at \p ptr, including pointer to the IL code,
4290 * info about local variables and optional exception tables.
4292 * \returns a transient \c MonoMethodHeader allocated from the heap.
4295 mono_metadata_parse_mh (MonoImage
*m
, const char *ptr
)
4298 MonoMethodHeader
*header
= mono_metadata_parse_mh_full (m
, NULL
, ptr
, error
);
4299 mono_error_cleanup (error
);
4304 * mono_metadata_free_mh:
4305 * \param mh a method header
4307 * Free the memory allocated for the method header.
4310 mono_metadata_free_mh (MonoMethodHeader
*mh
)
4314 /* If it is not transient it means it's part of a wrapper method,
4315 * or a SRE-generated method, so the lifetime in that case is
4316 * dictated by the method's own lifetime
4318 if (mh
&& mh
->is_transient
) {
4319 for (i
= 0; i
< mh
->num_locals
; ++i
)
4320 mono_metadata_free_type (mh
->locals
[i
]);
4326 * mono_method_header_get_code:
4327 * \param header a \c MonoMethodHeader pointer
4328 * \param code_size memory location for returning the code size
4329 * \param max_stack memory location for returning the max stack
4331 * Method header accessor to retreive info about the IL code properties:
4332 * a pointer to the IL code itself, the size of the code and the max number
4333 * of stack slots used by the code.
4335 * \returns pointer to the IL code represented by the method header.
4337 const unsigned char*
4338 mono_method_header_get_code (MonoMethodHeader
*header
, guint32
* code_size
, guint32
* max_stack
)
4341 *code_size
= header
->code_size
;
4343 *max_stack
= header
->max_stack
;
4344 return header
->code
;
4348 * mono_method_header_get_locals:
4349 * \param header a \c MonoMethodHeader pointer
4350 * \param num_locals memory location for returning the number of local variables
4351 * \param init_locals memory location for returning the init_locals flag
4353 * Method header accessor to retreive info about the local variables:
4354 * an array of local types, the number of locals and whether the locals
4355 * are supposed to be initialized to 0 on method entry
4357 * \returns pointer to an array of types of the local variables
4360 mono_method_header_get_locals (MonoMethodHeader
*header
, guint32
* num_locals
, gboolean
*init_locals
)
4363 *num_locals
= header
->num_locals
;
4365 *init_locals
= header
->init_locals
;
4366 return header
->locals
;
4370 * mono_method_header_get_num_clauses:
4371 * @header: a MonoMethodHeader pointer
4373 * Method header accessor to retreive the number of exception clauses.
4375 * Returns: the number of exception clauses present
4378 mono_method_header_get_num_clauses (MonoMethodHeader
*header
)
4380 return header
->num_clauses
;
4384 * mono_method_header_get_clauses:
4385 * \param header a \c MonoMethodHeader pointer
4386 * \param method \c MonoMethod the header belongs to
4387 * \param iter pointer to a iterator
4388 * \param clause pointer to a \c MonoExceptionClause structure which will be filled with the info
4390 * Get the info about the exception clauses in the method. Set \c *iter to NULL to
4391 * initiate the iteration, then call the method repeatedly until it returns FALSE.
4392 * At each iteration, the structure pointed to by clause if filled with the
4393 * exception clause information.
4395 * \returns TRUE if clause was filled with info, FALSE if there are no more exception
4399 mono_method_header_get_clauses (MonoMethodHeader
*header
, MonoMethod
*method
, gpointer
*iter
, MonoExceptionClause
*clause
)
4401 MonoExceptionClause
*sc
;
4402 /* later we'll be able to use this interface to parse the clause info on demand,
4403 * without allocating anything.
4405 if (!iter
|| !header
->num_clauses
)
4408 *iter
= sc
= header
->clauses
;
4412 sc
= (MonoExceptionClause
*)*iter
;
4414 if (sc
< header
->clauses
+ header
->num_clauses
) {
4423 * mono_metadata_parse_field_type:
4424 * \param m metadata context to extract information from
4425 * \param ptr pointer to the field signature
4426 * \param rptr pointer updated to match the end of the decoded stream
4428 * Parses the field signature, and returns the type information for it.
4430 * \returns The \c MonoType that was extracted from \p ptr .
4433 mono_metadata_parse_field_type (MonoImage
*m
, short field_flags
, const char *ptr
, const char **rptr
)
4436 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, field_flags
, FALSE
, ptr
, rptr
, error
);
4437 mono_error_cleanup (error
);
4442 * mono_metadata_parse_param:
4443 * \param m metadata context to extract information from
4444 * \param ptr pointer to the param signature
4445 * \param rptr pointer updated to match the end of the decoded stream
4447 * Parses the param signature, and returns the type information for it.
4449 * \returns The \c MonoType that was extracted from \p ptr .
4452 mono_metadata_parse_param (MonoImage
*m
, const char *ptr
, const char **rptr
)
4455 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, 0, FALSE
, ptr
, rptr
, error
);
4456 mono_error_cleanup (error
);
4461 * mono_metadata_token_from_dor:
4462 * \param dor_token A \c TypeDefOrRef coded index
4464 * \p dor_token is a \c TypeDefOrRef coded index: it contains either
4465 * a \c TypeDef, \c TypeRef or \c TypeSpec in the lower bits, and the upper
4466 * bits contain an index into the table.
4468 * \returns an expanded token
4471 mono_metadata_token_from_dor (guint32 dor_index
)
4475 table
= dor_index
& 0x03;
4476 idx
= dor_index
>> 2;
4479 case 0: /* TypeDef */
4480 return MONO_TOKEN_TYPE_DEF
| idx
;
4481 case 1: /* TypeRef */
4482 return MONO_TOKEN_TYPE_REF
| idx
;
4483 case 2: /* TypeSpec */
4484 return MONO_TOKEN_TYPE_SPEC
| idx
;
4486 g_assert_not_reached ();
4493 * We use this to pass context information to the row locator
4496 int idx
; /* The index that we are trying to locate */
4497 int col_idx
; /* The index in the row where idx may be stored */
4498 MonoTableInfo
*t
; /* pointer to the table */
4503 * How the row locator works.
4508 * ___|___------> _______
4511 * A column in the rows of table A references an index in table B.
4512 * For example A may be the TYPEDEF table and B the METHODDEF table.
4514 * Given an index in table B we want to get the row in table A
4515 * where the column n references our index in B.
4517 * In the locator_t structure:
4519 * col_idx is the column number
4520 * index is the index in table B
4521 * result will be the index in table A
4524 * Table A Table B column (in table A)
4525 * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
4526 * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
4527 * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
4528 * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
4529 * METHODSEM PROPERTY ASSOCIATION (encoded index)
4531 * Note that we still don't support encoded indexes.
4535 typedef_locator (const void *a
, const void *b
)
4537 locator_t
*loc
= (locator_t
*) a
;
4538 const char *bb
= (const char *) b
;
4539 int typedef_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4540 guint32 col
, col_next
;
4542 col
= mono_metadata_decode_row_col (loc
->t
, typedef_index
, loc
->col_idx
);
4548 * Need to check that the next row is valid.
4550 if (typedef_index
+ 1 < loc
->t
->rows
) {
4551 col_next
= mono_metadata_decode_row_col (loc
->t
, typedef_index
+ 1, loc
->col_idx
);
4552 if (loc
->idx
>= col_next
)
4555 if (col
== col_next
)
4559 loc
->result
= typedef_index
;
4565 table_locator (const void *a
, const void *b
)
4567 locator_t
*loc
= (locator_t
*) a
;
4568 const char *bb
= (const char *) b
;
4569 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4572 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
4574 if (loc
->idx
== col
) {
4575 loc
->result
= table_index
;
4585 declsec_locator (const void *a
, const void *b
)
4587 locator_t
*loc
= (locator_t
*) a
;
4588 const char *bb
= (const char *) b
;
4589 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4592 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
4594 if (loc
->idx
== col
) {
4595 loc
->result
= table_index
;
4607 * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
4608 * which contains IDX.
4611 search_ptr_table (MonoImage
*image
, int table
, int idx
)
4613 MonoTableInfo
*ptrdef
= &image
->tables
[table
];
4616 /* Use a linear search to find our index in the table */
4617 for (i
= 0; i
< ptrdef
->rows
; i
++)
4618 /* All the Ptr tables have the same structure */
4619 if (mono_metadata_decode_row_col (ptrdef
, i
, 0) == idx
)
4622 if (i
< ptrdef
->rows
)
4629 * mono_metadata_typedef_from_field:
4630 * \param meta metadata context
4631 * \param index FieldDef token
4633 * \returns the 1-based index into the \c TypeDef table of the type that
4634 * declared the field described by \p index, or 0 if not found.
4637 mono_metadata_typedef_from_field (MonoImage
*meta
, guint32 index
)
4639 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
4645 loc
.idx
= mono_metadata_token_index (index
);
4646 loc
.col_idx
= MONO_TYPEDEF_FIELD_LIST
;
4649 if (meta
->uncompressed_metadata
)
4650 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
4652 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
4655 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4656 return loc
.result
+ 1;
4660 * mono_metadata_typedef_from_method:
4661 * \param meta metadata context
4662 * \param index \c MethodDef token
4663 * \returns the 1-based index into the \c TypeDef table of the type that
4664 * declared the method described by \p index. 0 if not found.
4667 mono_metadata_typedef_from_method (MonoImage
*meta
, guint32 index
)
4669 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
4675 loc
.idx
= mono_metadata_token_index (index
);
4676 loc
.col_idx
= MONO_TYPEDEF_METHOD_LIST
;
4679 if (meta
->uncompressed_metadata
)
4680 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_METHOD_POINTER
, loc
.idx
);
4682 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
4685 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4686 return loc
.result
+ 1;
4690 * mono_metadata_interfaces_from_typedef_full:
4691 * \param meta metadata context
4692 * \param index typedef token
4693 * \param interfaces Out parameter used to store the interface array
4694 * \param count Out parameter used to store the number of interfaces
4695 * \param heap_alloc_result if TRUE the result array will be \c g_malloc'd
4696 * \param context The generic context
4697 * \param error set on error
4699 * The array of interfaces that the \p index typedef token implements is returned in
4700 * \p interfaces. The number of elements in the array is returned in \p count.
4702 * \returns \c TRUE on success, \c FALSE on failure and sets \p error.
4705 mono_metadata_interfaces_from_typedef_full (MonoImage
*meta
, guint32 index
, MonoClass
***interfaces
, guint
*count
, gboolean heap_alloc_result
, MonoGenericContext
*context
, MonoError
*error
)
4707 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_INTERFACEIMPL
];
4710 guint32 cols
[MONO_INTERFACEIMPL_SIZE
];
4721 loc
.idx
= mono_metadata_token_index (index
);
4722 loc
.col_idx
= MONO_INTERFACEIMPL_CLASS
;
4725 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4730 * We may end up in the middle of the rows...
4733 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_INTERFACEIMPL_CLASS
))
4739 while (pos
< tdef
->rows
) {
4740 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
4741 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
4746 if (heap_alloc_result
)
4747 result
= g_new0 (MonoClass
*, pos
- start
);
4749 result
= (MonoClass
**)mono_image_alloc0 (meta
, sizeof (MonoClass
*) * (pos
- start
));
4752 while (pos
< tdef
->rows
) {
4755 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
4756 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
4758 iface
= mono_class_get_and_inflate_typespec_checked (
4759 meta
, mono_metadata_token_from_dor (cols
[MONO_INTERFACEIMPL_INTERFACE
]), context
, error
);
4762 result
[pos
- start
] = iface
;
4765 *count
= pos
- start
;
4766 *interfaces
= result
;
4771 * mono_metadata_interfaces_from_typedef:
4772 * \param meta metadata context
4773 * \param index typedef token
4774 * \param count Out parameter used to store the number of interfaces
4776 * The array of interfaces that the \p index typedef token implements is returned in
4777 * \p interfaces. The number of elements in the array is returned in \p count. The returned
4778 * array is allocated with \c g_malloc and the caller must free it.
4780 * LOCKING: Acquires the loader lock .
4782 * \returns the interface array on success, NULL on failure.
4785 mono_metadata_interfaces_from_typedef (MonoImage
*meta
, guint32 index
, guint
*count
)
4788 MonoClass
**interfaces
= NULL
;
4791 rv
= mono_metadata_interfaces_from_typedef_full (meta
, index
, &interfaces
, count
, TRUE
, NULL
, error
);
4792 mono_error_assert_ok (error
);
4800 * mono_metadata_nested_in_typedef:
4801 * \param meta metadata context
4802 * \param index typedef token
4803 * \returns the 1-based index into the TypeDef table of the type
4804 * where the type described by \p index is nested.
4805 * Returns 0 if \p index describes a non-nested type.
4808 mono_metadata_nested_in_typedef (MonoImage
*meta
, guint32 index
)
4810 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4816 loc
.idx
= mono_metadata_token_index (index
);
4817 loc
.col_idx
= MONO_NESTED_CLASS_NESTED
;
4820 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4823 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4824 return mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_NESTED_CLASS_ENCLOSING
) | MONO_TOKEN_TYPE_DEF
;
4828 * mono_metadata_nesting_typedef:
4829 * \param meta metadata context
4830 * \param index typedef token
4831 * \returns the 1-based index into the \c TypeDef table of the first type
4832 * that is nested inside the type described by \p index. The search starts at
4833 * \p start_index. Returns 0 if no such type is found.
4836 mono_metadata_nesting_typedef (MonoImage
*meta
, guint32 index
, guint32 start_index
)
4838 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4840 guint32 class_index
= mono_metadata_token_index (index
);
4845 start
= start_index
;
4847 while (start
<= tdef
->rows
) {
4848 if (class_index
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_NESTED_CLASS_ENCLOSING
))
4854 if (start
> tdef
->rows
)
4861 * mono_metadata_packing_from_typedef:
4862 * \param meta metadata context
4863 * \param index token representing a type
4864 * \returns the info stored in the \c ClassLayout table for the given typedef token
4865 * into the \p packing and \p size pointers.
4866 * Returns 0 if the info is not found.
4869 mono_metadata_packing_from_typedef (MonoImage
*meta
, guint32 index
, guint32
*packing
, guint32
*size
)
4871 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CLASSLAYOUT
];
4873 guint32 cols
[MONO_CLASS_LAYOUT_SIZE
];
4878 loc
.idx
= mono_metadata_token_index (index
);
4879 loc
.col_idx
= MONO_CLASS_LAYOUT_PARENT
;
4882 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4885 mono_metadata_decode_row (tdef
, loc
.result
, cols
, MONO_CLASS_LAYOUT_SIZE
);
4887 *packing
= cols
[MONO_CLASS_LAYOUT_PACKING_SIZE
];
4889 *size
= cols
[MONO_CLASS_LAYOUT_CLASS_SIZE
];
4891 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4892 return loc
.result
+ 1;
4896 * mono_metadata_custom_attrs_from_index:
4897 * \param meta metadata context
4898 * \param index token representing the parent
4899 * \returns: the 1-based index into the \c CustomAttribute table of the first
4900 * attribute which belongs to the metadata object described by \p index.
4901 * Returns 0 if no such attribute is found.
4904 mono_metadata_custom_attrs_from_index (MonoImage
*meta
, guint32 index
)
4906 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4913 loc
.col_idx
= MONO_CUSTOM_ATTR_PARENT
;
4916 /* FIXME: Index translation */
4918 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4921 /* Find the first entry by searching backwards */
4922 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_CUSTOM_ATTR_PARENT
) == index
))
4925 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4926 return loc
.result
+ 1;
4930 * mono_metadata_declsec_from_index:
4931 * \param meta metadata context
4932 * \param index token representing the parent
4933 * \returns the 0-based index into the \c DeclarativeSecurity table of the first
4934 * attribute which belongs to the metadata object described by \p index.
4935 * Returns \c -1 if no such attribute is found.
4938 mono_metadata_declsec_from_index (MonoImage
*meta
, guint32 index
)
4940 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_DECLSECURITY
];
4947 loc
.col_idx
= MONO_DECL_SECURITY_PARENT
;
4950 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, declsec_locator
))
4953 /* Find the first entry by searching backwards */
4954 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_DECL_SECURITY_PARENT
) == index
))
4961 * mono_metadata_localscope_from_methoddef:
4962 * @meta: metadata context
4963 * @index: methoddef index
4965 * Returns: the 1-based index into the LocalScope table of the first
4966 * scope which belongs to the method described by @index.
4967 * Returns 0 if no such row is found.
4970 mono_metadata_localscope_from_methoddef (MonoImage
*meta
, guint32 index
)
4972 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_LOCALSCOPE
];
4979 loc
.col_idx
= MONO_LOCALSCOPE_METHOD
;
4982 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4985 /* Find the first entry by searching backwards */
4986 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_LOCALSCOPE_METHOD
) == index
))
4989 return loc
.result
+ 1;
4994 mono_backtrace (int limit
)
4999 backtrace (array
, limit
);
5000 names
= backtrace_symbols (array
, limit
);
5001 for (i
=0; i
< limit
; ++i
) {
5002 g_print ("\t%s\n", names
[i
]);
5008 static int i8_align
;
5011 * mono_type_set_alignment:
5013 * Set the alignment used by runtime to layout fields etc. of type TYPE to ALIGN.
5014 * This should only be used in AOT mode since the resulting layout will not match the
5018 mono_type_set_alignment (MonoTypeEnum type
, int align
)
5020 /* Support only a few types whose alignment is abi dependent */
5026 g_assert_not_reached ();
5033 * \param t the type to return the size of
5034 * \returns The number of bytes required to hold an instance of this
5038 mono_type_size (MonoType
*t
, int *align
)
5040 MonoTypeEnum simple_type
;
5047 *align
= MONO_ABI_ALIGNOF (gpointer
);
5048 return MONO_ABI_SIZEOF (gpointer
);
5051 simple_type
= t
->type
;
5053 switch (simple_type
) {
5054 case MONO_TYPE_VOID
:
5057 case MONO_TYPE_BOOLEAN
:
5058 *align
= MONO_ABI_ALIGNOF (gint8
);
5062 *align
= MONO_ABI_ALIGNOF (gint8
);
5064 case MONO_TYPE_CHAR
:
5067 *align
= MONO_ABI_ALIGNOF (gint16
);
5071 *align
= MONO_ABI_ALIGNOF (gint32
);
5074 *align
= MONO_ABI_ALIGNOF (float);
5078 *align
= MONO_ABI_ALIGNOF (gint64
);
5081 *align
= MONO_ABI_ALIGNOF (double);
5085 *align
= MONO_ABI_ALIGNOF (gpointer
);
5086 return MONO_ABI_SIZEOF (gpointer
);
5087 case MONO_TYPE_VALUETYPE
: {
5088 if (m_class_is_enumtype (t
->data
.klass
))
5089 return mono_type_size (mono_class_enum_basetype_internal (t
->data
.klass
), align
);
5091 return mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
5093 case MONO_TYPE_STRING
:
5094 case MONO_TYPE_OBJECT
:
5095 case MONO_TYPE_CLASS
:
5096 case MONO_TYPE_SZARRAY
:
5098 case MONO_TYPE_FNPTR
:
5099 case MONO_TYPE_ARRAY
:
5100 *align
= MONO_ABI_ALIGNOF (gpointer
);
5101 return MONO_ABI_SIZEOF (gpointer
);
5102 case MONO_TYPE_TYPEDBYREF
:
5103 return mono_class_value_size (mono_defaults
.typed_reference_class
, (guint32
*)align
);
5104 case MONO_TYPE_GENERICINST
: {
5105 MonoGenericClass
*gclass
= t
->data
.generic_class
;
5106 MonoClass
*container_class
= gclass
->container_class
;
5108 // g_assert (!gclass->inst->is_open);
5110 if (m_class_is_valuetype (container_class
)) {
5111 if (m_class_is_enumtype (container_class
))
5112 return mono_type_size (mono_class_enum_basetype_internal (container_class
), align
);
5114 return mono_class_value_size (mono_class_from_mono_type_internal (t
), (guint32
*)align
);
5116 *align
= MONO_ABI_ALIGNOF (gpointer
);
5117 return MONO_ABI_SIZEOF (gpointer
);
5121 case MONO_TYPE_MVAR
:
5122 if (!t
->data
.generic_param
->gshared_constraint
|| t
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_VALUETYPE
) {
5123 *align
= MONO_ABI_ALIGNOF (gpointer
);
5124 return MONO_ABI_SIZEOF (gpointer
);
5126 /* The gparam can only match types given by gshared_constraint */
5127 return mono_type_size (t
->data
.generic_param
->gshared_constraint
, align
);
5131 g_error ("mono_type_size: type 0x%02x unknown", t
->type
);
5137 * mono_type_stack_size:
5138 * \param t the type to return the size it uses on the stack
5139 * \returns The number of bytes required to hold an instance of this
5140 * type on the runtime stack
5143 mono_type_stack_size (MonoType
*t
, int *align
)
5145 return mono_type_stack_size_internal (t
, align
, FALSE
);
5149 mono_type_stack_size_internal (MonoType
*t
, int *align
, gboolean allow_open
)
5152 MonoTypeEnum simple_type
;
5153 int stack_slot_size
= TARGET_SIZEOF_VOID_P
;
5154 int stack_slot_align
= TARGET_SIZEOF_VOID_P
;
5156 g_assert (t
!= NULL
);
5162 *align
= stack_slot_align
;
5163 return stack_slot_size
;
5166 simple_type
= t
->type
;
5167 switch (simple_type
) {
5168 case MONO_TYPE_BOOLEAN
:
5169 case MONO_TYPE_CHAR
:
5178 case MONO_TYPE_STRING
:
5179 case MONO_TYPE_OBJECT
:
5180 case MONO_TYPE_CLASS
:
5181 case MONO_TYPE_SZARRAY
:
5183 case MONO_TYPE_FNPTR
:
5184 case MONO_TYPE_ARRAY
:
5185 *align
= stack_slot_align
;
5186 return stack_slot_size
;
5188 case MONO_TYPE_MVAR
:
5189 g_assert (allow_open
);
5190 if (!t
->data
.generic_param
->gshared_constraint
|| t
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_VALUETYPE
) {
5191 *align
= stack_slot_align
;
5192 return stack_slot_size
;
5194 /* The gparam can only match types given by gshared_constraint */
5195 return mono_type_stack_size_internal (t
->data
.generic_param
->gshared_constraint
, align
, allow_open
);
5197 case MONO_TYPE_TYPEDBYREF
:
5198 *align
= stack_slot_align
;
5199 return stack_slot_size
* 3;
5201 *align
= MONO_ABI_ALIGNOF (float);
5202 return sizeof (float);
5205 *align
= MONO_ABI_ALIGNOF (gint64
);
5206 return sizeof (gint64
);
5208 *align
= MONO_ABI_ALIGNOF (double);
5209 return sizeof (double);
5210 case MONO_TYPE_VALUETYPE
: {
5213 if (m_class_is_enumtype (t
->data
.klass
))
5214 return mono_type_stack_size_internal (mono_class_enum_basetype_internal (t
->data
.klass
), align
, allow_open
);
5216 size
= mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
5218 *align
= *align
+ stack_slot_align
- 1;
5219 *align
&= ~(stack_slot_align
- 1);
5221 size
+= stack_slot_size
- 1;
5222 size
&= ~(stack_slot_size
- 1);
5227 case MONO_TYPE_GENERICINST
: {
5228 MonoGenericClass
*gclass
= t
->data
.generic_class
;
5229 MonoClass
*container_class
= gclass
->container_class
;
5232 g_assert (!gclass
->context
.class_inst
->is_open
);
5234 if (m_class_is_valuetype (container_class
)) {
5235 if (m_class_is_enumtype (container_class
))
5236 return mono_type_stack_size_internal (mono_class_enum_basetype_internal (container_class
), align
, allow_open
);
5238 guint32 size
= mono_class_value_size (mono_class_from_mono_type_internal (t
), (guint32
*)align
);
5240 *align
= *align
+ stack_slot_align
- 1;
5241 *align
&= ~(stack_slot_align
- 1);
5243 size
+= stack_slot_size
- 1;
5244 size
&= ~(stack_slot_size
- 1);
5249 *align
= stack_slot_align
;
5250 return stack_slot_size
;
5254 g_error ("type 0x%02x unknown", t
->type
);
5260 mono_type_generic_inst_is_valuetype (MonoType
*type
)
5262 g_assert (type
->type
== MONO_TYPE_GENERICINST
);
5263 return m_class_is_valuetype (type
->data
.generic_class
->container_class
);
5267 * mono_metadata_generic_class_is_valuetype:
5270 mono_metadata_generic_class_is_valuetype (MonoGenericClass
*gclass
)
5272 return m_class_is_valuetype (gclass
->container_class
);
5276 _mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
, gboolean signature_only
)
5278 MonoGenericInst
*i1
= g1
->context
.class_inst
;
5279 MonoGenericInst
*i2
= g2
->context
.class_inst
;
5281 if (g1
->is_dynamic
!= g2
->is_dynamic
)
5283 if (!mono_metadata_class_equal (g1
->container_class
, g2
->container_class
, signature_only
))
5285 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
5287 return g1
->is_tb_open
== g2
->is_tb_open
;
5291 _mono_metadata_generic_class_container_equal (const MonoGenericClass
*g1
, MonoClass
*c2
, gboolean signature_only
)
5293 MonoGenericInst
*i1
= g1
->context
.class_inst
;
5294 MonoGenericInst
*i2
= mono_class_get_generic_container (c2
)->context
.class_inst
;
5296 if (!mono_metadata_class_equal (g1
->container_class
, c2
, signature_only
))
5298 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
5300 return !g1
->is_tb_open
;
5304 mono_metadata_generic_context_hash (const MonoGenericContext
*context
)
5306 /* FIXME: check if this seed is good enough */
5307 guint hash
= 0xc01dfee7;
5308 if (context
->class_inst
)
5309 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->class_inst
);
5310 if (context
->method_inst
)
5311 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->method_inst
);
5316 mono_metadata_generic_context_equal (const MonoGenericContext
*g1
, const MonoGenericContext
*g2
)
5318 return g1
->class_inst
== g2
->class_inst
&& g1
->method_inst
== g2
->method_inst
;
5322 * mono_metadata_str_hash:
5324 * This should be used instead of g_str_hash for computing hash codes visible
5325 * outside this module, since g_str_hash () is not guaranteed to be stable
5326 * (its not the same in eglib for example).
5329 mono_metadata_str_hash (gconstpointer v1
)
5331 /* Same as g_str_hash () in glib */
5332 char *p
= (char *) v1
;
5337 hash
= (hash
<< 5) - hash
+ *p
;
5344 * mono_metadata_type_hash:
5346 * Computes a hash value for \p t1 to be used in \c GHashTable.
5347 * The returned hash is guaranteed to be the same across executions.
5350 mono_metadata_type_hash (MonoType
*t1
)
5352 guint hash
= t1
->type
;
5354 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
5356 case MONO_TYPE_VALUETYPE
:
5357 case MONO_TYPE_CLASS
:
5358 case MONO_TYPE_SZARRAY
: {
5359 MonoClass
*klass
= t1
->data
.klass
;
5361 * Dynamic classes must not be hashed on their type since it can change
5362 * during runtime. For example, if we hash a reference type that is
5363 * later made into a valuetype.
5365 * This is specially problematic with generic instances since they are
5366 * inserted in a bunch of hash tables before been finished.
5368 if (image_is_dynamic (m_class_get_image (klass
)))
5369 return (t1
->byref
<< 6) | mono_metadata_str_hash (m_class_get_name (klass
));
5370 return ((hash
<< 5) - hash
) ^ mono_metadata_str_hash (m_class_get_name (klass
));
5373 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (t1
->data
.type
);
5374 case MONO_TYPE_ARRAY
:
5375 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (m_class_get_byval_arg (t1
->data
.array
->eklass
));
5376 case MONO_TYPE_GENERICINST
:
5377 return ((hash
<< 5) - hash
) ^ mono_generic_class_hash (t1
->data
.generic_class
);
5379 case MONO_TYPE_MVAR
:
5380 return ((hash
<< 5) - hash
) ^ mono_metadata_generic_param_hash (t1
->data
.generic_param
);
5387 mono_metadata_generic_param_hash (MonoGenericParam
*p
)
5390 MonoGenericParamInfo
*info
;
5392 hash
= (mono_generic_param_num (p
) << 2);
5393 if (p
->gshared_constraint
)
5394 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (p
->gshared_constraint
);
5395 info
= mono_generic_param_info (p
);
5396 /* Can't hash on the owner klass/method, since those might not be set when this is called */
5397 if (!p
->owner
->is_anonymous
)
5398 hash
= ((hash
<< 5) - hash
) ^ info
->token
;
5403 mono_metadata_generic_param_equal_internal (MonoGenericParam
*p1
, MonoGenericParam
*p2
, gboolean signature_only
)
5407 if (mono_generic_param_num (p1
) != mono_generic_param_num (p2
))
5409 if (p1
->gshared_constraint
&& p2
->gshared_constraint
) {
5410 if (!mono_metadata_type_equal (p1
->gshared_constraint
, p2
->gshared_constraint
))
5413 if (p1
->gshared_constraint
!= p2
->gshared_constraint
)
5418 * We have to compare the image as well because if we didn't,
5419 * the generic_inst_cache lookup wouldn't care about the image
5420 * of generic params, so what could happen is that a generic
5421 * inst with params from image A is put into the cache, then
5422 * image B gets that generic inst from the cache, image A is
5423 * unloaded, so the inst is deleted, but image B still retains
5426 if (mono_generic_param_owner (p1
) == mono_generic_param_owner (p2
))
5430 * If `signature_only' is true, we're comparing two (method) signatures.
5431 * In this case, the owner of two type parameters doesn't need to match.
5434 return signature_only
;
5438 mono_metadata_generic_param_equal (MonoGenericParam
*p1
, MonoGenericParam
*p2
)
5440 return mono_metadata_generic_param_equal_internal (p1
, p2
, TRUE
);
5444 mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
)
5448 if (mono_class_is_ginst (c1
) && mono_class_is_ginst (c2
))
5449 return _mono_metadata_generic_class_equal (mono_class_get_generic_class (c1
), mono_class_get_generic_class (c2
), signature_only
);
5450 if (mono_class_is_ginst (c1
) && mono_class_is_gtd (c2
))
5451 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c1
), c2
, signature_only
);
5452 if (mono_class_is_gtd (c1
) && mono_class_is_ginst (c2
))
5453 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c2
), c1
, signature_only
);
5454 MonoType
*c1_type
= m_class_get_byval_arg (c1
);
5455 MonoType
*c2_type
= m_class_get_byval_arg (c2
);
5456 if ((c1_type
->type
== MONO_TYPE_VAR
) && (c2_type
->type
== MONO_TYPE_VAR
))
5457 return mono_metadata_generic_param_equal_internal (
5458 c1_type
->data
.generic_param
, c2_type
->data
.generic_param
, signature_only
);
5459 if ((c1_type
->type
== MONO_TYPE_MVAR
) && (c2_type
->type
== MONO_TYPE_MVAR
))
5460 return mono_metadata_generic_param_equal_internal (
5461 c1_type
->data
.generic_param
, c2_type
->data
.generic_param
, signature_only
);
5462 if (signature_only
&&
5463 (c1_type
->type
== MONO_TYPE_SZARRAY
) && (c2_type
->type
== MONO_TYPE_SZARRAY
))
5464 return mono_metadata_class_equal (c1_type
->data
.klass
, c2_type
->data
.klass
, signature_only
);
5465 if (signature_only
&&
5466 (c1_type
->type
== MONO_TYPE_ARRAY
) && (c2_type
->type
== MONO_TYPE_ARRAY
))
5467 return do_mono_metadata_type_equal (c1_type
, c2_type
, signature_only
);
5472 mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
)
5474 gpointer iter1
= 0, iter2
= 0;
5478 if (s1
->call_convention
!= s2
->call_convention
)
5480 if (s1
->sentinelpos
!= s2
->sentinelpos
)
5482 if (s1
->hasthis
!= s2
->hasthis
)
5484 if (s1
->explicit_this
!= s2
->explicit_this
)
5486 if (! do_mono_metadata_type_equal (s1
->ret
, s2
->ret
, signature_only
))
5488 if (s1
->param_count
!= s2
->param_count
)
5492 MonoType
*t1
= mono_signature_get_params (s1
, &iter1
);
5493 MonoType
*t2
= mono_signature_get_params (s2
, &iter2
);
5495 if (t1
== NULL
|| t2
== NULL
)
5497 if (! do_mono_metadata_type_equal (t1
, t2
, signature_only
))
5503 * mono_metadata_type_equal:
5506 * @signature_only: If true, treat ginsts as equal which are instantiated separately but have equal positional value
5508 * Determine if @t1 and @t2 represent the same type.
5509 * Returns: #TRUE if @t1 and @t2 are equal.
5512 do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
5514 if (t1
->type
!= t2
->type
|| t1
->byref
!= t2
->byref
)
5517 gboolean cmod_reject
= FALSE
;
5519 gboolean is_pointer
= (t1
->type
== MONO_TYPE_PTR
);
5521 if (t1
->has_cmods
!= t2
->has_cmods
)
5523 else if (t1
->has_cmods
&& t2
->has_cmods
) {
5524 MonoCustomModContainer
*cm1
= mono_type_get_cmods (t1
);
5525 MonoCustomModContainer
*cm2
= mono_type_get_cmods (t2
);
5531 // The CLI itself shall treat required and optional modifiers in the same manner.
5532 // Two signatures that differ only by the addition of a custom modifier
5533 // (required or optional) shall not be considered to match.
5534 if (cm1
->count
!= cm2
->count
) {
5536 } else for (int i
=0; i
< cm1
->count
; i
++) {
5537 if (cm1
->modifiers
[i
].required
!= cm2
->modifiers
[i
].required
) {
5542 // FIXME: propagate error to caller
5544 MonoClass
*c1
= mono_class_get_checked (cm1
->image
, cm1
->modifiers
[i
].token
, error
);
5545 mono_error_assert_ok (error
);
5546 MonoClass
*c2
= mono_class_get_checked (cm2
->image
, cm2
->modifiers
[i
].token
, error
);
5547 mono_error_assert_ok (error
);
5556 gboolean result
= FALSE
;
5559 case MONO_TYPE_VOID
:
5560 case MONO_TYPE_BOOLEAN
:
5561 case MONO_TYPE_CHAR
:
5572 case MONO_TYPE_STRING
:
5575 case MONO_TYPE_OBJECT
:
5576 case MONO_TYPE_TYPEDBYREF
:
5579 case MONO_TYPE_VALUETYPE
:
5580 case MONO_TYPE_CLASS
:
5581 case MONO_TYPE_SZARRAY
:
5582 result
= mono_metadata_class_equal (t1
->data
.klass
, t2
->data
.klass
, signature_only
);
5585 result
= do_mono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
, signature_only
);
5587 case MONO_TYPE_ARRAY
:
5588 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
5591 result
= mono_metadata_class_equal (t1
->data
.array
->eklass
, t2
->data
.array
->eklass
, signature_only
);
5593 case MONO_TYPE_GENERICINST
:
5594 result
= _mono_metadata_generic_class_equal (
5595 t1
->data
.generic_class
, t2
->data
.generic_class
, signature_only
);
5598 result
= mono_metadata_generic_param_equal_internal (
5599 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
5601 case MONO_TYPE_MVAR
:
5602 result
= mono_metadata_generic_param_equal_internal (
5603 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
5605 case MONO_TYPE_FNPTR
:
5606 result
= mono_metadata_fnptr_equal (t1
->data
.method
, t2
->data
.method
, signature_only
);
5609 g_error ("implement type compare for %0x!", t1
->type
);
5613 if (cmod_reject
&& is_pointer
)
5620 * mono_metadata_type_equal:
5623 mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
5625 return do_mono_metadata_type_equal (t1
, t2
, FALSE
);
5629 * mono_metadata_type_equal_full:
5631 * \param t2 another type
5632 * \param signature_only if signature only comparison should be made
5634 * Determine if \p t1 and \p t2 are signature compatible if \p signature_only is TRUE, otherwise
5635 * behaves the same way as mono_metadata_type_equal.
5636 * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
5637 * \returns TRUE if \p t1 and \p t2 are equal taking \p signature_only into account.
5640 mono_metadata_type_equal_full (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
5642 return do_mono_metadata_type_equal (t1
, t2
, signature_only
);
5646 * mono_metadata_signature_equal:
5647 * \param sig1 a signature
5648 * \param sig2 another signature
5650 * Determine if \p sig1 and \p sig2 represent the same signature, with the
5651 * same number of arguments and the same types.
5652 * \returns TRUE if \p sig1 and \p sig2 are equal.
5655 mono_metadata_signature_equal (MonoMethodSignature
*sig1
, MonoMethodSignature
*sig2
)
5659 if (sig1
->hasthis
!= sig2
->hasthis
|| sig1
->param_count
!= sig2
->param_count
)
5662 if (sig1
->generic_param_count
!= sig2
->generic_param_count
)
5666 * We're just comparing the signatures of two methods here:
5668 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
5669 * U and V are equal here.
5671 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
5674 for (i
= 0; i
< sig1
->param_count
; i
++) {
5675 MonoType
*p1
= sig1
->params
[i
];
5676 MonoType
*p2
= sig2
->params
[i
];
5678 /* if (p1->attrs != p2->attrs)
5681 if (!do_mono_metadata_type_equal (p1
, p2
, TRUE
))
5685 if (!do_mono_metadata_type_equal (sig1
->ret
, sig2
->ret
, TRUE
))
5691 * mono_metadata_type_dup:
5692 * \param image image to alloc memory from
5693 * \param original type to duplicate
5694 * \returns copy of type allocated from the image's mempool (or from the heap, if \p image is null).
5697 mono_metadata_type_dup (MonoImage
*image
, const MonoType
*o
)
5699 return mono_metadata_type_dup_with_cmods (image
, o
, o
);
5703 * Works the same way as mono_metadata_type_dup but pick cmods from @cmods_source
5706 mono_metadata_type_dup_with_cmods (MonoImage
*image
, const MonoType
*o
, const MonoType
*cmods_source
)
5709 size_t sizeof_o
= mono_sizeof_type (cmods_source
);
5711 r
= image
? (MonoType
*)mono_image_alloc0 (image
, sizeof_o
) : (MonoType
*)g_malloc (sizeof_o
);
5713 if (cmods_source
->has_cmods
) {
5714 g_assert (!image
|| image
== mono_type_get_cmods (cmods_source
)->image
);
5715 memcpy (r
, cmods_source
, sizeof_o
);
5718 memcpy (r
, o
, sizeof (MonoType
));
5719 r
->has_cmods
= cmods_source
->has_cmods
;
5721 if (o
->type
== MONO_TYPE_PTR
) {
5722 r
->data
.type
= mono_metadata_type_dup (image
, o
->data
.type
);
5723 } else if (o
->type
== MONO_TYPE_ARRAY
) {
5724 r
->data
.array
= mono_dup_array_type (image
, o
->data
.array
);
5725 } else if (o
->type
== MONO_TYPE_FNPTR
) {
5726 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
5727 r
->data
.method
= mono_metadata_signature_deep_dup (image
, o
->data
.method
);
5733 * mono_signature_hash:
5736 mono_signature_hash (MonoMethodSignature
*sig
)
5738 guint i
, res
= sig
->ret
->type
;
5740 for (i
= 0; i
< sig
->param_count
; i
++)
5741 res
= (res
<< 5) - res
+ mono_type_hash (sig
->params
[i
]);
5747 * mono_metadata_encode_value:
5748 * @value: value to encode
5749 * @buf: buffer where to write the compressed representation
5750 * @endbuf: pointer updated to point at the end of the encoded output
5752 * Encodes the value @value in the compressed representation used
5753 * in metadata and stores the result in @buf. @buf needs to be big
5754 * enough to hold the data (4 bytes).
5757 mono_metadata_encode_value (guint32 value
, char *buf
, char **endbuf
)
5763 else if (value
< 0x4000) {
5764 p
[0] = 0x80 | (value
>> 8);
5765 p
[1] = value
& 0xff;
5768 p
[0] = (value
>> 24) | 0xc0;
5769 p
[1] = (value
>> 16) & 0xff;
5770 p
[2] = (value
>> 8) & 0xff;
5771 p
[3] = value
& 0xff;
5779 * mono_metadata_field_info:
5780 * \param meta the Image the field is defined in
5781 * \param index the index in the field table representing the field
5782 * \param offset a pointer to an integer where to store the offset that may have been specified for the field in a FieldLayout table
5783 * \param rva a pointer to the RVA of the field data in the image that may have been defined in a \c FieldRVA table
5784 * \param marshal_spec a pointer to the marshal spec that may have been defined for the field in a \c FieldMarshal table.
5786 * Gather info for field \p index that may have been defined in the \c FieldLayout,
5787 * \c FieldRVA and \c FieldMarshal tables.
5788 * Either of \p offset, \p rva and \p marshal_spec can be NULL if you're not interested
5792 mono_metadata_field_info (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5793 MonoMarshalSpec
**marshal_spec
)
5795 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, FALSE
);
5799 mono_metadata_field_info_with_mempool (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5800 MonoMarshalSpec
**marshal_spec
)
5802 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, TRUE
);
5806 mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5807 MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
)
5809 MonoTableInfo
*tdef
;
5812 loc
.idx
= index
+ 1;
5813 if (meta
->uncompressed_metadata
)
5814 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
5817 tdef
= &meta
->tables
[MONO_TABLE_FIELDLAYOUT
];
5819 loc
.col_idx
= MONO_FIELD_LAYOUT_FIELD
;
5822 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5823 *offset
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_LAYOUT_OFFSET
);
5825 *offset
= (guint32
)-1;
5829 tdef
= &meta
->tables
[MONO_TABLE_FIELDRVA
];
5831 loc
.col_idx
= MONO_FIELD_RVA_FIELD
;
5834 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5836 * LAMESPEC: There is no signature, no nothing, just the raw data.
5838 *rva
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_RVA_RVA
);
5846 if ((p
= mono_metadata_get_marshal_info (meta
, index
, TRUE
))) {
5847 *marshal_spec
= mono_metadata_parse_marshal_spec_full (alloc_from_image
? meta
: NULL
, meta
, p
);
5854 * mono_metadata_get_constant_index:
5855 * \param meta the Image the field is defined in
5856 * \param index the token that may have a row defined in the constants table
5857 * \param hint possible position for the row
5859 * \p token must be a \c FieldDef, \c ParamDef or \c PropertyDef token.
5861 * \returns the index into the \c Constants table or 0 if not found.
5864 mono_metadata_get_constant_index (MonoImage
*meta
, guint32 token
, guint32 hint
)
5866 MonoTableInfo
*tdef
;
5868 guint32 index
= mono_metadata_token_index (token
);
5870 tdef
= &meta
->tables
[MONO_TABLE_CONSTANT
];
5871 index
<<= MONO_HASCONSTANT_BITS
;
5872 switch (mono_metadata_token_table (token
)) {
5873 case MONO_TABLE_FIELD
:
5874 index
|= MONO_HASCONSTANT_FIEDDEF
;
5876 case MONO_TABLE_PARAM
:
5877 index
|= MONO_HASCONSTANT_PARAM
;
5879 case MONO_TABLE_PROPERTY
:
5880 index
|= MONO_HASCONSTANT_PROPERTY
;
5883 g_warning ("Not a valid token for the constant table: 0x%08x", token
);
5887 loc
.col_idx
= MONO_CONSTANT_PARENT
;
5890 /* FIXME: Index translation */
5892 if ((hint
> 0) && (hint
< tdef
->rows
) && (mono_metadata_decode_row_col (tdef
, hint
- 1, MONO_CONSTANT_PARENT
) == index
))
5895 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5896 return loc
.result
+ 1;
5902 * mono_metadata_events_from_typedef:
5903 * \param meta metadata context
5904 * \param index 0-based index (in the \c TypeDef table) describing a type
5905 * \returns the 0-based index in the \c Event table for the events in the
5906 * type. The last event that belongs to the type (plus 1) is stored
5907 * in the \p end_idx pointer.
5910 mono_metadata_events_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5914 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_EVENTMAP
];
5922 loc
.col_idx
= MONO_EVENT_MAP_PARENT
;
5923 loc
.idx
= index
+ 1;
5925 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5928 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_EVENT_MAP_EVENTLIST
);
5929 if (loc
.result
+ 1 < tdef
->rows
) {
5930 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_EVENT_MAP_EVENTLIST
) - 1;
5932 end
= meta
->tables
[MONO_TABLE_EVENT
].rows
;
5940 * mono_metadata_methods_from_event:
5941 * \param meta metadata context
5942 * \param index 0-based index (in the \c Event table) describing a event
5943 * \returns the 0-based index in the \c MethodDef table for the methods in the
5944 * event. The last method that belongs to the event (plus 1) is stored
5945 * in the \p end_idx pointer.
5948 mono_metadata_methods_from_event (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5952 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
5953 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
5959 if (meta
->uncompressed_metadata
)
5960 index
= search_ptr_table (meta
, MONO_TABLE_EVENT_POINTER
, index
+ 1) - 1;
5963 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
5964 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
; /* Method association coded index */
5966 if (!mono_binary_search (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
5971 * We may end up in the middle of the rows...
5974 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
5980 while (end
< msemt
->rows
) {
5981 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
5982 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
5991 * mono_metadata_properties_from_typedef:
5992 * \param meta metadata context
5993 * \param index 0-based index (in the \c TypeDef table) describing a type
5994 * \returns the 0-based index in the \c Property table for the properties in the
5995 * type. The last property that belongs to the type (plus 1) is stored
5996 * in the \p end_idx pointer.
5999 mono_metadata_properties_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
6003 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_PROPERTYMAP
];
6011 loc
.col_idx
= MONO_PROPERTY_MAP_PARENT
;
6012 loc
.idx
= index
+ 1;
6014 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6017 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_PROPERTY_MAP_PROPERTY_LIST
);
6018 if (loc
.result
+ 1 < tdef
->rows
) {
6019 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_PROPERTY_MAP_PROPERTY_LIST
) - 1;
6021 end
= meta
->tables
[MONO_TABLE_PROPERTY
].rows
;
6029 * mono_metadata_methods_from_property:
6030 * \param meta metadata context
6031 * \param index 0-based index (in the \c PropertyDef table) describing a property
6032 * \returns the 0-based index in the \c MethodDef table for the methods in the
6033 * property. The last method that belongs to the property (plus 1) is stored
6034 * in the \p end_idx pointer.
6037 mono_metadata_methods_from_property (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
6041 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
6042 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
6048 if (meta
->uncompressed_metadata
)
6049 index
= search_ptr_table (meta
, MONO_TABLE_PROPERTY_POINTER
, index
+ 1) - 1;
6052 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
6053 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
; /* Method association coded index */
6055 if (!mono_binary_search (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
6060 * We may end up in the middle of the rows...
6063 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
6069 while (end
< msemt
->rows
) {
6070 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
6071 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
6080 * mono_metadata_implmap_from_method:
6083 mono_metadata_implmap_from_method (MonoImage
*meta
, guint32 method_idx
)
6086 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_IMPLMAP
];
6091 /* No index translation seems to be needed */
6094 loc
.col_idx
= MONO_IMPLMAP_MEMBER
;
6095 loc
.idx
= ((method_idx
+ 1) << MONO_MEMBERFORWD_BITS
) | MONO_MEMBERFORWD_METHODDEF
;
6097 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6100 return loc
.result
+ 1;
6104 * mono_type_create_from_typespec:
6105 * \param image context where the image is created
6106 * \param type_spec typespec token
6107 * \deprecated use \c mono_type_create_from_typespec_checked that has proper error handling
6109 * Creates a \c MonoType representing the \c TypeSpec indexed by the \p type_spec
6113 mono_type_create_from_typespec (MonoImage
*image
, guint32 type_spec
)
6116 MonoType
*type
= mono_type_create_from_typespec_checked (image
, type_spec
, error
);
6118 g_error ("Could not create typespec %x due to %s", type_spec
, mono_error_get_message (error
));
6123 mono_type_create_from_typespec_checked (MonoImage
*image
, guint32 type_spec
, MonoError
*error
)
6126 guint32 idx
= mono_metadata_token_index (type_spec
);
6128 guint32 cols
[MONO_TYPESPEC_SIZE
];
6130 MonoType
*type
, *type2
;
6134 type
= (MonoType
*)mono_conc_hashtable_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
6138 t
= &image
->tables
[MONO_TABLE_TYPESPEC
];
6140 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPESPEC_SIZE
);
6141 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_TYPESPEC_SIGNATURE
]);
6143 if (!mono_verifier_verify_typespec_signature (image
, cols
[MONO_TYPESPEC_SIGNATURE
], type_spec
, error
))
6146 mono_metadata_decode_value (ptr
, &ptr
);
6148 type
= mono_metadata_parse_type_checked (image
, NULL
, 0, TRUE
, ptr
, &ptr
, error
);
6152 type2
= mono_metadata_type_dup (image
, type
);
6153 mono_metadata_free_type (type
);
6155 mono_image_lock (image
);
6157 /* We might leak some data in the image mempool if found */
6158 type
= (MonoType
*)mono_conc_hashtable_insert (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
), type2
);
6162 mono_image_unlock (image
);
6169 mono_image_strndup (MonoImage
*image
, const char *data
, guint len
)
6173 return g_strndup (data
, len
);
6174 res
= (char *)mono_image_alloc (image
, len
+ 1);
6175 memcpy (res
, data
, len
);
6181 * mono_metadata_parse_marshal_spec:
6184 mono_metadata_parse_marshal_spec (MonoImage
*image
, const char *ptr
)
6186 return mono_metadata_parse_marshal_spec_full (NULL
, image
, ptr
);
6190 * If IMAGE is non-null, memory will be allocated from its mempool, otherwise it will be allocated using malloc.
6191 * PARENT_IMAGE is the image containing the marshal spec.
6194 mono_metadata_parse_marshal_spec_full (MonoImage
*image
, MonoImage
*parent_image
, const char *ptr
)
6196 MonoMarshalSpec
*res
;
6198 const char *start
= ptr
;
6200 /* fixme: this is incomplete, but I cant find more infos in the specs */
6203 res
= (MonoMarshalSpec
*)mono_image_alloc0 (image
, sizeof (MonoMarshalSpec
));
6205 res
= g_new0 (MonoMarshalSpec
, 1);
6207 len
= mono_metadata_decode_value (ptr
, &ptr
);
6208 res
->native
= (MonoMarshalNative
)*ptr
++;
6210 if (res
->native
== MONO_NATIVE_LPARRAY
) {
6211 res
->data
.array_data
.param_num
= -1;
6212 res
->data
.array_data
.num_elem
= -1;
6213 res
->data
.array_data
.elem_mult
= -1;
6215 if (ptr
- start
<= len
)
6216 res
->data
.array_data
.elem_type
= (MonoMarshalNative
)*ptr
++;
6217 if (ptr
- start
<= len
)
6218 res
->data
.array_data
.param_num
= mono_metadata_decode_value (ptr
, &ptr
);
6219 if (ptr
- start
<= len
)
6220 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
6221 if (ptr
- start
<= len
) {
6223 * LAMESPEC: Older spec versions say this parameter comes before
6224 * num_elem. Never spec versions don't talk about elem_mult at
6225 * all, but csc still emits it, and it is used to distinguish
6226 * between param_num being 0, and param_num being omitted.
6227 * So if (param_num == 0) && (num_elem > 0), then
6228 * elem_mult == 0 -> the array size is num_elem
6229 * elem_mult == 1 -> the array size is @param_num + num_elem
6231 res
->data
.array_data
.elem_mult
= mono_metadata_decode_value (ptr
, &ptr
);
6235 if (res
->native
== MONO_NATIVE_BYVALTSTR
) {
6236 if (ptr
- start
<= len
)
6237 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
6240 if (res
->native
== MONO_NATIVE_BYVALARRAY
) {
6241 if (ptr
- start
<= len
)
6242 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
6245 if (res
->native
== MONO_NATIVE_CUSTOM
) {
6246 /* skip unused type guid */
6247 len
= mono_metadata_decode_value (ptr
, &ptr
);
6249 /* skip unused native type name */
6250 len
= mono_metadata_decode_value (ptr
, &ptr
);
6252 /* read custom marshaler type name */
6253 len
= mono_metadata_decode_value (ptr
, &ptr
);
6254 res
->data
.custom_data
.custom_name
= mono_image_strndup (image
, ptr
, len
);
6256 /* read cookie string */
6257 len
= mono_metadata_decode_value (ptr
, &ptr
);
6258 res
->data
.custom_data
.cookie
= mono_image_strndup (image
, ptr
, len
);
6259 res
->data
.custom_data
.image
= parent_image
;
6262 if (res
->native
== MONO_NATIVE_SAFEARRAY
) {
6263 res
->data
.safearray_data
.elem_type
= (MonoMarshalVariant
)0;
6264 res
->data
.safearray_data
.num_elem
= 0;
6265 if (ptr
- start
<= len
)
6266 res
->data
.safearray_data
.elem_type
= (MonoMarshalVariant
)*ptr
++;
6267 if (ptr
- start
<= len
)
6268 res
->data
.safearray_data
.num_elem
= *ptr
++;
6274 * mono_metadata_free_marshal_spec:
6277 mono_metadata_free_marshal_spec (MonoMarshalSpec
*spec
)
6282 if (spec
->native
== MONO_NATIVE_CUSTOM
) {
6283 g_free (spec
->data
.custom_data
.custom_name
);
6284 g_free (spec
->data
.custom_data
.cookie
);
6290 * mono_type_to_unmanaged:
6291 * The value pointed to by \p conv will contain the kind of marshalling required for this
6292 * particular type one of the \c MONO_MARSHAL_CONV_ enumeration values.
6293 * \returns A \c MonoMarshalNative enumeration value (<code>MONO_NATIVE_</code>) value
6294 * describing the underlying native reprensetation of the type.
6296 guint32
// FIXMEcxx MonoMarshalNative
6297 mono_type_to_unmanaged (MonoType
*type
, MonoMarshalSpec
*mspec
, gboolean as_field
,
6298 gboolean unicode
, MonoMarshalConv
*conv
)
6300 MonoMarshalConv dummy_conv
;
6306 *conv
= MONO_MARSHAL_CONV_NONE
;
6309 return MONO_NATIVE_UINT
;
6313 case MONO_TYPE_BOOLEAN
:
6315 switch (mspec
->native
) {
6316 case MONO_NATIVE_VARIANTBOOL
:
6317 *conv
= MONO_MARSHAL_CONV_BOOL_VARIANTBOOL
;
6318 return MONO_NATIVE_VARIANTBOOL
;
6319 case MONO_NATIVE_BOOLEAN
:
6320 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
6321 return MONO_NATIVE_BOOLEAN
;
6322 case MONO_NATIVE_I1
:
6323 case MONO_NATIVE_U1
:
6324 return mspec
->native
;
6326 g_error ("cant marshal bool to native type %02x", mspec
->native
);
6329 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
6330 return MONO_NATIVE_BOOLEAN
;
6331 case MONO_TYPE_CHAR
:
6333 switch (mspec
->native
) {
6334 case MONO_NATIVE_U2
:
6335 case MONO_NATIVE_U1
:
6336 return mspec
->native
;
6338 g_error ("cant marshal char to native type %02x", mspec
->native
);
6341 return unicode
? MONO_NATIVE_U2
: MONO_NATIVE_U1
;
6342 case MONO_TYPE_I1
: return MONO_NATIVE_I1
;
6343 case MONO_TYPE_U1
: return MONO_NATIVE_U1
;
6344 case MONO_TYPE_I2
: return MONO_NATIVE_I2
;
6345 case MONO_TYPE_U2
: return MONO_NATIVE_U2
;
6346 case MONO_TYPE_I4
: return MONO_NATIVE_I4
;
6347 case MONO_TYPE_U4
: return MONO_NATIVE_U4
;
6348 case MONO_TYPE_I8
: return MONO_NATIVE_I8
;
6349 case MONO_TYPE_U8
: return MONO_NATIVE_U8
;
6350 case MONO_TYPE_R4
: return MONO_NATIVE_R4
;
6351 case MONO_TYPE_R8
: return MONO_NATIVE_R8
;
6352 case MONO_TYPE_STRING
:
6354 switch (mspec
->native
) {
6355 case MONO_NATIVE_BSTR
:
6356 *conv
= MONO_MARSHAL_CONV_STR_BSTR
;
6357 return MONO_NATIVE_BSTR
;
6358 case MONO_NATIVE_LPSTR
:
6359 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
6360 return MONO_NATIVE_LPSTR
;
6361 case MONO_NATIVE_LPWSTR
:
6362 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
6363 return MONO_NATIVE_LPWSTR
;
6364 case MONO_NATIVE_LPTSTR
:
6365 *conv
= MONO_MARSHAL_CONV_STR_LPTSTR
;
6366 return MONO_NATIVE_LPTSTR
;
6367 case MONO_NATIVE_ANSIBSTR
:
6368 *conv
= MONO_MARSHAL_CONV_STR_ANSIBSTR
;
6369 return MONO_NATIVE_ANSIBSTR
;
6370 case MONO_NATIVE_TBSTR
:
6371 *conv
= MONO_MARSHAL_CONV_STR_TBSTR
;
6372 return MONO_NATIVE_TBSTR
;
6373 case MONO_NATIVE_UTF8STR
:
6374 *conv
= MONO_MARSHAL_CONV_STR_UTF8STR
;
6375 return MONO_NATIVE_UTF8STR
;
6376 case MONO_NATIVE_BYVALTSTR
:
6378 *conv
= MONO_MARSHAL_CONV_STR_BYVALWSTR
;
6380 *conv
= MONO_MARSHAL_CONV_STR_BYVALSTR
;
6381 return MONO_NATIVE_BYVALTSTR
;
6383 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
);
6387 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
6388 return MONO_NATIVE_LPWSTR
;
6391 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
6392 return MONO_NATIVE_LPSTR
;
6394 case MONO_TYPE_PTR
: return MONO_NATIVE_UINT
;
6395 case MONO_TYPE_VALUETYPE
: /*FIXME*/
6396 if (m_class_is_enumtype (type
->data
.klass
)) {
6397 t
= mono_class_enum_basetype_internal (type
->data
.klass
)->type
;
6400 if (type
->data
.klass
== mono_class_try_get_handleref_class ()){
6401 *conv
= MONO_MARSHAL_CONV_HANDLEREF
;
6402 return MONO_NATIVE_INT
;
6404 return MONO_NATIVE_STRUCT
;
6405 case MONO_TYPE_SZARRAY
:
6406 case MONO_TYPE_ARRAY
:
6408 switch (mspec
->native
) {
6409 case MONO_NATIVE_BYVALARRAY
:
6410 if ((m_class_get_element_class (type
->data
.klass
) == mono_defaults
.char_class
) && !unicode
)
6411 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY
;
6413 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALARRAY
;
6414 return MONO_NATIVE_BYVALARRAY
;
6415 case MONO_NATIVE_SAFEARRAY
:
6416 *conv
= MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
;
6417 return MONO_NATIVE_SAFEARRAY
;
6418 case MONO_NATIVE_LPARRAY
:
6419 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
6420 return MONO_NATIVE_LPARRAY
;
6422 g_error ("cant marshal array as native type %02x", mspec
->native
);
6426 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
6427 return MONO_NATIVE_LPARRAY
;
6428 case MONO_TYPE_I
: return MONO_NATIVE_INT
;
6429 case MONO_TYPE_U
: return MONO_NATIVE_UINT
;
6430 case MONO_TYPE_CLASS
:
6431 case MONO_TYPE_OBJECT
: {
6432 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
6434 switch (mspec
->native
) {
6435 case MONO_NATIVE_STRUCT
:
6436 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
6437 return MONO_NATIVE_STRUCT
;
6438 case MONO_NATIVE_CUSTOM
:
6439 return MONO_NATIVE_CUSTOM
;
6440 case MONO_NATIVE_INTERFACE
:
6441 *conv
= MONO_MARSHAL_CONV_OBJECT_INTERFACE
;
6442 return MONO_NATIVE_INTERFACE
;
6443 case MONO_NATIVE_IDISPATCH
:
6444 *conv
= MONO_MARSHAL_CONV_OBJECT_IDISPATCH
;
6445 return MONO_NATIVE_IDISPATCH
;
6446 case MONO_NATIVE_IUNKNOWN
:
6447 *conv
= MONO_MARSHAL_CONV_OBJECT_IUNKNOWN
;
6448 return MONO_NATIVE_IUNKNOWN
;
6449 case MONO_NATIVE_FUNC
:
6450 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
6451 type
->data
.klass
== mono_defaults
.delegate_class
||
6452 m_class_get_parent (type
->data
.klass
) == mono_defaults
.multicastdelegate_class
)) {
6453 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
6454 return MONO_NATIVE_FUNC
;
6458 g_error ("cant marshal object as native type %02x", mspec
->native
);
6461 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
6462 type
->data
.klass
== mono_defaults
.delegate_class
||
6463 m_class_get_parent (type
->data
.klass
) == mono_defaults
.multicastdelegate_class
)) {
6464 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
6465 return MONO_NATIVE_FUNC
;
6467 if (mono_class_try_get_safehandle_class () && type
->data
.klass
== mono_class_try_get_safehandle_class ()){
6468 *conv
= MONO_MARSHAL_CONV_SAFEHANDLE
;
6469 return MONO_NATIVE_INT
;
6471 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
6472 return MONO_NATIVE_STRUCT
;
6474 case MONO_TYPE_FNPTR
: return MONO_NATIVE_FUNC
;
6475 case MONO_TYPE_GENERICINST
:
6476 type
= m_class_get_byval_arg (type
->data
.generic_class
->container_class
);
6479 case MONO_TYPE_TYPEDBYREF
:
6481 g_error ("type 0x%02x not handled in marshal", t
);
6483 return MONO_NATIVE_MAX
;
6487 * mono_metadata_get_marshal_info:
6490 mono_metadata_get_marshal_info (MonoImage
*meta
, guint32 idx
, gboolean is_field
)
6493 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_FIELDMARSHAL
];
6499 loc
.col_idx
= MONO_FIELD_MARSHAL_PARENT
;
6500 loc
.idx
= ((idx
+ 1) << MONO_HAS_FIELD_MARSHAL_BITS
) | (is_field
? MONO_HAS_FIELD_MARSHAL_FIELDSREF
: MONO_HAS_FIELD_MARSHAL_PARAMDEF
);
6502 /* FIXME: Index translation */
6504 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6507 return mono_metadata_blob_heap (meta
, mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_MARSHAL_NATIVE_TYPE
));
6511 mono_method_from_method_def_or_ref (MonoImage
*m
, guint32 tok
, MonoGenericContext
*context
, MonoError
*error
)
6513 MonoMethod
*result
= NULL
;
6514 guint32 idx
= tok
>> MONO_METHODDEFORREF_BITS
;
6518 switch (tok
& MONO_METHODDEFORREF_MASK
) {
6519 case MONO_METHODDEFORREF_METHODDEF
:
6520 result
= mono_get_method_checked (m
, MONO_TOKEN_METHOD_DEF
| idx
, NULL
, context
, error
);
6522 case MONO_METHODDEFORREF_METHODREF
:
6523 result
= mono_get_method_checked (m
, MONO_TOKEN_MEMBER_REF
| idx
, NULL
, context
, error
);
6526 mono_error_set_bad_image (error
, m
, "Invalid MethodDefOfRef token %x", tok
);
6533 * mono_class_get_overrides_full:
6535 * Compute the method overrides belonging to class @type_token in @overrides, and the number of overrides in @num_overrides.
6539 mono_class_get_overrides_full (MonoImage
*image
, guint32 type_token
, MonoMethod
***overrides
, gint32
*num_overrides
, MonoGenericContext
*generic_context
, MonoError
*error
)
6542 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_METHODIMPL
];
6545 guint32 cols
[MONO_METHODIMPL_SIZE
];
6546 MonoMethod
**result
;
6558 loc
.col_idx
= MONO_METHODIMPL_CLASS
;
6559 loc
.idx
= mono_metadata_token_index (type_token
);
6561 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6567 * We may end up in the middle of the rows...
6570 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_METHODIMPL_CLASS
))
6575 while (end
< tdef
->rows
) {
6576 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, end
, MONO_METHODIMPL_CLASS
))
6582 result
= g_new (MonoMethod
*, num
* 2);
6583 for (i
= 0; i
< num
; ++i
) {
6586 if (!mono_verifier_verify_methodimpl_row (image
, start
+ i
, error
))
6589 mono_metadata_decode_row (tdef
, start
+ i
, cols
, MONO_METHODIMPL_SIZE
);
6590 method
= mono_method_from_method_def_or_ref (image
, cols
[MONO_METHODIMPL_DECLARATION
], generic_context
, error
);
6594 result
[i
* 2] = method
;
6595 method
= mono_method_from_method_def_or_ref (image
, cols
[MONO_METHODIMPL_BODY
], generic_context
, error
);
6599 result
[i
* 2 + 1] = method
;
6602 if (!is_ok (error
)) {
6608 *overrides
= result
;
6610 *num_overrides
= num
;
6615 * mono_guid_to_string:
6617 * Converts a 16 byte Microsoft GUID to the standard string representation.
6620 mono_guid_to_string (const guint8
*guid
)
6622 return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
6623 guid
[3], guid
[2], guid
[1], guid
[0],
6627 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
6631 * mono_guid_to_string_minimal:
6633 * Converts a 16 byte Microsoft GUID to lower case no '-' representation..
6636 mono_guid_to_string_minimal (const guint8
*guid
)
6638 return g_strdup_printf ("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
6639 guid
[3], guid
[2], guid
[1], guid
[0],
6643 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
6646 get_constraints (MonoImage
*image
, int owner
, MonoClass
***constraints
, MonoGenericContainer
*container
, MonoError
*error
)
6648 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
6649 guint32 cols
[MONO_GENPARCONSTRAINT_SIZE
];
6650 guint32 i
, token
, found
;
6651 MonoClass
*klass
, **res
;
6652 GSList
*cons
= NULL
, *tmp
;
6653 MonoGenericContext
*context
= &container
->context
;
6657 *constraints
= NULL
;
6659 for (i
= 0; i
< tdef
->rows
; ++i
) {
6660 mono_metadata_decode_row (tdef
, i
, cols
, MONO_GENPARCONSTRAINT_SIZE
);
6661 if (cols
[MONO_GENPARCONSTRAINT_GENERICPAR
] == owner
) {
6662 token
= mono_metadata_token_from_dor (cols
[MONO_GENPARCONSTRAINT_CONSTRAINT
]);
6663 klass
= mono_class_get_and_inflate_typespec_checked (image
, token
, context
, error
);
6665 g_slist_free (cons
);
6668 cons
= g_slist_append (cons
, klass
);
6671 /* contiguous list finished */
6678 res
= (MonoClass
**)mono_image_alloc0 (image
, sizeof (MonoClass
*) * (found
+ 1));
6679 for (i
= 0, tmp
= cons
; i
< found
; ++i
, tmp
= tmp
->next
) {
6680 res
[i
] = (MonoClass
*)tmp
->data
;
6682 g_slist_free (cons
);
6688 * mono_metadata_get_generic_param_row:
6691 * @token: TypeOrMethodDef token, owner for GenericParam
6692 * @owner: coded token, set on return
6694 * Returns: 1-based row-id in the GenericParam table whose
6695 * owner is @token. 0 if not found.
6698 mono_metadata_get_generic_param_row (MonoImage
*image
, guint32 token
, guint32
*owner
)
6700 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
6707 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPEDEF
)
6708 *owner
= MONO_TYPEORMETHOD_TYPE
;
6709 else if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
6710 *owner
= MONO_TYPEORMETHOD_METHOD
;
6712 g_error ("wrong token %x to get_generic_param_row", token
);
6715 *owner
|= mono_metadata_token_index (token
) << MONO_TYPEORMETHOD_BITS
;
6718 loc
.col_idx
= MONO_GENERICPARAM_OWNER
;
6721 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6724 /* Find the first entry by searching backwards */
6725 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_GENERICPARAM_OWNER
) == loc
.idx
))
6728 return loc
.result
+ 1;
6732 mono_metadata_has_generic_params (MonoImage
*image
, guint32 token
)
6735 return mono_metadata_get_generic_param_row (image
, token
, &owner
);
6739 * Memory is allocated from IMAGE's mempool.
6742 mono_metadata_load_generic_param_constraints_checked (MonoImage
*image
, guint32 token
,
6743 MonoGenericContainer
*container
, MonoError
*error
)
6746 guint32 start_row
, i
, owner
;
6749 if (! (start_row
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
6751 for (i
= 0; i
< container
->type_argc
; i
++) {
6752 if (!get_constraints (image
, start_row
+ i
, &mono_generic_container_get_param_info (container
, i
)->constraints
, container
, error
)) {
6760 * mono_metadata_load_generic_params:
6762 * Load the type parameters from the type or method definition @token.
6764 * Use this method after parsing a type or method definition to figure out whether it's a generic
6765 * type / method. When parsing a method definition, @parent_container points to the generic container
6766 * of the current class, if any.
6768 * Note: This method does not load the constraints: for typedefs, this has to be done after fully
6769 * creating the type.
6771 * Returns: NULL if @token is not a generic type or method definition or the new generic container.
6773 * LOCKING: Acquires the loader lock
6776 MonoGenericContainer
*
6777 mono_metadata_load_generic_params (MonoImage
*image
, guint32 token
, MonoGenericContainer
*parent_container
, gpointer real_owner
)
6779 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
6780 guint32 cols
[MONO_GENERICPARAM_SIZE
];
6781 guint32 i
, owner
= 0, n
;
6782 MonoGenericContainer
*container
;
6783 MonoGenericParamFull
*params
;
6784 MonoGenericContext
*context
;
6785 gboolean is_method
= mono_metadata_token_table (token
) == MONO_TABLE_METHOD
;
6786 gboolean is_anonymous
= real_owner
== NULL
;
6788 if (!(i
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
6790 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
6793 container
= (MonoGenericContainer
*)mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
6794 container
->is_anonymous
= is_anonymous
;
6796 container
->owner
.image
= image
;
6799 container
->owner
.method
= (MonoMethod
*)real_owner
;
6801 container
->owner
.klass
= (MonoClass
*)real_owner
;
6805 params
= (MonoGenericParamFull
*)g_realloc (params
, sizeof (MonoGenericParamFull
) * n
);
6806 memset (¶ms
[n
- 1], 0, sizeof (MonoGenericParamFull
));
6807 params
[n
- 1].owner
= container
;
6808 params
[n
- 1].num
= cols
[MONO_GENERICPARAM_NUMBER
];
6809 params
[n
- 1].info
.token
= i
| MONO_TOKEN_GENERIC_PARAM
;
6810 params
[n
- 1].info
.flags
= cols
[MONO_GENERICPARAM_FLAGS
];
6811 params
[n
- 1].info
.name
= mono_metadata_string_heap (image
, cols
[MONO_GENERICPARAM_NAME
]);
6812 if (params
[n
- 1].num
!= n
- 1)
6813 g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i
);
6814 if (++i
> tdef
->rows
)
6816 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
6817 } while (cols
[MONO_GENERICPARAM_OWNER
] == owner
);
6819 container
->type_argc
= n
;
6820 container
->type_params
= (MonoGenericParamFull
*)mono_image_alloc0 (image
, sizeof (MonoGenericParamFull
) * n
);
6821 memcpy (container
->type_params
, params
, sizeof (MonoGenericParamFull
) * n
);
6823 container
->parent
= parent_container
;
6826 container
->is_method
= 1;
6828 g_assert (container
->parent
== NULL
|| container
->is_method
);
6830 context
= &container
->context
;
6831 if (container
->is_method
) {
6832 context
->class_inst
= container
->parent
? container
->parent
->context
.class_inst
: NULL
;
6833 context
->method_inst
= mono_get_shared_generic_inst (container
);
6835 context
->class_inst
= mono_get_shared_generic_inst (container
);
6842 mono_get_shared_generic_inst (MonoGenericContainer
*container
)
6844 MonoType
**type_argv
;
6846 MonoGenericInst
*nginst
;
6849 type_argv
= g_new0 (MonoType
*, container
->type_argc
);
6850 helper
= g_new0 (MonoType
, container
->type_argc
);
6852 for (i
= 0; i
< container
->type_argc
; i
++) {
6853 MonoType
*t
= &helper
[i
];
6855 t
->type
= container
->is_method
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
6856 t
->data
.generic_param
= mono_generic_container_get_param (container
, i
);
6861 nginst
= mono_metadata_get_generic_inst (container
->type_argc
, type_argv
);
6870 * mono_type_is_byref:
6871 * \param type the \c MonoType operated on
6872 * \returns TRUE if \p type represents a type passed by reference,
6876 mono_type_is_byref (MonoType
*type
)
6879 MONO_ENTER_GC_UNSAFE
;
6880 result
= type
->byref
;
6881 MONO_EXIT_GC_UNSAFE
;
6886 * mono_type_get_type:
6887 * \param type the \c MonoType operated on
6888 * \returns the IL type value for \p type. This is one of the \c MonoTypeEnum
6889 * enum members like \c MONO_TYPE_I4 or \c MONO_TYPE_STRING.
6892 mono_type_get_type (MonoType
*type
)
6898 * mono_type_get_signature:
6899 * \param type the \c MonoType operated on
6900 * It is only valid to call this function if \p type is a \c MONO_TYPE_FNPTR .
6901 * \returns the \c MonoMethodSignature pointer that describes the signature
6902 * of the function pointer \p type represents.
6904 MonoMethodSignature
*
6905 mono_type_get_signature (MonoType
*type
)
6907 g_assert (type
->type
== MONO_TYPE_FNPTR
);
6908 return type
->data
.method
;
6912 * mono_type_get_class:
6913 * \param type the \c MonoType operated on
6914 * It is only valid to call this function if \p type is a \c MONO_TYPE_CLASS or a
6915 * \c MONO_TYPE_VALUETYPE . For more general functionality, use \c mono_class_from_mono_type_internal,
6917 * \returns the \c MonoClass pointer that describes the class that \p type represents.
6920 mono_type_get_class (MonoType
*type
)
6922 /* FIXME: review the runtime users before adding the assert here */
6923 return type
->data
.klass
;
6927 * mono_type_get_array_type:
6928 * \param type the \c MonoType operated on
6929 * It is only valid to call this function if \p type is a \c MONO_TYPE_ARRAY .
6930 * \returns a \c MonoArrayType struct describing the array type that \p type
6931 * represents. The info includes details such as rank, array element type
6932 * and the sizes and bounds of multidimensional arrays.
6935 mono_type_get_array_type (MonoType
*type
)
6937 return type
->data
.array
;
6941 * mono_type_get_ptr_type:
6942 * \pararm type the \c MonoType operated on
6943 * It is only valid to call this function if \p type is a \c MONO_TYPE_PTR .
6944 * \returns the \c MonoType pointer that describes the type that \p type
6945 * represents a pointer to.
6948 mono_type_get_ptr_type (MonoType
*type
)
6950 g_assert (type
->type
== MONO_TYPE_PTR
);
6951 return type
->data
.type
;
6955 * mono_type_get_modifiers:
6958 mono_type_get_modifiers (MonoType
*type
, gboolean
*is_required
, gpointer
*iter
)
6960 /* FIXME: implement */
6965 * mono_type_is_struct:
6966 * \param type the \c MonoType operated on
6967 * \returns TRUE if \p type is a struct, that is a \c ValueType but not an enum
6968 * or a basic type like \c System.Int32 . FALSE otherwise.
6971 mono_type_is_struct (MonoType
*type
)
6973 return (!type
->byref
&& ((type
->type
== MONO_TYPE_VALUETYPE
&&
6974 !m_class_is_enumtype (type
->data
.klass
)) || (type
->type
== MONO_TYPE_TYPEDBYREF
) ||
6975 ((type
->type
== MONO_TYPE_GENERICINST
) &&
6976 mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
) &&
6977 !m_class_is_enumtype (type
->data
.generic_class
->container_class
))));
6981 * mono_type_is_void:
6982 * \param type the \c MonoType operated on
6983 * \returns TRUE if \p type is \c System.Void . FALSE otherwise.
6986 mono_type_is_void (MonoType
*type
)
6988 return (type
&& (type
->type
== MONO_TYPE_VOID
) && !type
->byref
);
6992 * mono_type_is_pointer:
6993 * \param type the \c MonoType operated on
6994 * \returns TRUE if \p type is a managed or unmanaged pointer type. FALSE otherwise.
6997 mono_type_is_pointer (MonoType
*type
)
6999 return (type
&& ((type
->byref
|| (type
->type
== MONO_TYPE_I
) || type
->type
== MONO_TYPE_STRING
)
7000 || (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
7001 (type
->type
== MONO_TYPE_U
) || (type
->type
== MONO_TYPE_OBJECT
) ||
7002 (type
->type
== MONO_TYPE_ARRAY
) || (type
->type
== MONO_TYPE_PTR
) ||
7003 (type
->type
== MONO_TYPE_FNPTR
)));
7007 * mono_type_is_reference:
7008 * \param type the \c MonoType operated on
7009 * \returns TRUE if \p type represents an object reference. FALSE otherwise.
7012 mono_type_is_reference (MonoType
*type
)
7014 return (type
&& (((type
->type
== MONO_TYPE_STRING
) ||
7015 (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
7016 (type
->type
== MONO_TYPE_OBJECT
) || (type
->type
== MONO_TYPE_ARRAY
)) ||
7017 ((type
->type
== MONO_TYPE_GENERICINST
) &&
7018 !mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
))));
7022 mono_type_is_generic_parameter (MonoType
*type
)
7024 return !type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
);
7028 * mono_signature_get_return_type:
7029 * \param sig the method signature inspected
7030 * \returns the return type of the method signature \p sig
7033 mono_signature_get_return_type (MonoMethodSignature
*sig
)
7036 MONO_ENTER_GC_UNSAFE
;
7038 MONO_EXIT_GC_UNSAFE
;
7043 * mono_signature_get_params:
7044 * \param sig the method signature inspected
7045 * \param iter pointer to an iterator
7046 * Iterates over the parameters for the method signature \p sig.
7047 * A \c void* pointer must be initialized to NULL to start the iteration
7048 * and its address is passed to this function repeteadly until it returns
7050 * \returns the next parameter type of the method signature \p sig,
7051 * NULL when finished.
7054 mono_signature_get_params (MonoMethodSignature
*sig
, gpointer
*iter
)
7057 MONO_ENTER_GC_UNSAFE
;
7058 result
= mono_signature_get_params_internal (sig
, iter
);
7059 MONO_EXIT_GC_UNSAFE
;
7064 mono_signature_get_params_internal (MonoMethodSignature
*sig
, gpointer
*iter
)
7070 /* start from the first */
7071 if (sig
->param_count
) {
7072 *iter
= &sig
->params
[0];
7073 return sig
->params
[0];
7079 type
= (MonoType
**)*iter
;
7081 if (type
< &sig
->params
[sig
->param_count
]) {
7089 * mono_signature_get_param_count:
7090 * \param sig the method signature inspected
7091 * \returns the number of parameters in the method signature \p sig.
7094 mono_signature_get_param_count (MonoMethodSignature
*sig
)
7096 return sig
->param_count
;
7100 * mono_signature_get_call_conv:
7101 * \param sig the method signature inspected
7102 * \returns the call convention of the method signature \p sig.
7105 mono_signature_get_call_conv (MonoMethodSignature
*sig
)
7107 return sig
->call_convention
;
7111 * mono_signature_vararg_start:
7112 * \param sig the method signature inspected
7113 * \returns the number of the first vararg parameter in the
7114 * method signature \param sig. \c -1 if this is not a vararg signature.
7117 mono_signature_vararg_start (MonoMethodSignature
*sig
)
7119 return sig
->sentinelpos
;
7123 * mono_signature_is_instance:
7124 * \param sig the method signature inspected
7125 * \returns TRUE if this the method signature \p sig has an implicit
7126 * first instance argument. FALSE otherwise.
7129 mono_signature_is_instance (MonoMethodSignature
*sig
)
7131 return sig
->hasthis
;
7135 * mono_signature_param_is_out
7136 * \param sig the method signature inspected
7137 * \param param_num the 0-based index of the inspected parameter
7138 * \returns TRUE if the parameter is an out parameter, FALSE
7142 mono_signature_param_is_out (MonoMethodSignature
*sig
, int param_num
)
7144 g_assert (param_num
>= 0 && param_num
< sig
->param_count
);
7145 return (sig
->params
[param_num
]->attrs
& PARAM_ATTRIBUTE_OUT
) != 0;
7149 * mono_signature_explicit_this:
7150 * \param sig the method signature inspected
7151 * \returns TRUE if this the method signature \p sig has an explicit
7152 * instance argument. FALSE otherwise.
7155 mono_signature_explicit_this (MonoMethodSignature
*sig
)
7157 return sig
->explicit_this
;
7160 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
7162 mono_aligned_addr_hash (gconstpointer ptr
)
7164 /* Same hashing we use for objects */
7165 return (GPOINTER_TO_UINT (ptr
) >> 3) * 2654435761u;
7169 * If @field belongs to an inflated generic class, return the corresponding field of the
7170 * generic type definition class.
7173 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField
*field
)
7178 if (!mono_class_is_ginst (field
->parent
))
7181 gtd
= mono_class_get_generic_class (field
->parent
)->container_class
;
7182 offset
= field
- m_class_get_fields (field
->parent
);
7183 return m_class_get_fields (gtd
) + offset
;
7187 * If @event belongs to an inflated generic class, return the corresponding event of the
7188 * generic type definition class.
7191 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent
*event
)
7196 if (!mono_class_is_ginst (event
->parent
))
7199 gtd
= mono_class_get_generic_class (event
->parent
)->container_class
;
7200 offset
= event
- mono_class_get_event_info (event
->parent
)->events
;
7201 return mono_class_get_event_info (gtd
)->events
+ offset
;
7205 * If @property belongs to an inflated generic class, return the corresponding property of the
7206 * generic type definition class.
7209 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty
*property
)
7211 MonoClassPropertyInfo
*info
;
7215 if (!mono_class_is_ginst (property
->parent
))
7218 info
= mono_class_get_property_info (property
->parent
);
7219 gtd
= mono_class_get_generic_class (property
->parent
)->container_class
;
7220 offset
= property
- info
->properties
;
7221 return mono_class_get_property_info (gtd
)->properties
+ offset
;
7225 mono_method_get_wrapper_cache (MonoMethod
*method
)
7227 if (method
->is_inflated
) {
7228 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
7229 return &imethod
->owner
->wrapper_caches
;
7231 return &m_class_get_image (method
->klass
)->wrapper_caches
;
7235 // 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.
7238 * mono_find_image_set_owner:
7240 * Find the imageset, if any, which a given pointer is located in the memory of.
7243 mono_find_image_set_owner (void *ptr
)
7245 MonoImageSet
*owner
= NULL
;
7252 for (i
= 0; !owner
&& i
< image_sets
->len
; ++i
) {
7253 MonoImageSet
*set
= (MonoImageSet
*)g_ptr_array_index (image_sets
, i
);
7254 if (mono_mempool_contains_addr (set
->mempool
, ptr
))
7259 image_sets_unlock ();
7265 mono_loader_set_strict_strong_names (gboolean enabled
)
7267 check_strong_names_strictly
= enabled
;
7271 mono_loader_get_strict_strong_names (void)
7273 return check_strong_names_strictly
;
7277 MonoCustomModContainer
*
7278 mono_type_get_cmods (const MonoType
*t
)
7283 MonoTypeWithModifiers
*full
= (MonoTypeWithModifiers
*)t
;
7285 return &full
->cmods
;
7289 mono_sizeof_type_with_mods (uint8_t num_mods
)
7292 accum
+= sizeof (MonoType
);
7296 accum
+= offsetof (struct _MonoCustomModContainer
, modifiers
);
7297 accum
+= sizeof (MonoCustomMod
) * num_mods
;
7302 mono_sizeof_type (const MonoType
*ty
)
7304 MonoCustomModContainer
*cmods
= mono_type_get_cmods (ty
);
7306 return mono_sizeof_type_with_mods (cmods
->count
);
7308 return sizeof (MonoType
);