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 tableidx
)
562 if (meta
->referenced_tables
&& (meta
->referenced_tables
& ((guint64
)1 << tableidx
)))
563 return meta
->referenced_table_rows
[tableidx
] < 65536 ? 2 : 4;
565 return meta
->tables
[tableidx
].rows
< 65536 ? 2 : 4;
569 get_nrows (MonoImage
*meta
, int tableidx
)
571 if (meta
->referenced_tables
&& (meta
->referenced_tables
& ((guint64
)1 << tableidx
)))
572 return meta
->referenced_table_rows
[tableidx
];
574 return meta
->tables
[tableidx
].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 #if SIZEOF_VOID_P == 8
1122 return (const unsigned char *) (((guint64
) (ptr
+ 3)) & ~3);
1124 return (const unsigned char *) (((guint32
) (ptr
+ 3)) & ~3);
1129 * mono_metadata_decode_row:
1130 * \param t table to extract information from.
1131 * \param idx index in table.
1132 * \param res array of \p res_size cols to store the results in
1134 * This decompresses the metadata element \p idx in table \p t
1135 * into the \c guint32 \p res array that has \p res_size elements
1138 mono_metadata_decode_row (const MonoTableInfo
*t
, int idx
, guint32
*res
, int res_size
)
1140 guint32 bitfield
= t
->size_bitfield
;
1141 int i
, count
= mono_metadata_table_count (bitfield
);
1144 g_assert (idx
< t
->rows
);
1145 g_assert (idx
>= 0);
1146 data
= t
->base
+ idx
* t
->row_size
;
1148 g_assert (res_size
== count
);
1150 for (i
= 0; i
< count
; i
++) {
1151 int n
= mono_metadata_table_size (bitfield
, i
);
1155 res
[i
] = *data
; break;
1157 res
[i
] = read16 (data
); break;
1159 res
[i
] = read32 (data
); break;
1161 g_assert_not_reached ();
1168 * mono_metadata_decode_row_checked:
1169 * \param image the \c MonoImage the table belongs to
1170 * \param t table to extract information from.
1171 * \param idx index in the table.
1172 * \param res array of \p res_size cols to store the results in
1173 * \param error set on bounds error
1176 * This decompresses the metadata element \p idx in the table \p t
1177 * into the \c guint32 \p res array that has \p res_size elements.
1179 * \returns TRUE if the read succeeded. Otherwise sets \p error and returns FALSE.
1182 mono_metadata_decode_row_checked (const MonoImage
*image
, const MonoTableInfo
*t
, int idx
, guint32
*res
, int res_size
, MonoError
*error
)
1184 guint32 bitfield
= t
->size_bitfield
;
1185 int i
, count
= mono_metadata_table_count (bitfield
);
1187 const char *image_name
= image
&& image
->name
? image
->name
: "unknown image";
1189 if (G_UNLIKELY (! (idx
< t
->rows
&& idx
>= 0))) {
1190 mono_error_set_bad_image_by_name (error
, image_name
, "row index %d out of bounds: %d rows", idx
, t
->rows
);
1193 const char *data
= t
->base
+ idx
* t
->row_size
;
1195 if (G_UNLIKELY (res_size
!= count
)) {
1196 mono_error_set_bad_image_by_name (error
, image_name
, "res_size %d != count %d", res_size
, count
);
1200 for (i
= 0; i
< count
; i
++) {
1201 int n
= mono_metadata_table_size (bitfield
, i
);
1205 res
[i
] = *data
; break;
1207 res
[i
] = read16 (data
); break;
1209 res
[i
] = read32 (data
); break;
1211 mono_error_set_bad_image_by_name (error
, image_name
, "unexpected table [%d] size %d", i
, n
);
1221 * mono_metadata_decode_row_col:
1222 * \param t table to extract information from.
1223 * \param idx index for row in table.
1224 * \param col column in the row.
1226 * This function returns the value of column \p col from the \p idx
1227 * row in the table \p t .
1230 mono_metadata_decode_row_col (const MonoTableInfo
*t
, int idx
, guint col
)
1232 guint32 bitfield
= t
->size_bitfield
;
1237 g_assert (idx
< t
->rows
);
1238 g_assert (col
< mono_metadata_table_count (bitfield
));
1239 data
= t
->base
+ idx
* t
->row_size
;
1241 n
= mono_metadata_table_size (bitfield
, 0);
1242 for (i
= 0; i
< col
; ++i
) {
1244 n
= mono_metadata_table_size (bitfield
, i
+ 1);
1250 return read16 (data
);
1252 return read32 (data
);
1254 g_assert_not_reached ();
1260 * mono_metadata_decode_blob_size:
1261 * \param ptr pointer to a blob object
1262 * \param rptr the new position of the pointer
1264 * This decodes a compressed size as described by 24.2.4 (#US and #Blob a blob or user string object)
1266 * \returns the size of the blob object
1269 mono_metadata_decode_blob_size (const char *xptr
, const char **rptr
)
1271 const unsigned char *ptr
= (const unsigned char *)xptr
;
1274 if ((*ptr
& 0x80) == 0){
1275 size
= ptr
[0] & 0x7f;
1277 } else if ((*ptr
& 0x40) == 0){
1278 size
= ((ptr
[0] & 0x3f) << 8) + ptr
[1];
1281 size
= ((ptr
[0] & 0x1f) << 24) +
1293 * mono_metadata_decode_value:
1294 * \param ptr pointer to decode from
1295 * \param rptr the new position of the pointer
1297 * This routine decompresses 32-bit values as specified in the "Blob and
1298 * Signature" section (23.2)
1300 * \returns the decoded value
1303 mono_metadata_decode_value (const char *_ptr
, const char **rptr
)
1305 const unsigned char *ptr
= (const unsigned char *) _ptr
;
1306 unsigned char b
= *ptr
;
1309 if ((b
& 0x80) == 0){
1312 } else if ((b
& 0x40) == 0){
1313 len
= ((b
& 0x3f) << 8 | ptr
[1]);
1316 len
= ((b
& 0x1f) << 24) |
1329 * mono_metadata_decode_signed_value:
1330 * \param ptr pointer to decode from
1331 * \param rptr the new position of the pointer
1333 * This routine decompresses 32-bit signed values
1334 * (not specified in the spec)
1336 * \returns the decoded value
1339 mono_metadata_decode_signed_value (const char *ptr
, const char **rptr
)
1341 guint32 uval
= mono_metadata_decode_value (ptr
, rptr
);
1342 gint32 ival
= uval
>> 1;
1345 /* ival is a truncated 2's complement negative number. */
1347 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1350 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1351 return ival
- 0x2000;
1352 if (ival
< 0x10000000)
1353 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1354 return ival
- 0x10000000;
1355 g_assert (ival
< 0x20000000);
1356 g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival
, uval
);
1357 return ival
- 0x20000000;
1361 * mono_metadata_translate_token_index:
1362 * Translates the given 1-based index into the \c Method, \c Field, \c Event, or \c Param tables
1363 * using the \c *Ptr tables in uncompressed metadata, if they are available.
1365 * FIXME: The caller is not forced to call this function, which is error-prone, since
1366 * forgetting to call it would only show up as a bug on uncompressed metadata.
1369 mono_metadata_translate_token_index (MonoImage
*image
, int table
, guint32 idx
)
1371 if (!image
->uncompressed_metadata
)
1375 case MONO_TABLE_METHOD
:
1376 if (image
->tables
[MONO_TABLE_METHOD_POINTER
].rows
)
1377 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_METHOD_POINTER
], idx
- 1, MONO_METHOD_POINTER_METHOD
);
1380 case MONO_TABLE_FIELD
:
1381 if (image
->tables
[MONO_TABLE_FIELD_POINTER
].rows
)
1382 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_FIELD_POINTER
], idx
- 1, MONO_FIELD_POINTER_FIELD
);
1385 case MONO_TABLE_EVENT
:
1386 if (image
->tables
[MONO_TABLE_EVENT_POINTER
].rows
)
1387 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_EVENT_POINTER
], idx
- 1, MONO_EVENT_POINTER_EVENT
);
1390 case MONO_TABLE_PROPERTY
:
1391 if (image
->tables
[MONO_TABLE_PROPERTY_POINTER
].rows
)
1392 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PROPERTY_POINTER
], idx
- 1, MONO_PROPERTY_POINTER_PROPERTY
);
1395 case MONO_TABLE_PARAM
:
1396 if (image
->tables
[MONO_TABLE_PARAM_POINTER
].rows
)
1397 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PARAM_POINTER
], idx
- 1, MONO_PARAM_POINTER_PARAM
);
1406 * mono_metadata_decode_table_row:
1408 * Same as \c mono_metadata_decode_row, but takes an \p image + \p table ID pair, and takes
1409 * uncompressed metadata into account, so it should be used to access the
1410 * \c Method, \c Field, \c Param and \c Event tables when the access is made from metadata, i.e.
1411 * \p idx is retrieved from a metadata table, like \c MONO_TYPEDEF_FIELD_LIST.
1414 mono_metadata_decode_table_row (MonoImage
*image
, int table
, int idx
, guint32
*res
, int res_size
)
1416 if (image
->uncompressed_metadata
)
1417 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1419 mono_metadata_decode_row (&image
->tables
[table
], idx
, res
, res_size
);
1423 * mono_metadata_decode_table_row_col:
1425 * Same as \c mono_metadata_decode_row_col, but takes an \p image + \p table ID pair, and takes
1426 * uncompressed metadata into account, so it should be used to access the
1427 * \c Method, \c Field, \c Param and \c Event tables.
1429 guint32
mono_metadata_decode_table_row_col (MonoImage
*image
, int table
, int idx
, guint col
)
1431 if (image
->uncompressed_metadata
)
1432 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1434 return mono_metadata_decode_row_col (&image
->tables
[table
], idx
, col
);
1438 * mono_metadata_parse_typedef_or_ref:
1439 * \param m a metadata context.
1440 * \param ptr a pointer to an encoded TypedefOrRef in \p m
1441 * \param rptr pointer updated to match the end of the decoded stream
1442 * \returns a token valid in the \p m metadata decoded from
1443 * the compressed representation.
1446 mono_metadata_parse_typedef_or_ref (MonoImage
*m
, const char *ptr
, const char **rptr
)
1449 token
= mono_metadata_decode_value (ptr
, &ptr
);
1452 return mono_metadata_token_from_dor (token
);
1456 * mono_metadata_parse_custom_mod:
1457 * \param m a metadata context.
1458 * \param dest storage where the info about the custom modifier is stored (may be NULL)
1459 * \param ptr a pointer to (possibly) the start of a custom modifier list
1460 * \param rptr pointer updated to match the end of the decoded stream
1462 * Checks if \p ptr points to a type custom modifier compressed representation.
1464 * \returns TRUE if a custom modifier was found, FALSE if not.
1467 mono_metadata_parse_custom_mod (MonoImage
*m
, MonoCustomMod
*dest
, const char *ptr
, const char **rptr
)
1469 MonoCustomMod local
;
1470 if ((*ptr
== MONO_TYPE_CMOD_OPT
) || (*ptr
== MONO_TYPE_CMOD_REQD
)) {
1473 dest
->required
= *ptr
== MONO_TYPE_CMOD_REQD
? 1 : 0;
1474 dest
->token
= mono_metadata_parse_typedef_or_ref (m
, ptr
+ 1, rptr
);
1481 * mono_metadata_parse_array_internal:
1482 * @m: a metadata context.
1483 * @transient: whenever to allocate data from the heap
1484 * @ptr: a pointer to an encoded array description.
1485 * @rptr: pointer updated to match the end of the decoded stream
1487 * Decodes the compressed array description found in the metadata @m at @ptr.
1489 * Returns: a #MonoArrayType structure describing the array type
1490 * and dimensions. Memory is allocated from the heap or from the image mempool, depending
1491 * on the value of @transient.
1493 * LOCKING: Acquires the loader lock
1495 static MonoArrayType
*
1496 mono_metadata_parse_array_internal (MonoImage
*m
, MonoGenericContainer
*container
,
1497 gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1500 MonoArrayType
*array
;
1503 etype
= mono_metadata_parse_type_checked (m
, container
, 0, FALSE
, ptr
, &ptr
, error
); //FIXME this doesn't respect @transient
1507 array
= transient
? (MonoArrayType
*)g_malloc0 (sizeof (MonoArrayType
)) : (MonoArrayType
*)mono_image_alloc0 (m
, sizeof (MonoArrayType
));
1508 array
->eklass
= mono_class_from_mono_type_internal (etype
);
1509 array
->rank
= mono_metadata_decode_value (ptr
, &ptr
);
1511 array
->numsizes
= mono_metadata_decode_value (ptr
, &ptr
);
1512 if (array
->numsizes
)
1513 array
->sizes
= transient
? (int *)g_malloc0 (sizeof (int) * array
->numsizes
) : (int *)mono_image_alloc0 (m
, sizeof (int) * array
->numsizes
);
1514 for (i
= 0; i
< array
->numsizes
; ++i
)
1515 array
->sizes
[i
] = mono_metadata_decode_value (ptr
, &ptr
);
1517 array
->numlobounds
= mono_metadata_decode_value (ptr
, &ptr
);
1518 if (array
->numlobounds
)
1519 array
->lobounds
= transient
? (int *)g_malloc0 (sizeof (int) * array
->numlobounds
) : (int *)mono_image_alloc0 (m
, sizeof (int) * array
->numlobounds
);
1520 for (i
= 0; i
< array
->numlobounds
; ++i
)
1521 array
->lobounds
[i
] = mono_metadata_decode_signed_value (ptr
, &ptr
);
1529 * mono_metadata_parse_array:
1532 mono_metadata_parse_array (MonoImage
*m
, const char *ptr
, const char **rptr
)
1535 MonoArrayType
*ret
= mono_metadata_parse_array_internal (m
, NULL
, FALSE
, ptr
, rptr
, error
);
1536 mono_error_cleanup (error
);
1542 * mono_metadata_free_array:
1543 * \param array array description
1545 * Frees the array description returned from \c mono_metadata_parse_array.
1548 mono_metadata_free_array (MonoArrayType
*array
)
1550 g_free (array
->sizes
);
1551 g_free (array
->lobounds
);
1556 * need to add common field and param attributes combinations:
1559 * public static literal
1562 * private static literal
1564 static const MonoType
1566 /* data, attrs, type, nmods, byref, pinned */
1567 {{NULL
}, 0, MONO_TYPE_VOID
, 0, 0, 0},
1568 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 0, 0},
1569 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 1, 0},
1570 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 0, 0},
1571 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 1, 0},
1572 {{NULL
}, 0, MONO_TYPE_I1
, 0, 0, 0},
1573 {{NULL
}, 0, MONO_TYPE_I1
, 0, 1, 0},
1574 {{NULL
}, 0, MONO_TYPE_U1
, 0, 0, 0},
1575 {{NULL
}, 0, MONO_TYPE_U1
, 0, 1, 0},
1576 {{NULL
}, 0, MONO_TYPE_I2
, 0, 0, 0},
1577 {{NULL
}, 0, MONO_TYPE_I2
, 0, 1, 0},
1578 {{NULL
}, 0, MONO_TYPE_U2
, 0, 0, 0},
1579 {{NULL
}, 0, MONO_TYPE_U2
, 0, 1, 0},
1580 {{NULL
}, 0, MONO_TYPE_I4
, 0, 0, 0},
1581 {{NULL
}, 0, MONO_TYPE_I4
, 0, 1, 0},
1582 {{NULL
}, 0, MONO_TYPE_U4
, 0, 0, 0},
1583 {{NULL
}, 0, MONO_TYPE_U4
, 0, 1, 0},
1584 {{NULL
}, 0, MONO_TYPE_I8
, 0, 0, 0},
1585 {{NULL
}, 0, MONO_TYPE_I8
, 0, 1, 0},
1586 {{NULL
}, 0, MONO_TYPE_U8
, 0, 0, 0},
1587 {{NULL
}, 0, MONO_TYPE_U8
, 0, 1, 0},
1588 {{NULL
}, 0, MONO_TYPE_R4
, 0, 0, 0},
1589 {{NULL
}, 0, MONO_TYPE_R4
, 0, 1, 0},
1590 {{NULL
}, 0, MONO_TYPE_R8
, 0, 0, 0},
1591 {{NULL
}, 0, MONO_TYPE_R8
, 0, 1, 0},
1592 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 0, 0},
1593 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 1, 0},
1594 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 0, 0},
1595 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 1, 0},
1596 {{NULL
}, 0, MONO_TYPE_TYPEDBYREF
, 0, 0, 0},
1597 {{NULL
}, 0, MONO_TYPE_I
, 0, 0, 0},
1598 {{NULL
}, 0, MONO_TYPE_I
, 0, 1, 0},
1599 {{NULL
}, 0, MONO_TYPE_U
, 0, 0, 0},
1600 {{NULL
}, 0, MONO_TYPE_U
, 0, 1, 0},
1603 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1605 static GHashTable
*type_cache
= NULL
;
1606 static gint32 next_generic_inst_id
= 0;
1608 /* Protected by image_sets_mutex */
1609 static MonoImageSet
*mscorlib_image_set
;
1610 /* Protected by image_sets_mutex */
1611 static GPtrArray
*image_sets
;
1612 static mono_mutex_t image_sets_mutex
;
1614 static guint
mono_generic_class_hash (gconstpointer data
);
1617 * MonoTypes with modifies are never cached, so we never check or use that field.
1620 mono_type_hash (gconstpointer data
)
1622 const MonoType
*type
= (const MonoType
*) data
;
1623 if (type
->type
== MONO_TYPE_GENERICINST
)
1624 return mono_generic_class_hash (type
->data
.generic_class
);
1626 return type
->type
| (type
->byref
<< 8) | (type
->attrs
<< 9);
1630 mono_type_equal (gconstpointer ka
, gconstpointer kb
)
1632 const MonoType
*a
= (const MonoType
*) ka
;
1633 const MonoType
*b
= (const MonoType
*) kb
;
1635 if (a
->type
!= b
->type
|| a
->byref
!= b
->byref
|| a
->attrs
!= b
->attrs
|| a
->pinned
!= b
->pinned
)
1637 /* need other checks */
1642 mono_metadata_generic_inst_hash (gconstpointer data
)
1644 const MonoGenericInst
*ginst
= (const MonoGenericInst
*) data
;
1648 g_assert (ginst
->type_argv
);
1650 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
1652 g_assert (ginst
->type_argv
[i
]);
1653 hash
+= mono_metadata_type_hash (ginst
->type_argv
[i
]);
1656 return hash
^ (ginst
->is_open
<< 8);
1660 mono_generic_inst_equal_full (const MonoGenericInst
*a
, const MonoGenericInst
*b
, gboolean signature_only
)
1664 // An optimization: if the ids of two insts are the same, we know they are the same inst and don't check contents.
1665 // Furthermore, because we perform early de-duping, if the ids differ, we know the contents differ.
1666 #ifndef MONO_SMALL_CONFIG // Optimization does not work in MONO_SMALL_CONFIG: There are no IDs
1667 if (a
->id
&& b
->id
) { // "id 0" means "object has no id"-- de-duping hasn't been performed yet, must check contents.
1670 // In signature-comparison mode id equality implies object equality, but this is not true for inequality.
1671 // Two separate objects could have signature-equavalent contents.
1672 if (!signature_only
)
1677 if (a
->is_open
!= b
->is_open
|| a
->type_argc
!= b
->type_argc
)
1679 for (i
= 0; i
< a
->type_argc
; ++i
) {
1680 if (!do_mono_metadata_type_equal (a
->type_argv
[i
], b
->type_argv
[i
], signature_only
))
1687 mono_metadata_generic_inst_equal (gconstpointer ka
, gconstpointer kb
)
1689 const MonoGenericInst
*a
= (const MonoGenericInst
*) ka
;
1690 const MonoGenericInst
*b
= (const MonoGenericInst
*) kb
;
1692 return mono_generic_inst_equal_full (a
, b
, FALSE
);
1696 mono_generic_class_hash (gconstpointer data
)
1698 const MonoGenericClass
*gclass
= (const MonoGenericClass
*) data
;
1699 guint hash
= mono_metadata_type_hash (m_class_get_byval_arg (gclass
->container_class
));
1702 hash
+= gclass
->is_tb_open
;
1703 hash
+= mono_metadata_generic_context_hash (&gclass
->context
);
1709 mono_generic_class_equal (gconstpointer ka
, gconstpointer kb
)
1711 const MonoGenericClass
*a
= (const MonoGenericClass
*) ka
;
1712 const MonoGenericClass
*b
= (const MonoGenericClass
*) kb
;
1714 return _mono_metadata_generic_class_equal (a
, b
, FALSE
);
1718 * mono_metadata_init:
1720 * Initialize the global variables of this module.
1721 * This is a Mono runtime internal function.
1724 mono_metadata_init (void)
1728 /* We guard against double initialization due to how pedump in verification mode works.
1729 Until runtime initialization is properly factored to work with what it needs we need workarounds like this.
1730 FIXME: https://bugzilla.xamarin.com/show_bug.cgi?id=58793
1732 static gboolean inited
;
1738 type_cache
= g_hash_table_new (mono_type_hash
, mono_type_equal
);
1740 for (i
= 0; i
< NBUILTIN_TYPES (); ++i
)
1741 g_hash_table_insert (type_cache
, (gpointer
) &builtin_types
[i
], (gpointer
) &builtin_types
[i
]);
1743 mono_os_mutex_init_recursive (&image_sets_mutex
);
1745 mono_counters_register ("ImgSet Cache Hit", MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &img_set_cache_hit
);
1746 mono_counters_register ("ImgSet Cache Miss", MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &img_set_cache_miss
);
1747 mono_counters_register ("ImgSet Count", MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &img_set_count
);
1751 * mono_metadata_cleanup:
1753 * Free all resources used by this module.
1754 * This is a Mono runtime internal function.
1757 mono_metadata_cleanup (void)
1759 g_hash_table_destroy (type_cache
);
1761 g_ptr_array_free (image_sets
, TRUE
);
1763 mono_os_mutex_destroy (&image_sets_mutex
);
1767 * mono_metadata_parse_type:
1768 * \param m metadata context
1769 * \param mode kind of type that may be found at \p ptr
1770 * \param opt_attrs optional attributes to store in the returned type
1771 * \param ptr pointer to the type representation
1772 * \param rptr pointer updated to match the end of the decoded stream
1773 * \param transient whenever to allocate the result from the heap or from a mempool
1775 * Decode a compressed type description found at \p ptr in \p m .
1776 * \p mode can be one of \c MONO_PARSE_MOD_TYPE, \c MONO_PARSE_PARAM, \c MONO_PARSE_RET,
1777 * \c MONO_PARSE_FIELD, \c MONO_PARSE_LOCAL, \c MONO_PARSE_TYPE.
1778 * This function can be used to decode type descriptions in method signatures,
1779 * field signatures, locals signatures etc.
1781 * To parse a generic type, \c generic_container points to the current class'es
1782 * (the \c generic_container field in the <code>MonoClass</code>) or the current generic method's
1783 * (stored in <code>image->property_hash</code>) generic container.
1784 * When we encounter a \c MONO_TYPE_VAR or \c MONO_TYPE_MVAR, it's looked up in
1785 * this \c MonoGenericContainer.
1787 * LOCKING: Acquires the loader lock.
1789 * \returns a \c MonoType structure representing the decoded type.
1792 mono_metadata_parse_type_internal (MonoImage
*m
, MonoGenericContainer
*container
,
1793 short opt_attrs
, gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1795 MonoType
*type
, *cached
;
1797 gboolean byref
= FALSE
;
1798 gboolean pinned
= FALSE
;
1799 const char *tmp_ptr
;
1800 int count
= 0; // Number of mod arguments
1806 * According to the spec, custom modifiers should come before the byref
1807 * flag, but the IL produced by ilasm from the following signature:
1808 * object modopt(...) &
1809 * starts with a byref flag, followed by the modifiers. (bug #49802)
1810 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1811 * it would be better to treat byref as real type constructor instead of
1813 * Also, pinned should come before anything else, but some MSV++ produced
1814 * assemblies violate this (#bug 61990).
1817 /* Count the modifiers first */
1822 case MONO_TYPE_PINNED
:
1823 case MONO_TYPE_BYREF
:
1826 case MONO_TYPE_CMOD_REQD
:
1827 case MONO_TYPE_CMOD_OPT
:
1829 mono_metadata_parse_custom_mod (m
, NULL
, tmp_ptr
, &tmp_ptr
);
1836 MonoCustomModContainer
*cmods
= NULL
;
1838 if (count
) { // There are mods, so the MonoType will be of nonstandard size.
1840 mono_error_set_bad_image (error
, m
, "Invalid type with more than 64 modifiers");
1844 size_t size
= mono_sizeof_type_with_mods (count
);
1845 type
= transient
? (MonoType
*)g_malloc0 (size
) : (MonoType
*)mono_image_alloc0 (m
, size
);
1846 type
->has_cmods
= TRUE
;
1848 cmods
= mono_type_get_cmods (type
);
1849 cmods
->count
= count
;
1851 } else { // The type is of standard size, so we can allocate it on the stack.
1853 memset (type
, 0, MONO_SIZEOF_TYPE
);
1856 /* Iterate again, but now parse pinned, byref and custom modifiers */
1861 case MONO_TYPE_PINNED
:
1865 case MONO_TYPE_BYREF
:
1869 case MONO_TYPE_CMOD_REQD
:
1870 case MONO_TYPE_CMOD_OPT
:
1871 mono_metadata_parse_custom_mod (m
, &(cmods
->modifiers
[count
]), ptr
, &ptr
);
1879 type
->attrs
= opt_attrs
;
1880 type
->byref
= byref
;
1881 type
->pinned
= pinned
? 1 : 0;
1883 if (!do_mono_metadata_parse_type (type
, m
, container
, transient
, ptr
, &ptr
, error
))
1889 // Possibly we can return an already-allocated type instead of the one we decoded
1890 if (!type
->has_cmods
&& !transient
) {
1891 /* no need to free type here, because it is on the stack */
1892 if ((type
->type
== MONO_TYPE_CLASS
|| type
->type
== MONO_TYPE_VALUETYPE
) && !type
->pinned
&& !type
->attrs
) {
1893 MonoType
*ret
= type
->byref
? m_class_get_this_arg (type
->data
.klass
) : m_class_get_byval_arg (type
->data
.klass
);
1895 /* Consider the case:
1897 class Foo<T> { class Bar {} }
1898 class Test : Foo<Test>.Bar {}
1900 When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
1901 a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1903 We ensure that the MonoClass is in a state that we can canonicalize to:
1905 klass->_byval_arg.data.klass == klass
1906 klass->this_arg.data.klass == klass
1908 If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1910 LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1911 of a MonoClass which currently holds the loader lock. 'type' is local.
1913 if (ret
->data
.klass
== type
->data
.klass
) {
1917 /* No need to use locking since nobody is modifying the hash table */
1918 if ((cached
= (MonoType
*)g_hash_table_lookup (type_cache
, type
))) {
1923 /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1925 if (type
== &stype
) { // Type was allocated on the stack, so we need to copy it to safety
1926 type
= transient
? (MonoType
*)g_malloc (MONO_SIZEOF_TYPE
) : (MonoType
*)mono_image_alloc (m
, MONO_SIZEOF_TYPE
);
1927 memcpy (type
, &stype
, MONO_SIZEOF_TYPE
);
1934 mono_metadata_parse_type_checked (MonoImage
*m
, MonoGenericContainer
*container
,
1935 short opt_attrs
, gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1937 return mono_metadata_parse_type_internal (m
, container
, opt_attrs
, transient
, ptr
, rptr
, error
);
1941 * LOCKING: Acquires the loader lock.
1944 mono_metadata_parse_type (MonoImage
*m
, MonoParseTypeMode mode
, short opt_attrs
,
1945 const char *ptr
, const char **rptr
)
1948 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, opt_attrs
, FALSE
, ptr
, rptr
, error
);
1949 mono_error_cleanup (error
);
1954 mono_metadata_method_has_param_attrs (MonoImage
*m
, int def
)
1956 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1957 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1958 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1960 if (def
< methodt
->rows
)
1961 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1963 lastp
= m
->tables
[MONO_TABLE_PARAM
].rows
+ 1;
1965 for (i
= param_index
; i
< lastp
; ++i
) {
1966 guint32 flags
= mono_metadata_decode_row_col (paramt
, i
- 1, MONO_PARAM_FLAGS
);
1975 * mono_metadata_get_param_attrs:
1977 * @m The image to loader parameter attributes from
1978 * @def method def token (one based)
1979 * @param_count number of params to decode including the return value
1981 * Return the parameter attributes for the method whose MethodDef index is DEF. The
1982 * returned memory needs to be freed by the caller. If all the param attributes are
1983 * 0, then NULL is returned.
1986 mono_metadata_get_param_attrs (MonoImage
*m
, int def
, int param_count
)
1988 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1989 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1990 guint32 cols
[MONO_PARAM_SIZE
];
1991 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1994 if (def
< methodt
->rows
)
1995 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1997 lastp
= paramt
->rows
+ 1;
1999 for (i
= param_index
; i
< lastp
; ++i
) {
2000 mono_metadata_decode_row (paramt
, i
- 1, cols
, MONO_PARAM_SIZE
);
2001 if (cols
[MONO_PARAM_FLAGS
]) {
2003 pattrs
= g_new0 (int, param_count
);
2004 /* at runtime we just ignore this kind of malformed file:
2005 * the verifier can signal the error to the user
2007 if (cols
[MONO_PARAM_SEQUENCE
] >= param_count
)
2009 pattrs
[cols
[MONO_PARAM_SEQUENCE
]] = cols
[MONO_PARAM_FLAGS
];
2018 * mono_metadata_parse_signature:
2019 * \param image metadata context
2020 * \param token metadata token
2022 * Decode a method signature stored in the \c StandAloneSig table
2024 * \returns a \c MonoMethodSignature describing the signature.
2026 MonoMethodSignature
*
2027 mono_metadata_parse_signature (MonoImage
*image
, guint32 token
)
2030 MonoMethodSignature
*ret
;
2031 ret
= mono_metadata_parse_signature_checked (image
, token
, error
);
2032 mono_error_cleanup (error
);
2037 * mono_metadata_parse_signature_checked:
2038 * @image: metadata context
2039 * @token: metadata token
2040 * @error: set on error
2042 * Decode a method signature stored in the STANDALONESIG table
2044 * Returns: a MonoMethodSignature describing the signature. On failure
2045 * returns NULL and sets @error.
2047 MonoMethodSignature
*
2048 mono_metadata_parse_signature_checked (MonoImage
*image
, guint32 token
, MonoError
*error
)
2052 MonoTableInfo
*tables
= image
->tables
;
2053 guint32 idx
= mono_metadata_token_index (token
);
2057 if (image_is_dynamic (image
)) {
2058 return (MonoMethodSignature
*)mono_lookup_dynamic_token (image
, token
, NULL
, error
);
2061 g_assert (mono_metadata_token_table(token
) == MONO_TABLE_STANDALONESIG
);
2063 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
2065 ptr
= mono_metadata_blob_heap (image
, sig
);
2066 mono_metadata_decode_blob_size (ptr
, &ptr
);
2068 return mono_metadata_parse_method_signature_full (image
, NULL
, 0, ptr
, NULL
, error
);
2072 * mono_metadata_signature_alloc:
2073 * \param image metadata context
2074 * \param nparams number of parameters in the signature
2076 * Allocate a \c MonoMethodSignature structure with the specified number of params.
2077 * The return type and the params types need to be filled later.
2078 * This is a Mono runtime internal function.
2080 * LOCKING: Assumes the loader lock is held.
2082 * \returns the new \c MonoMethodSignature structure.
2084 MonoMethodSignature
*
2085 mono_metadata_signature_alloc (MonoImage
*m
, guint32 nparams
)
2087 MonoMethodSignature
*sig
;
2089 sig
= (MonoMethodSignature
*)mono_image_alloc0 (m
, MONO_SIZEOF_METHOD_SIGNATURE
+ ((gint32
)nparams
) * sizeof (MonoType
*));
2090 sig
->param_count
= nparams
;
2091 sig
->sentinelpos
= -1;
2096 static MonoMethodSignature
*
2097 mono_metadata_signature_dup_internal_with_padding (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
, size_t padding
)
2099 int sigsize
, sig_header_size
;
2100 MonoMethodSignature
*ret
;
2101 sigsize
= sig_header_size
= MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*) + padding
;
2103 sigsize
+= mono_sizeof_type (sig
->ret
);
2106 ret
= (MonoMethodSignature
*)mono_image_alloc (image
, sigsize
);
2108 ret
= (MonoMethodSignature
*)mono_mempool_alloc (mp
, sigsize
);
2110 ret
= (MonoMethodSignature
*)g_malloc (sigsize
);
2113 memcpy (ret
, sig
, sig_header_size
- padding
);
2115 // Copy return value because of ownership semantics.
2117 // Danger! Do not alter padding use without changing the dup_add_this below
2118 intptr_t end_of_header
= (intptr_t)( (char*)(ret
) + sig_header_size
);
2119 ret
->ret
= (MonoType
*)end_of_header
;
2120 memcpy (ret
->ret
, sig
->ret
, mono_sizeof_type (sig
->ret
));
2126 static MonoMethodSignature
*
2127 mono_metadata_signature_dup_internal (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
)
2129 return mono_metadata_signature_dup_internal_with_padding (image
, mp
, sig
, 0);
2132 * signature_dup_add_this:
2134 * Make a copy of @sig, adding an explicit this argument.
2136 MonoMethodSignature
*
2137 mono_metadata_signature_dup_add_this (MonoImage
*image
, MonoMethodSignature
*sig
, MonoClass
*klass
)
2139 MonoMethodSignature
*ret
;
2140 ret
= mono_metadata_signature_dup_internal_with_padding (image
, NULL
, sig
, sizeof (MonoType
*));
2142 ret
->param_count
= sig
->param_count
+ 1;
2143 ret
->hasthis
= FALSE
;
2145 for (int i
= sig
->param_count
- 1; i
>= 0; i
--)
2146 ret
->params
[i
+ 1] = sig
->params
[i
];
2147 ret
->params
[0] = m_class_is_valuetype (klass
) ? m_class_get_this_arg (klass
) : m_class_get_byval_arg (klass
);
2149 for (int i
= sig
->param_count
- 1; i
>= 0; i
--)
2150 g_assert(ret
->params
[i
+ 1]->type
== sig
->params
[i
]->type
&& ret
->params
[i
+1]->type
!= MONO_TYPE_END
);
2151 g_assert (ret
->ret
->type
== sig
->ret
->type
&& ret
->ret
->type
!= MONO_TYPE_END
);
2158 MonoMethodSignature
*
2159 mono_metadata_signature_dup_full (MonoImage
*image
, MonoMethodSignature
*sig
)
2161 MonoMethodSignature
*ret
= mono_metadata_signature_dup_internal (image
, NULL
, sig
);
2163 for (int i
= 0 ; i
< sig
->param_count
; i
++)
2164 g_assert(ret
->params
[i
]->type
== sig
->params
[i
]->type
);
2165 g_assert (ret
->ret
->type
== sig
->ret
->type
);
2170 /*The mempool is accessed without synchronization*/
2171 MonoMethodSignature
*
2172 mono_metadata_signature_dup_mempool (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
2174 return mono_metadata_signature_dup_internal (NULL
, mp
, sig
);
2178 * mono_metadata_signature_dup:
2179 * \param sig method signature
2181 * Duplicate an existing \c MonoMethodSignature so it can be modified.
2182 * This is a Mono runtime internal function.
2184 * \returns the new \c MonoMethodSignature structure.
2186 MonoMethodSignature
*
2187 mono_metadata_signature_dup (MonoMethodSignature
*sig
)
2189 return mono_metadata_signature_dup_full (NULL
, sig
);
2193 * mono_metadata_signature_size:
2195 * Return the amount of memory allocated to SIG.
2198 mono_metadata_signature_size (MonoMethodSignature
*sig
)
2200 return MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*);
2204 * mono_metadata_parse_method_signature_full:
2205 * \param m metadata context
2206 * \param generic_container: generics container
2207 * \param def the \c MethodDef index or 0 for \c Ref signatures.
2208 * \param ptr pointer to the signature metadata representation
2209 * \param rptr pointer updated to match the end of the decoded stream
2210 * \param error set on error
2213 * Decode a method signature stored at \p ptr.
2214 * This is a Mono runtime internal function.
2216 * LOCKING: Assumes the loader lock is held.
2218 * \returns a \c MonoMethodSignature describing the signature. On error sets
2219 * \p error and returns \c NULL.
2221 MonoMethodSignature
*
2222 mono_metadata_parse_method_signature_full (MonoImage
*m
, MonoGenericContainer
*container
,
2223 int def
, const char *ptr
, const char **rptr
, MonoError
*error
)
2225 MonoMethodSignature
*method
;
2226 int i
, *pattrs
= NULL
;
2227 guint32 hasthis
= 0, explicit_this
= 0, call_convention
, param_count
;
2228 guint32 gen_param_count
= 0;
2229 gboolean is_open
= FALSE
;
2234 gen_param_count
= 1;
2239 call_convention
= *ptr
& 0x0F;
2241 if (gen_param_count
)
2242 gen_param_count
= mono_metadata_decode_value (ptr
, &ptr
);
2243 param_count
= mono_metadata_decode_value (ptr
, &ptr
);
2246 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 */
2248 method
= mono_metadata_signature_alloc (m
, param_count
);
2249 method
->hasthis
= hasthis
;
2250 method
->explicit_this
= explicit_this
;
2251 method
->call_convention
= call_convention
;
2252 method
->generic_param_count
= gen_param_count
;
2254 if (call_convention
!= 0xa) {
2255 method
->ret
= mono_metadata_parse_type_checked (m
, container
, pattrs
? pattrs
[0] : 0, FALSE
, ptr
, &ptr
, error
);
2257 mono_metadata_free_method_signature (method
);
2261 is_open
= mono_class_is_open_constructed_type (method
->ret
);
2264 for (i
= 0; i
< method
->param_count
; ++i
) {
2265 if (*ptr
== MONO_TYPE_SENTINEL
) {
2266 if (method
->call_convention
!= MONO_CALL_VARARG
|| def
) {
2267 mono_error_set_bad_image (error
, m
, "Found sentinel for methoddef or no vararg");
2271 if (method
->sentinelpos
>= 0) {
2272 mono_error_set_bad_image (error
, m
, "Found sentinel twice in the same signature.");
2276 method
->sentinelpos
= i
;
2279 method
->params
[i
] = mono_metadata_parse_type_checked (m
, container
, pattrs
? pattrs
[i
+1] : 0, FALSE
, ptr
, &ptr
, error
);
2280 if (!method
->params
[i
]) {
2281 mono_metadata_free_method_signature (method
);
2286 is_open
= mono_class_is_open_constructed_type (method
->params
[i
]);
2289 /* The sentinel could be missing if the caller does not pass any additional arguments */
2290 if (!def
&& method
->call_convention
== MONO_CALL_VARARG
&& method
->sentinelpos
< 0)
2291 method
->sentinelpos
= method
->param_count
;
2293 method
->has_type_parameters
= is_open
;
2295 if (def
&& (method
->call_convention
== MONO_CALL_VARARG
))
2296 method
->sentinelpos
= method
->param_count
;
2303 * Add signature to a cache and increase ref count...
2310 * mono_metadata_parse_method_signature:
2311 * \param m metadata context
2312 * \param def the \c MethodDef index or 0 for \c Ref signatures.
2313 * \param ptr pointer to the signature metadata representation
2314 * \param rptr pointer updated to match the end of the decoded stream
2316 * Decode a method signature stored at \p ptr.
2317 * This is a Mono runtime internal function.
2319 * LOCKING: Assumes the loader lock is held.
2321 * \returns a \c MonoMethodSignature describing the signature.
2323 MonoMethodSignature
*
2324 mono_metadata_parse_method_signature (MonoImage
*m
, int def
, const char *ptr
, const char **rptr
)
2327 * This function MUST NOT be called by runtime code as it does error handling incorrectly.
2328 * Use mono_metadata_parse_method_signature_full instead.
2329 * It's ok to asser on failure as we no longer use it.
2332 MonoMethodSignature
*ret
;
2333 ret
= mono_metadata_parse_method_signature_full (m
, NULL
, def
, ptr
, rptr
, error
);
2334 mono_error_assert_ok (error
);
2340 * mono_metadata_free_method_signature:
2341 * \param sig signature to destroy
2343 * Free the memory allocated in the signature \p sig.
2344 * This method needs to be robust and work also on partially-built
2345 * signatures, so it does extra checks.
2348 mono_metadata_free_method_signature (MonoMethodSignature
*sig
)
2350 /* Everything is allocated from mempools */
2354 mono_metadata_free_type (sig->ret);
2355 for (i = 0; i < sig->param_count; ++i) {
2356 if (sig->params [i])
2357 mono_metadata_free_type (sig->params [i]);
2363 mono_metadata_free_inflated_signature (MonoMethodSignature
*sig
)
2367 /* Allocated in inflate_generic_signature () */
2369 mono_metadata_free_type (sig
->ret
);
2370 for (i
= 0; i
< sig
->param_count
; ++i
) {
2371 if (sig
->params
[i
])
2372 mono_metadata_free_type (sig
->params
[i
]);
2378 inflated_method_equal (gconstpointer a
, gconstpointer b
)
2380 const MonoMethodInflated
*ma
= (const MonoMethodInflated
*)a
;
2381 const MonoMethodInflated
*mb
= (const MonoMethodInflated
*)b
;
2382 if (ma
->declaring
!= mb
->declaring
)
2384 return mono_metadata_generic_context_equal (&ma
->context
, &mb
->context
);
2388 inflated_method_hash (gconstpointer a
)
2390 const MonoMethodInflated
*ma
= (const MonoMethodInflated
*)a
;
2391 return (mono_metadata_generic_context_hash (&ma
->context
) ^ mono_aligned_addr_hash (ma
->declaring
));
2395 inflated_signature_equal (gconstpointer a
, gconstpointer b
)
2397 const MonoInflatedMethodSignature
*sig1
= (const MonoInflatedMethodSignature
*)a
;
2398 const MonoInflatedMethodSignature
*sig2
= (const MonoInflatedMethodSignature
*)b
;
2400 /* sig->sig is assumed to be canonized */
2401 if (sig1
->sig
!= sig2
->sig
)
2403 /* The generic instances are canonized */
2404 return mono_metadata_generic_context_equal (&sig1
->context
, &sig2
->context
);
2408 inflated_signature_hash (gconstpointer a
)
2410 const MonoInflatedMethodSignature
*sig
= (const MonoInflatedMethodSignature
*)a
;
2412 /* sig->sig is assumed to be canonized */
2413 return mono_metadata_generic_context_hash (&sig
->context
) ^ mono_aligned_addr_hash (sig
->sig
);
2417 dump_ginst (MonoGenericInst *ginst)
2422 g_print ("Ginst: <");
2423 for (i = 0; i < ginst->type_argc; ++i) {
2426 name = mono_type_get_name (ginst->type_argv [i]);
2427 g_print ("%s", name);
2433 static gboolean
type_in_image (MonoType
*type
, MonoImage
*image
);
2436 signature_in_image (MonoMethodSignature
*sig
, MonoImage
*image
)
2438 gpointer iter
= NULL
;
2441 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2442 if (type_in_image (p
, image
))
2445 return type_in_image (mono_signature_get_return_type (sig
), image
);
2449 ginst_in_image (MonoGenericInst
*ginst
, MonoImage
*image
)
2453 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2454 if (type_in_image (ginst
->type_argv
[i
], image
))
2462 gclass_in_image (MonoGenericClass
*gclass
, MonoImage
*image
)
2464 return m_class_get_image (gclass
->container_class
) == image
||
2465 ginst_in_image (gclass
->context
.class_inst
, image
);
2469 type_in_image (MonoType
*type
, MonoImage
*image
)
2472 switch (type
->type
) {
2473 case MONO_TYPE_GENERICINST
:
2474 return gclass_in_image (type
->data
.generic_class
, image
);
2476 type
= type
->data
.type
;
2478 case MONO_TYPE_SZARRAY
:
2479 type
= m_class_get_byval_arg (type
->data
.klass
);
2481 case MONO_TYPE_ARRAY
:
2482 type
= m_class_get_byval_arg (type
->data
.array
->eklass
);
2484 case MONO_TYPE_FNPTR
:
2485 return signature_in_image (type
->data
.method
, image
);
2487 case MONO_TYPE_MVAR
:
2488 return image
== mono_get_image_for_generic_param (type
->data
.generic_param
);
2490 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type_internal () */
2491 return image
== m_class_get_image (mono_class_from_mono_type_internal (type
));
2496 mono_type_in_image (MonoType
*type
, MonoImage
*image
)
2498 return type_in_image (type
, image
);
2502 image_sets_lock (void)
2504 mono_os_mutex_lock (&image_sets_mutex
);
2508 image_sets_unlock (void)
2510 mono_os_mutex_unlock (&image_sets_mutex
);
2514 compare_pointers (const void *a
, const void *b
)
2516 return (size_t)a
- (size_t)b
;
2520 #define HASH_TABLE_SIZE 1103
2521 static MonoImageSet
*img_set_cache
[HASH_TABLE_SIZE
];
2524 mix_hash (uintptr_t source
)
2526 unsigned int hash
= source
;
2529 hash
= (((hash
* 215497) >> 16) ^ ((hash
* 1823231) + hash
));
2531 // Mix in highest bits on 64-bit systems only
2532 if (sizeof (source
) > 4)
2533 hash
= hash
^ (source
>> 32);
2539 hash_images (MonoImage
**images
, int nimages
)
2543 for (i
= 0; i
< nimages
; ++i
)
2544 res
+= mix_hash ((size_t)images
[i
]);
2550 compare_img_set (MonoImageSet
*set
, MonoImage
**images
, int nimages
)
2554 if (set
->nimages
!= nimages
)
2557 for (j
= 0; j
< nimages
; ++j
) {
2558 for (k
= 0; k
< nimages
; ++k
)
2559 if (set
->images
[k
] == images
[j
])
2560 break; // Break on match
2562 // If we iterated all the way through set->images, images[j] was *not* found.
2564 break; // Break on "image not found"
2567 // If we iterated all the way through images without breaking, all items in images were found in set->images
2568 return j
== nimages
;
2572 static MonoImageSet
*
2573 img_set_cache_get (MonoImage
**images
, int nimages
)
2575 guint32 hash_code
= hash_images (images
, nimages
);
2576 int index
= hash_code
% HASH_TABLE_SIZE
;
2577 MonoImageSet
*img
= img_set_cache
[index
];
2578 if (!img
|| !compare_img_set (img
, images
, nimages
)) {
2579 UnlockedIncrement (&img_set_cache_miss
);
2582 UnlockedIncrement (&img_set_cache_hit
);
2587 img_set_cache_add (MonoImageSet
*set
)
2589 guint32 hash_code
= hash_images (set
->images
, set
->nimages
);
2590 int index
= hash_code
% HASH_TABLE_SIZE
;
2591 img_set_cache
[index
] = set
;
2595 img_set_cache_remove (MonoImageSet
*is
)
2597 guint32 hash_code
= hash_images (is
->images
, is
->nimages
);
2598 int index
= hash_code
% HASH_TABLE_SIZE
;
2599 if (img_set_cache
[index
] == is
)
2600 img_set_cache
[index
] = NULL
;
2605 * Return a MonoImageSet representing the set of images in IMAGES.
2607 static MonoImageSet
*
2608 get_image_set (MonoImage
**images
, int nimages
)
2614 /* Common case: Image set contains corlib only. If we've seen that case before, we cached the set. */
2615 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
&& mscorlib_image_set
)
2616 return mscorlib_image_set
;
2618 /* Happens with empty generic instances */
2619 // 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.
2621 return mscorlib_image_set
;
2623 set
= img_set_cache_get (images
, nimages
);
2630 image_sets
= g_ptr_array_new ();
2632 // Before we go on, we should check to see whether a MonoImageSet with these images already exists.
2633 // We can search the referred-by imagesets of any one of our images to do this. Arbitrarily pick one here:
2634 if (images
[0] == mono_defaults
.corlib
&& nimages
> 1)
2635 l
= images
[1]->image_sets
; // Prefer not to search the imagesets of corlib-- that will be a long list.
2637 l
= images
[0]->image_sets
;
2640 while (l
) // Iterate over selected list, looking for an imageset with members equal to our target one
2642 set
= (MonoImageSet
*)l
->data
;
2644 if (set
->nimages
== nimages
) { // Member count differs, this can't be it
2645 // Compare all members to all members-- order might be different
2646 for (j
= 0; j
< nimages
; ++j
) {
2647 for (k
= 0; k
< nimages
; ++k
)
2648 if (set
->images
[k
] == images
[j
])
2649 break; // Break on match
2651 // If we iterated all the way through set->images, images[j] was *not* found.
2653 break; // Break on "image not found"
2656 // If we iterated all the way through images without breaking, all items in images were found in set->images
2658 // Break on "found a set with equal members".
2659 // This happens in case of a hash collision with a previously cached set.
2667 // If we iterated all the way through l without breaking, the imageset does not already exist and we should create it
2669 set
= g_new0 (MonoImageSet
, 1);
2670 set
->nimages
= nimages
;
2671 set
->images
= g_new0 (MonoImage
*, nimages
);
2672 mono_os_mutex_init_recursive (&set
->lock
);
2673 for (i
= 0; i
< nimages
; ++i
)
2674 set
->images
[i
] = images
[i
];
2675 set
->gclass_cache
= mono_conc_hashtable_new_full (mono_generic_class_hash
, mono_generic_class_equal
, NULL
, (GDestroyNotify
)free_generic_class
);
2676 set
->ginst_cache
= g_hash_table_new_full (mono_metadata_generic_inst_hash
, mono_metadata_generic_inst_equal
, NULL
, (GDestroyNotify
)free_generic_inst
);
2677 set
->gmethod_cache
= g_hash_table_new_full (inflated_method_hash
, inflated_method_equal
, NULL
, (GDestroyNotify
)free_inflated_method
);
2678 set
->gsignature_cache
= g_hash_table_new_full (inflated_signature_hash
, inflated_signature_equal
, NULL
, (GDestroyNotify
)free_inflated_signature
);
2680 set
->szarray_cache
= g_hash_table_new_full (mono_aligned_addr_hash
, NULL
, NULL
, NULL
);
2681 set
->array_cache
= g_hash_table_new_full (mono_aligned_addr_hash
, NULL
, NULL
, NULL
);
2683 for (i
= 0; i
< nimages
; ++i
)
2684 set
->images
[i
]->image_sets
= g_slist_prepend (set
->images
[i
]->image_sets
, set
);
2686 g_ptr_array_add (image_sets
, set
);
2687 UnlockedIncrement (&img_set_count
); /* locked by image_sets_lock () */
2690 /* Cache the set. If there was a cache collision, the previously cached value will be replaced. */
2691 img_set_cache_add (set
);
2693 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
) {
2694 mono_memory_barrier ();
2695 mscorlib_image_set
= set
;
2698 image_sets_unlock ();
2704 delete_image_set (MonoImageSet
*set
)
2708 mono_conc_hashtable_destroy (set
->gclass_cache
);
2709 g_hash_table_destroy (set
->ginst_cache
);
2710 g_hash_table_destroy (set
->gmethod_cache
);
2711 g_hash_table_destroy (set
->gsignature_cache
);
2713 g_hash_table_destroy (set
->szarray_cache
);
2714 g_hash_table_destroy (set
->array_cache
);
2716 g_hash_table_destroy (set
->ptr_cache
);
2718 mono_wrapper_caches_free (&set
->wrapper_caches
);
2722 for (i
= 0; i
< set
->nimages
; ++i
)
2723 set
->images
[i
]->image_sets
= g_slist_remove (set
->images
[i
]->image_sets
, set
);
2725 g_ptr_array_remove (image_sets
, set
);
2727 image_sets_unlock ();
2729 img_set_cache_remove (set
);
2732 mono_mempool_destroy (set
->mempool
);
2733 g_free (set
->images
);
2734 mono_os_mutex_destroy (&set
->lock
);
2739 mono_image_set_lock (MonoImageSet
*set
)
2741 mono_os_mutex_lock (&set
->lock
);
2745 mono_image_set_unlock (MonoImageSet
*set
)
2747 mono_os_mutex_unlock (&set
->lock
);
2751 mono_image_set_alloc (MonoImageSet
*set
, guint size
)
2755 mono_image_set_lock (set
);
2757 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2758 res
= mono_mempool_alloc (set
->mempool
, size
);
2759 mono_image_set_unlock (set
);
2765 mono_image_set_alloc0 (MonoImageSet
*set
, guint size
)
2769 mono_image_set_lock (set
);
2771 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2772 res
= mono_mempool_alloc0 (set
->mempool
, size
);
2773 mono_image_set_unlock (set
);
2779 mono_image_set_strdup (MonoImageSet
*set
, const char *s
)
2783 mono_image_set_lock (set
);
2785 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2786 res
= mono_mempool_strdup (set
->mempool
, s
);
2787 mono_image_set_unlock (set
);
2792 // Get a descriptive string for a MonoImageSet
2793 // Callers are obligated to free buffer with g_free after use
2795 mono_image_set_description (MonoImageSet
*set
)
2797 GString
*result
= g_string_new (NULL
);
2799 g_string_append (result
, "[");
2800 for (img
= 0; img
< set
->nimages
; img
++)
2803 g_string_append (result
, ", ");
2804 g_string_append (result
, set
->images
[img
]->name
);
2806 g_string_append (result
, "]");
2807 return g_string_free (result
, FALSE
);
2811 * Structure used by the collect_..._images functions to store the image list.
2814 MonoImage
*image_buf
[64];
2816 int nimages
, images_len
;
2820 collect_data_init (CollectData
*data
)
2822 data
->images
= data
->image_buf
;
2823 data
->images_len
= 64;
2828 collect_data_free (CollectData
*data
)
2830 if (data
->images
!= data
->image_buf
)
2831 g_free (data
->images
);
2835 enlarge_data (CollectData
*data
)
2837 int new_len
= data
->images_len
< 16 ? 16 : data
->images_len
* 2;
2838 MonoImage
**d
= g_new (MonoImage
*, new_len
);
2841 g_assert_not_reached ();
2842 memcpy (d
, data
->images
, data
->images_len
);
2843 if (data
->images
!= data
->image_buf
)
2844 g_free (data
->images
);
2846 data
->images_len
= new_len
;
2850 add_image (MonoImage
*image
, CollectData
*data
)
2854 /* The arrays are small, so use a linear search instead of a hash table */
2855 for (i
= 0; i
< data
->nimages
; ++i
)
2856 if (data
->images
[i
] == image
)
2859 if (data
->nimages
== data
->images_len
)
2860 enlarge_data (data
);
2862 data
->images
[data
->nimages
++] = image
;
2866 collect_type_images (MonoType
*type
, CollectData
*data
);
2869 collect_ginst_images (MonoGenericInst
*ginst
, CollectData
*data
)
2873 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2874 collect_type_images (ginst
->type_argv
[i
], data
);
2879 collect_gclass_images (MonoGenericClass
*gclass
, CollectData
*data
)
2881 add_image (m_class_get_image (gclass
->container_class
), data
);
2882 if (gclass
->context
.class_inst
)
2883 collect_ginst_images (gclass
->context
.class_inst
, data
);
2887 collect_signature_images (MonoMethodSignature
*sig
, CollectData
*data
)
2889 gpointer iter
= NULL
;
2892 collect_type_images (mono_signature_get_return_type (sig
), data
);
2893 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2894 collect_type_images (p
, data
);
2898 collect_inflated_signature_images (MonoInflatedMethodSignature
*sig
, CollectData
*data
)
2900 collect_signature_images (sig
->sig
, data
);
2901 if (sig
->context
.class_inst
)
2902 collect_ginst_images (sig
->context
.class_inst
, data
);
2903 if (sig
->context
.method_inst
)
2904 collect_ginst_images (sig
->context
.method_inst
, data
);
2908 collect_method_images (MonoMethodInflated
*method
, CollectData
*data
)
2910 MonoMethod
*m
= method
->declaring
;
2912 add_image (m_class_get_image (method
->declaring
->klass
), data
);
2913 if (method
->context
.class_inst
)
2914 collect_ginst_images (method
->context
.class_inst
, data
);
2915 if (method
->context
.method_inst
)
2916 collect_ginst_images (method
->context
.method_inst
, data
);
2918 * Dynamic assemblies have no references, so the images they depend on can be unloaded before them.
2920 if (image_is_dynamic (m_class_get_image (m
->klass
)))
2921 collect_signature_images (mono_method_signature_internal (m
), data
);
2925 collect_type_images (MonoType
*type
, CollectData
*data
)
2928 switch (type
->type
) {
2929 case MONO_TYPE_GENERICINST
:
2930 collect_gclass_images (type
->data
.generic_class
, data
);
2933 type
= type
->data
.type
;
2935 case MONO_TYPE_SZARRAY
:
2936 type
= m_class_get_byval_arg (type
->data
.klass
);
2938 case MONO_TYPE_ARRAY
:
2939 type
= m_class_get_byval_arg (type
->data
.array
->eklass
);
2941 case MONO_TYPE_FNPTR
:
2942 //return signature_in_image (type->data.method, image);
2943 g_assert_not_reached ();
2945 case MONO_TYPE_MVAR
:
2947 MonoImage
*image
= mono_get_image_for_generic_param (type
->data
.generic_param
);
2948 add_image (image
, data
);
2951 case MONO_TYPE_CLASS
:
2952 case MONO_TYPE_VALUETYPE
:
2953 add_image (m_class_get_image (mono_class_from_mono_type_internal (type
)), data
);
2956 add_image (mono_defaults
.corlib
, data
);
2963 } CleanForImageUserData
;
2966 steal_gclass_in_image (gpointer key
, gpointer value
, gpointer data
)
2968 MonoGenericClass
*gclass
= (MonoGenericClass
*)key
;
2969 CleanForImageUserData
*user_data
= (CleanForImageUserData
*)data
;
2971 g_assert (gclass_in_image (gclass
, user_data
->image
));
2973 user_data
->list
= g_slist_prepend (user_data
->list
, gclass
);
2978 steal_ginst_in_image (gpointer key
, gpointer value
, gpointer data
)
2980 MonoGenericInst
*ginst
= (MonoGenericInst
*)key
;
2981 CleanForImageUserData
*user_data
= (CleanForImageUserData
*)data
;
2983 // This doesn't work during corlib compilation
2984 //g_assert (ginst_in_image (ginst, user_data->image));
2986 user_data
->list
= g_slist_prepend (user_data
->list
, ginst
);
2991 inflated_method_in_image (gpointer key
, gpointer value
, gpointer data
)
2993 MonoImage
*image
= (MonoImage
*)data
;
2994 MonoMethodInflated
*method
= (MonoMethodInflated
*)key
;
2997 // https://bugzilla.novell.com/show_bug.cgi?id=458168
2998 g_assert (m_class_get_image (method
->declaring
->klass
) == image
||
2999 (method
->context
.class_inst
&& ginst_in_image (method
->context
.class_inst
, image
)) ||
3000 (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
)));
3006 inflated_signature_in_image (gpointer key
, gpointer value
, gpointer data
)
3008 MonoImage
*image
= (MonoImage
*)data
;
3009 MonoInflatedMethodSignature
*sig
= (MonoInflatedMethodSignature
*)key
;
3011 return signature_in_image (sig
->sig
, image
) ||
3012 (sig
->context
.class_inst
&& ginst_in_image (sig
->context
.class_inst
, image
)) ||
3013 (sig
->context
.method_inst
&& ginst_in_image (sig
->context
.method_inst
, image
));
3017 class_in_image (gpointer key
, gpointer value
, gpointer data
)
3019 MonoImage
*image
= (MonoImage
*)data
;
3020 MonoClass
*klass
= (MonoClass
*)key
;
3022 g_assert (type_in_image (m_class_get_byval_arg (klass
), image
));
3028 check_gmethod (gpointer key
, gpointer value
, gpointer data
)
3030 MonoMethodInflated
*method
= (MonoMethodInflated
*)key
;
3031 MonoImage
*image
= (MonoImage
*)data
;
3033 if (method
->context
.class_inst
)
3034 g_assert (!ginst_in_image (method
->context
.class_inst
, image
));
3035 if (method
->context
.method_inst
)
3036 g_assert (!ginst_in_image (method
->context
.method_inst
, image
));
3037 if (((MonoMethod
*)method
)->signature
)
3038 g_assert (!signature_in_image (mono_method_signature_internal ((MonoMethod
*)method
), image
));
3044 * Run a consistency check on the image set data structures.
3046 static G_GNUC_UNUSED
void
3047 check_image_sets (MonoImage
*image
)
3050 GSList
*l
= image
->image_sets
;
3055 for (i
= 0; i
< image_sets
->len
; ++i
) {
3056 MonoImageSet
*set
= (MonoImageSet
*)g_ptr_array_index (image_sets
, i
);
3058 if (!g_slist_find (l
, set
)) {
3059 g_hash_table_foreach (set
->gmethod_cache
, check_gmethod
, image
);
3065 mono_metadata_clean_for_image (MonoImage
*image
)
3067 CleanForImageUserData ginst_data
, gclass_data
;
3068 GSList
*l
, *set_list
;
3070 //check_image_sets (image);
3073 * The data structures could reference each other so we delete them in two phases.
3074 * This is required because of the hashing functions in gclass/ginst_cache.
3076 ginst_data
.image
= gclass_data
.image
= image
;
3077 ginst_data
.list
= gclass_data
.list
= NULL
;
3079 /* Collect the items to delete */
3080 /* delete_image_set () modifies the lists so make a copy */
3081 for (l
= image
->image_sets
; l
; l
= l
->next
) {
3082 MonoImageSet
*set
= (MonoImageSet
*)l
->data
;
3084 mono_image_set_lock (set
);
3085 mono_conc_hashtable_foreach_steal (set
->gclass_cache
, steal_gclass_in_image
, &gclass_data
);
3086 g_hash_table_foreach_steal (set
->ginst_cache
, steal_ginst_in_image
, &ginst_data
);
3087 g_hash_table_foreach_remove (set
->gmethod_cache
, inflated_method_in_image
, image
);
3088 g_hash_table_foreach_remove (set
->gsignature_cache
, inflated_signature_in_image
, image
);
3090 g_hash_table_foreach_steal (set
->szarray_cache
, class_in_image
, image
);
3091 g_hash_table_foreach_steal (set
->array_cache
, class_in_image
, image
);
3093 g_hash_table_foreach_steal (set
->ptr_cache
, class_in_image
, image
);
3094 mono_image_set_unlock (set
);
3097 /* Delete the removed items */
3098 for (l
= ginst_data
.list
; l
; l
= l
->next
)
3099 free_generic_inst ((MonoGenericInst
*)l
->data
);
3100 for (l
= gclass_data
.list
; l
; l
= l
->next
)
3101 free_generic_class ((MonoGenericClass
*)l
->data
);
3102 g_slist_free (ginst_data
.list
);
3103 g_slist_free (gclass_data
.list
);
3104 /* delete_image_set () modifies the lists so make a copy */
3105 set_list
= g_slist_copy (image
->image_sets
);
3106 for (l
= set_list
; l
; l
= l
->next
) {
3107 MonoImageSet
*set
= (MonoImageSet
*)l
->data
;
3109 delete_image_set (set
);
3111 g_slist_free (set_list
);
3115 free_inflated_method (MonoMethodInflated
*imethod
)
3117 MonoMethod
*method
= (MonoMethod
*)imethod
;
3119 if (method
->signature
)
3120 mono_metadata_free_inflated_signature (method
->signature
);
3122 if (method
->wrapper_type
)
3123 g_free (((MonoMethodWrapper
*)method
)->method_data
);
3129 free_generic_inst (MonoGenericInst
*ginst
)
3133 /* The ginst itself is allocated from the image set mempool */
3134 for (i
= 0; i
< ginst
->type_argc
; ++i
)
3135 mono_metadata_free_type (ginst
->type_argv
[i
]);
3139 free_generic_class (MonoGenericClass
*gclass
)
3141 /* The gclass itself is allocated from the image set mempool */
3142 if (gclass
->cached_class
&& m_class_get_interface_id (gclass
->cached_class
))
3143 mono_unload_interface_id (gclass
->cached_class
);
3147 free_inflated_signature (MonoInflatedMethodSignature
*sig
)
3149 mono_metadata_free_inflated_signature (sig
->sig
);
3154 * mono_metadata_get_inflated_signature:
3156 * Given an inflated signature and a generic context, return a canonical copy of the
3157 * signature. The returned signature might be equal to SIG or it might be a cached copy.
3159 MonoMethodSignature
*
3160 mono_metadata_get_inflated_signature (MonoMethodSignature
*sig
, MonoGenericContext
*context
)
3162 MonoInflatedMethodSignature helper
;
3163 MonoInflatedMethodSignature
*res
;
3168 helper
.context
.class_inst
= context
->class_inst
;
3169 helper
.context
.method_inst
= context
->method_inst
;
3171 collect_data_init (&data
);
3173 collect_inflated_signature_images (&helper
, &data
);
3175 set
= get_image_set (data
.images
, data
.nimages
);
3177 collect_data_free (&data
);
3179 mono_image_set_lock (set
);
3181 res
= (MonoInflatedMethodSignature
*)g_hash_table_lookup (set
->gsignature_cache
, &helper
);
3183 res
= g_new0 (MonoInflatedMethodSignature
, 1);
3185 res
->context
.class_inst
= context
->class_inst
;
3186 res
->context
.method_inst
= context
->method_inst
;
3187 g_hash_table_insert (set
->gsignature_cache
, res
, res
);
3190 mono_image_set_unlock (set
);
3196 mono_metadata_get_image_set_for_class (MonoClass
*klass
)
3199 CollectData image_set_data
;
3201 collect_data_init (&image_set_data
);
3202 collect_type_images (m_class_get_byval_arg (klass
), &image_set_data
);
3203 set
= get_image_set (image_set_data
.images
, image_set_data
.nimages
);
3204 collect_data_free (&image_set_data
);
3210 mono_metadata_get_image_set_for_method (MonoMethodInflated
*method
)
3213 CollectData image_set_data
;
3215 collect_data_init (&image_set_data
);
3216 collect_method_images (method
, &image_set_data
);
3217 set
= get_image_set (image_set_data
.images
, image_set_data
.nimages
);
3218 collect_data_free (&image_set_data
);
3224 type_is_gtd (MonoType
*type
)
3226 switch (type
->type
) {
3227 case MONO_TYPE_CLASS
:
3228 case MONO_TYPE_VALUETYPE
:
3229 return mono_class_is_gtd (type
->data
.klass
);
3236 * mono_metadata_get_generic_inst:
3238 * Given a list of types, return a MonoGenericInst that represents that list.
3239 * The returned MonoGenericInst has its own copy of the list of types. The list
3240 * passed in the argument can be freed, modified or disposed of.
3244 mono_metadata_get_generic_inst (int type_argc
, MonoType
**type_argv
)
3246 MonoGenericInst
*ginst
;
3249 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
3251 for (i
= 0; i
< type_argc
; ++i
)
3252 if (mono_class_is_open_constructed_type (type_argv
[i
]))
3254 is_open
= (i
< type_argc
);
3256 ginst
= (MonoGenericInst
*)g_alloca (size
);
3257 memset (ginst
, 0, sizeof (MonoGenericInst
));
3258 ginst
->is_open
= is_open
;
3259 ginst
->type_argc
= type_argc
;
3260 memcpy (ginst
->type_argv
, type_argv
, type_argc
* sizeof (MonoType
*));
3262 for (i
= 0; i
< type_argc
; ++i
) {
3263 MonoType
*t
= ginst
->type_argv
[i
];
3264 if (type_is_gtd (t
)) {
3265 ginst
->type_argv
[i
] = mono_class_gtd_get_canonical_inst (t
->data
.klass
);
3269 return mono_metadata_get_canonical_generic_inst (ginst
);
3274 * mono_metadata_get_canonical_generic_inst:
3275 * \param candidate an arbitrary generic instantiation
3277 * \returns the canonical generic instantiation that represents the given
3278 * candidate by identifying the image set for the candidate instantiation and
3279 * finding the instance in the image set or adding a copy of the given instance
3282 * The returned MonoGenericInst has its own copy of the list of types. The list
3283 * passed in the argument can be freed, modified or disposed of.
3287 mono_metadata_get_canonical_generic_inst (MonoGenericInst
*candidate
)
3290 int type_argc
= candidate
->type_argc
;
3291 gboolean is_open
= candidate
->is_open
;
3294 collect_data_init (&data
);
3296 collect_ginst_images (candidate
, &data
);
3298 set
= get_image_set (data
.images
, data
.nimages
);
3300 collect_data_free (&data
);
3302 mono_image_set_lock (set
);
3304 MonoGenericInst
*ginst
= (MonoGenericInst
*)g_hash_table_lookup (set
->ginst_cache
, candidate
);
3306 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
3307 ginst
= (MonoGenericInst
*)mono_image_set_alloc0 (set
, size
);
3308 #ifndef MONO_SMALL_CONFIG
3309 ginst
->id
= mono_atomic_inc_i32 (&next_generic_inst_id
);
3311 ginst
->is_open
= is_open
;
3312 ginst
->type_argc
= type_argc
;
3314 for (int i
= 0; i
< type_argc
; ++i
)
3315 ginst
->type_argv
[i
] = mono_metadata_type_dup (NULL
, candidate
->type_argv
[i
]);
3317 g_hash_table_insert (set
->ginst_cache
, ginst
, ginst
);
3320 mono_image_set_unlock (set
);
3325 mono_metadata_is_type_builder_generic_type_definition (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
3327 MonoGenericContainer
*container
= mono_class_get_generic_container (container_class
);
3329 if (!is_dynamic
|| m_class_was_typebuilder (container_class
) || container
->type_argc
!= inst
->type_argc
)
3331 return inst
== container
->context
.class_inst
;
3335 * mono_metadata_lookup_generic_class:
3337 * Returns a MonoGenericClass with the given properties.
3341 mono_metadata_lookup_generic_class (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
3343 MonoGenericClass
*gclass
;
3344 MonoGenericClass helper
;
3345 gboolean is_tb_open
= mono_metadata_is_type_builder_generic_type_definition (container_class
, inst
, is_dynamic
);
3349 g_assert (mono_class_get_generic_container (container_class
)->type_argc
== inst
->type_argc
);
3351 memset (&helper
, 0, sizeof(helper
)); // act like g_new0
3352 helper
.container_class
= container_class
;
3353 helper
.context
.class_inst
= inst
;
3354 helper
.is_dynamic
= is_dynamic
; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
3355 helper
.is_tb_open
= is_tb_open
;
3357 collect_data_init (&data
);
3359 collect_gclass_images (&helper
, &data
);
3361 set
= get_image_set (data
.images
, data
.nimages
);
3363 collect_data_free (&data
);
3365 gclass
= (MonoGenericClass
*)mono_conc_hashtable_lookup (set
->gclass_cache
, &helper
);
3367 /* A tripwire just to keep us honest */
3368 g_assert (!helper
.cached_class
);
3373 gclass
= mono_image_set_new0 (set
, MonoGenericClass
, 1);
3375 gclass
->is_dynamic
= 1;
3377 gclass
->is_tb_open
= is_tb_open
;
3378 gclass
->container_class
= container_class
;
3379 gclass
->context
.class_inst
= inst
;
3380 gclass
->context
.method_inst
= NULL
;
3381 gclass
->owner
= set
;
3382 if (inst
== mono_class_get_generic_container (container_class
)->context
.class_inst
&& !is_tb_open
)
3383 gclass
->cached_class
= container_class
;
3385 mono_image_set_lock (set
);
3387 MonoGenericClass
*gclass2
= (MonoGenericClass
*)mono_conc_hashtable_insert (set
->gclass_cache
, gclass
, gclass
);
3391 // g_hash_table_insert (set->gclass_cache, gclass, gclass);
3393 mono_image_set_unlock (set
);
3399 * mono_metadata_inflate_generic_inst:
3401 * Instantiate the generic instance @ginst with the context @context.
3402 * Check @error for success.
3406 mono_metadata_inflate_generic_inst (MonoGenericInst
*ginst
, MonoGenericContext
*context
, MonoError
*error
)
3408 MonoType
**type_argv
;
3409 MonoGenericInst
*nginst
= NULL
;
3414 if (!ginst
->is_open
)
3417 type_argv
= g_new0 (MonoType
*, ginst
->type_argc
);
3419 for (i
= 0; i
< ginst
->type_argc
; i
++) {
3420 type_argv
[i
] = mono_class_inflate_generic_type_checked (ginst
->type_argv
[i
], context
, error
);
3421 if (!mono_error_ok (error
))
3426 nginst
= mono_metadata_get_generic_inst (ginst
->type_argc
, type_argv
);
3429 for (i
= 0; i
< count
; i
++)
3430 mono_metadata_free_type (type_argv
[i
]);
3437 mono_metadata_parse_generic_inst (MonoImage
*m
, MonoGenericContainer
*container
,
3438 int count
, const char *ptr
, const char **rptr
, MonoError
*error
)
3440 MonoType
**type_argv
;
3441 MonoGenericInst
*ginst
= NULL
;
3442 int i
, parse_count
= 0;
3445 type_argv
= g_new0 (MonoType
*, count
);
3447 for (i
= 0; i
< count
; i
++) {
3448 /* this can be a transient type, mono_metadata_get_generic_inst will allocate
3449 * a canonical one, if needed.
3451 MonoType
*t
= mono_metadata_parse_type_checked (m
, container
, 0, TRUE
, ptr
, &ptr
, error
);
3461 g_assert (parse_count
== count
);
3462 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
3465 for (i
= 0; i
< parse_count
; i
++)
3466 mono_metadata_free_type (type_argv
[i
]);
3473 do_mono_metadata_parse_generic_class (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
3474 const char *ptr
, const char **rptr
, MonoError
*error
)
3476 MonoGenericInst
*inst
;
3483 // XXX how about transient?
3484 gtype
= mono_metadata_parse_type_checked (m
, NULL
, 0, FALSE
, ptr
, &ptr
, error
);
3488 gklass
= mono_class_from_mono_type_internal (gtype
);
3489 if (!mono_class_is_gtd (gklass
)) {
3490 mono_error_set_bad_image (error
, m
, "Generic instance with non-generic definition");
3494 count
= mono_metadata_decode_value (ptr
, &ptr
);
3495 inst
= mono_metadata_parse_generic_inst (m
, container
, count
, ptr
, &ptr
, error
);
3502 type
->data
.generic_class
= mono_metadata_lookup_generic_class (gklass
, inst
, FALSE
);
3508 * @gc: The generic container to normalize
3509 * @type: The kind of generic parameters the resulting generic-container should contain
3512 static MonoGenericContainer
*
3513 select_container (MonoGenericContainer
*gc
, MonoTypeEnum type
)
3515 gboolean is_var
= (type
== MONO_TYPE_VAR
);
3519 g_assert (is_var
|| type
== MONO_TYPE_MVAR
);
3522 if (gc
->is_method
|| gc
->parent
)
3524 * The current MonoGenericContainer is a generic method -> its `parent'
3525 * points to the containing class'es container.
3533 MonoGenericContainer
*
3534 mono_get_anonymous_container_for_image (MonoImage
*image
, gboolean is_mvar
)
3536 MonoGenericContainer
**container_pointer
;
3538 container_pointer
= &image
->anonymous_generic_method_container
;
3540 container_pointer
= &image
->anonymous_generic_class_container
;
3541 MonoGenericContainer
*result
= *container_pointer
;
3543 // This container has never been created; make it now.
3546 // Note this is never deallocated anywhere-- it exists for the lifetime of the image it's allocated from
3547 result
= (MonoGenericContainer
*)mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
3548 result
->owner
.image
= image
;
3549 result
->is_anonymous
= TRUE
;
3550 result
->is_method
= is_mvar
;
3552 // If another thread already made a container, use that and leak this new one.
3553 // (Technically it would currently be safe to just assign instead of CASing.)
3554 MonoGenericContainer
*exchange
= (MonoGenericContainer
*)mono_atomic_cas_ptr ((volatile gpointer
*)container_pointer
, result
, NULL
);
3561 #define FAST_GPARAM_CACHE_SIZE 16
3563 static MonoGenericParam
*
3564 lookup_anon_gparam (MonoImage
*image
, MonoGenericContainer
*container
, gint32 param_num
, gboolean is_mvar
)
3566 if (param_num
>= 0 && param_num
< FAST_GPARAM_CACHE_SIZE
) {
3567 MonoGenericParam
*cache
= is_mvar
? image
->mvar_gparam_cache_fast
: image
->var_gparam_cache_fast
;
3570 return &cache
[param_num
];
3572 MonoGenericParam key
;
3573 memset (&key
, 0, sizeof (key
));
3574 key
.owner
= container
;
3575 key
.num
= param_num
;
3576 key
.gshared_constraint
= NULL
;
3577 MonoConcurrentHashTable
*cache
= is_mvar
? image
->mvar_gparam_cache
: image
->var_gparam_cache
;
3580 return (MonoGenericParam
*)mono_conc_hashtable_lookup (cache
, &key
);
3584 static MonoGenericParam
*
3585 publish_anon_gparam_fast (MonoImage
*image
, MonoGenericContainer
*container
, gint32 param_num
)
3587 g_assert (param_num
>= 0 && param_num
< FAST_GPARAM_CACHE_SIZE
);
3588 MonoGenericParam
**cache
= container
->is_method
? &image
->mvar_gparam_cache_fast
: &image
->var_gparam_cache_fast
;
3590 mono_image_lock (image
);
3592 *cache
= (MonoGenericParam
*)mono_image_alloc0 (image
, sizeof (MonoGenericParam
) * FAST_GPARAM_CACHE_SIZE
);
3593 for (gint32 i
= 0; i
< FAST_GPARAM_CACHE_SIZE
; ++i
) {
3594 MonoGenericParam
*param
= &(*cache
)[i
];
3595 param
->owner
= container
;
3599 mono_image_unlock (image
);
3601 return &(*cache
)[param_num
];
3605 * publish_anon_gparam_slow:
3607 * Publish \p gparam anonymous generic parameter to the anon gparam cache for \p image.
3609 * LOCKING: takes the image lock.
3611 static MonoGenericParam
*
3612 publish_anon_gparam_slow (MonoImage
*image
, MonoGenericParam
*gparam
)
3614 MonoConcurrentHashTable
**cache
= gparam
->owner
->is_method
? &image
->mvar_gparam_cache
: &image
->var_gparam_cache
;
3616 mono_image_lock (image
);
3618 MonoConcurrentHashTable
*ht
= mono_conc_hashtable_new ((GHashFunc
)mono_metadata_generic_param_hash
,
3619 (GEqualFunc
) mono_metadata_generic_param_equal
);
3620 mono_atomic_store_release (cache
, ht
);
3622 mono_image_unlock (image
);
3624 MonoGenericParam
*other
= (MonoGenericParam
*)mono_conc_hashtable_insert (*cache
, gparam
, gparam
);
3625 // If another thread published first return their param, otherwise return ours.
3626 return other
? other
: gparam
;
3630 * mono_metadata_create_anon_gparam:
3631 * \param image the MonoImage that owns the anonymous generic parameter
3632 * \param param_num the parameter number
3633 * \param is_mvar TRUE if this is a method generic parameter, FALSE if it's a class generic parameter.
3635 * Returns: a new, or exisisting \c MonoGenericParam for an anonymous generic parameter with the given properties.
3637 * LOCKING: takes the image lock.
3640 mono_metadata_create_anon_gparam (MonoImage
*image
, gint32 param_num
, gboolean is_mvar
)
3642 MonoGenericContainer
*container
= mono_get_anonymous_container_for_image (image
, is_mvar
);
3643 MonoGenericParam
*gparam
= lookup_anon_gparam (image
, container
, param_num
, is_mvar
);
3646 if (param_num
>= 0 && param_num
< FAST_GPARAM_CACHE_SIZE
) {
3647 return publish_anon_gparam_fast (image
, container
, param_num
);
3649 // Create a candidate generic param and try to insert it in the cache.
3650 // If multiple threads both try to publish the same param, all but one
3651 // will leak, but that's okay.
3652 gparam
= (MonoGenericParam
*)mono_image_alloc0 (image
, sizeof (MonoGenericParam
));
3653 gparam
->owner
= container
;
3654 gparam
->num
= param_num
;
3656 return publish_anon_gparam_slow (image
, gparam
);
3661 * mono_metadata_parse_generic_param:
3662 * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3663 * see mono_metadata_parse_type_checked() for details.
3664 * Internal routine to parse a generic type parameter.
3665 * LOCKING: Acquires the loader lock
3667 static MonoGenericParam
*
3668 mono_metadata_parse_generic_param (MonoImage
*m
, MonoGenericContainer
*generic_container
,
3669 MonoTypeEnum type
, const char *ptr
, const char **rptr
, MonoError
*error
)
3671 int index
= mono_metadata_decode_value (ptr
, &ptr
);
3677 generic_container
= select_container (generic_container
, type
);
3678 if (!generic_container
) {
3679 gboolean is_mvar
= FALSE
;
3684 case MONO_TYPE_MVAR
:
3688 g_error ("Cerating generic param object with invalid MonoType"); // This is not a generic param
3691 return mono_metadata_create_anon_gparam (m
, index
, is_mvar
);
3694 if (index
>= generic_container
->type_argc
) {
3695 mono_error_set_bad_image (error
, m
, "Invalid generic %s parameter index %d, max index is %d",
3696 generic_container
->is_method
? "method" : "type",
3697 index
, generic_container
->type_argc
);
3701 //This can't return NULL
3702 return mono_generic_container_get_param (generic_container
, index
);
3706 * mono_metadata_get_shared_type:
3708 * Return a shared instance of TYPE, if available, NULL otherwise.
3709 * Shared MonoType instances help save memory. Their contents should not be modified
3710 * by the caller. They do not need to be freed as their lifetime is bound by either
3711 * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3712 * instance they are embedded in. If they are freed, they should be freed using
3713 * mono_metadata_free_type () instead of g_free ().
3716 mono_metadata_get_shared_type (MonoType
*type
)
3720 /* No need to use locking since nobody is modifying the hash table */
3721 if ((cached
= (MonoType
*)g_hash_table_lookup (type_cache
, type
)))
3724 switch (type
->type
){
3725 case MONO_TYPE_CLASS
:
3726 case MONO_TYPE_VALUETYPE
:
3727 if (type
== m_class_get_byval_arg (type
->data
.klass
))
3729 if (type
== m_class_get_this_arg (type
->data
.klass
))
3740 compare_type_literals (MonoImage
*image
, int class_type
, int type_type
, MonoError
*error
)
3744 /* _byval_arg.type can be zero if we're decoding a type that references a class been loading.
3745 * See mcs/test/gtest-440. and #650936.
3746 * FIXME This better be moved to the metadata verifier as it can catch more cases.
3750 /* NET 1.1 assemblies might encode string and object in a denormalized way.
3753 if (class_type
== type_type
)
3756 if (type_type
== MONO_TYPE_CLASS
) {
3757 if (class_type
== MONO_TYPE_STRING
|| class_type
== MONO_TYPE_OBJECT
)
3759 //XXX stringify this argument
3760 mono_error_set_bad_image (error
, image
, "Expected reference type but got type kind %d", class_type
);
3764 g_assert (type_type
== MONO_TYPE_VALUETYPE
);
3765 switch (class_type
) {
3766 case MONO_TYPE_BOOLEAN
:
3767 case MONO_TYPE_CHAR
:
3780 case MONO_TYPE_CLASS
:
3783 //XXX stringify this argument
3784 mono_error_set_bad_image (error
, image
, "Expected value type but got type kind %d", class_type
);
3790 verify_var_type_and_container (MonoImage
*image
, int var_type
, MonoGenericContainer
*container
, MonoError
*error
)
3793 if (var_type
== MONO_TYPE_MVAR
) {
3794 if (!container
->is_method
) { //MVAR and a method container
3795 mono_error_set_bad_image (error
, image
, "MVAR parsed in a context without a method container");
3799 if (!(!container
->is_method
|| //VAR and class container
3800 (container
->is_method
&& container
->parent
))) { //VAR and method container with parent
3801 mono_error_set_bad_image (error
, image
, "VAR parsed in a context without a class container");
3809 * do_mono_metadata_parse_type:
3810 * @type: MonoType to be filled in with the return value
3812 * @generic_context: generics_context
3813 * @transient: whenever to allocate data from the heap
3814 * @ptr: pointer to the encoded type
3815 * @rptr: pointer where the end of the encoded type is saved
3817 * Internal routine used to "fill" the contents of @type from an
3818 * allocated pointer. This is done this way to avoid doing too
3819 * many mini-allocations (particularly for the MonoFieldType which
3820 * most of the time is just a MonoType, but sometimes might be augmented).
3822 * This routine is used by mono_metadata_parse_type and
3823 * mono_metadata_parse_field_type
3825 * This extracts a Type as specified in Partition II (22.2.12)
3827 * Returns: FALSE if the type could not be loaded
3830 do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
3831 gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
3835 type
->type
= (MonoTypeEnum
)mono_metadata_decode_value (ptr
, &ptr
);
3837 switch (type
->type
){
3838 case MONO_TYPE_VOID
:
3839 case MONO_TYPE_BOOLEAN
:
3840 case MONO_TYPE_CHAR
:
3853 case MONO_TYPE_STRING
:
3854 case MONO_TYPE_OBJECT
:
3855 case MONO_TYPE_TYPEDBYREF
:
3857 case MONO_TYPE_VALUETYPE
:
3858 case MONO_TYPE_CLASS
: {
3861 token
= mono_metadata_parse_typedef_or_ref (m
, ptr
, &ptr
);
3862 klass
= mono_class_get_checked (m
, token
, error
);
3863 type
->data
.klass
= klass
;
3867 if (!compare_type_literals (m
, m_class_get_byval_arg (klass
)->type
, type
->type
, error
))
3872 case MONO_TYPE_SZARRAY
: {
3873 MonoType
*etype
= mono_metadata_parse_type_checked (m
, container
, 0, transient
, ptr
, &ptr
, error
);
3877 type
->data
.klass
= mono_class_from_mono_type_internal (etype
);
3880 mono_metadata_free_type (etype
);
3882 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.
3885 case MONO_TYPE_PTR
: {
3886 type
->data
.type
= mono_metadata_parse_type_checked (m
, container
, 0, transient
, ptr
, &ptr
, error
);
3887 if (!type
->data
.type
)
3891 case MONO_TYPE_FNPTR
: {
3892 type
->data
.method
= mono_metadata_parse_method_signature_full (m
, container
, 0, ptr
, &ptr
, error
);
3893 if (!type
->data
.method
)
3897 case MONO_TYPE_ARRAY
: {
3898 type
->data
.array
= mono_metadata_parse_array_internal (m
, container
, transient
, ptr
, &ptr
, error
);
3899 if (!type
->data
.array
)
3903 case MONO_TYPE_MVAR
:
3904 case MONO_TYPE_VAR
: {
3905 if (container
&& !verify_var_type_and_container (m
, type
->type
, container
, error
))
3908 type
->data
.generic_param
= mono_metadata_parse_generic_param (m
, container
, type
->type
, ptr
, &ptr
, error
);
3909 if (!type
->data
.generic_param
)
3914 case MONO_TYPE_GENERICINST
: {
3915 if (!do_mono_metadata_parse_generic_class (type
, m
, container
, ptr
, &ptr
, error
))
3920 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
);
3930 * mono_metadata_free_type:
3931 * \param type type to free
3933 * Free the memory allocated for type \p type which is allocated on the heap.
3936 mono_metadata_free_type (MonoType
*type
)
3938 if (type
>= builtin_types
&& type
< builtin_types
+ NBUILTIN_TYPES ())
3941 switch (type
->type
){
3942 case MONO_TYPE_OBJECT
:
3943 case MONO_TYPE_STRING
:
3944 if (!type
->data
.klass
)
3947 case MONO_TYPE_CLASS
:
3948 case MONO_TYPE_VALUETYPE
:
3949 if (type
== m_class_get_byval_arg (type
->data
.klass
) || type
== m_class_get_this_arg (type
->data
.klass
))
3953 mono_metadata_free_type (type
->data
.type
);
3955 case MONO_TYPE_FNPTR
:
3956 mono_metadata_free_method_signature (type
->data
.method
);
3958 case MONO_TYPE_ARRAY
:
3959 mono_metadata_free_array (type
->data
.array
);
3970 hex_dump (const char *buffer
, int base
, int count
)
3972 int show_header
= 1;
3980 for (i
= 0; i
< count
; i
++){
3983 printf ("\n0x%08x: ", (unsigned char) base
+ i
);
3985 printf ("%02x ", (unsigned char) (buffer
[i
]));
3992 * @ptr: Points to the beginning of the Section Data (25.3)
3994 static MonoExceptionClause
*
3995 parse_section_data (MonoImage
*m
, int *num_clauses
, const unsigned char *ptr
, MonoError
*error
)
3997 unsigned char sect_data_flags
;
3999 guint32 sect_data_len
;
4000 MonoExceptionClause
* clauses
= NULL
;
4005 /* align on 32-bit boundary */
4006 ptr
= dword_align (ptr
);
4007 sect_data_flags
= *ptr
;
4010 is_fat
= sect_data_flags
& METHOD_HEADER_SECTION_FAT_FORMAT
;
4012 sect_data_len
= (ptr
[2] << 16) | (ptr
[1] << 8) | ptr
[0];
4015 sect_data_len
= ptr
[0];
4019 if (sect_data_flags
& METHOD_HEADER_SECTION_EHTABLE
) {
4020 const unsigned char *p
= dword_align (ptr
);
4022 *num_clauses
= is_fat
? sect_data_len
/ 24: sect_data_len
/ 12;
4023 /* we could just store a pointer if we don't need to byteswap */
4024 clauses
= (MonoExceptionClause
*)g_malloc0 (sizeof (MonoExceptionClause
) * (*num_clauses
));
4025 for (i
= 0; i
< *num_clauses
; ++i
) {
4026 MonoExceptionClause
*ec
= &clauses
[i
];
4029 ec
->flags
= read32 (p
);
4030 ec
->try_offset
= read32 (p
+ 4);
4031 ec
->try_len
= read32 (p
+ 8);
4032 ec
->handler_offset
= read32 (p
+ 12);
4033 ec
->handler_len
= read32 (p
+ 16);
4034 tof_value
= read32 (p
+ 20);
4037 ec
->flags
= read16 (p
);
4038 ec
->try_offset
= read16 (p
+ 2);
4039 ec
->try_len
= *(p
+ 4);
4040 ec
->handler_offset
= read16 (p
+ 5);
4041 ec
->handler_len
= *(p
+ 7);
4042 tof_value
= read32 (p
+ 8);
4045 if (ec
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
) {
4046 ec
->data
.filter_offset
= tof_value
;
4047 } else if (ec
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) {
4048 ec
->data
.catch_class
= NULL
;
4050 ec
->data
.catch_class
= mono_class_get_checked (m
, tof_value
, error
);
4051 if (!is_ok (error
)) {
4057 ec
->data
.catch_class
= NULL
;
4059 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
4063 if (sect_data_flags
& METHOD_HEADER_SECTION_MORE_SECTS
)
4064 ptr
+= sect_data_len
- 4; /* LAMESPEC: it seems the size includes the header */
4071 * mono_method_get_header_summary:
4072 * @method: The method to get the header.
4073 * @summary: Where to store the header
4076 * Returns: TRUE if the header was properly decoded.
4079 mono_method_get_header_summary (MonoMethod
*method
, MonoMethodHeaderSummary
*summary
)
4085 unsigned char flags
, format
;
4089 /*Only the GMD has a pointer to the metadata.*/
4090 while (method
->is_inflated
)
4091 method
= ((MonoMethodInflated
*)method
)->declaring
;
4093 summary
->code
= NULL
;
4094 summary
->code_size
= 0;
4095 summary
->max_stack
= 0;
4096 summary
->has_clauses
= FALSE
;
4097 summary
->has_locals
= FALSE
;
4099 /*FIXME extract this into a MACRO and share it with mono_method_get_header*/
4100 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
))
4103 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| method
->sre_method
) {
4104 MonoMethodHeader
*header
= ((MonoMethodWrapper
*)method
)->header
;
4107 summary
->code
= header
->code
;
4108 summary
->code_size
= header
->code_size
;
4109 summary
->max_stack
= header
->max_stack
;
4110 summary
->has_clauses
= header
->num_clauses
> 0;
4111 summary
->has_locals
= header
->num_locals
> 0;
4116 idx
= mono_metadata_token_index (method
->token
);
4117 img
= m_class_get_image (method
->klass
);
4118 rva
= mono_metadata_decode_row_col (&img
->tables
[MONO_TABLE_METHOD
], idx
- 1, MONO_METHOD_RVA
);
4120 /*We must run the verifier since we'll be decoding it.*/
4121 if (!mono_verifier_verify_method_header (img
, rva
, error
)) {
4122 mono_error_cleanup (error
);
4126 ptr
= mono_image_rva_map (img
, rva
);
4130 flags
= *(const unsigned char *)ptr
;
4131 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
4134 case METHOD_HEADER_TINY_FORMAT
:
4136 summary
->max_stack
= 8;
4137 summary
->code
= (unsigned char *) ptr
;
4138 summary
->code_size
= flags
>> 2;
4140 case METHOD_HEADER_FAT_FORMAT
:
4141 fat_flags
= read16 (ptr
);
4143 summary
->max_stack
= read16 (ptr
);
4145 summary
->code_size
= read32 (ptr
);
4147 summary
->has_locals
= !!read32 (ptr
);
4149 if (fat_flags
& METHOD_HEADER_MORE_SECTS
)
4150 summary
->has_clauses
= TRUE
;
4151 summary
->code
= (unsigned char *) ptr
;
4160 * mono_metadata_parse_mh_full:
4161 * @m: metadata context
4162 * @generic_context: generics context
4163 * @ptr: pointer to the method header.
4165 * Decode the method header at @ptr, including pointer to the IL code,
4166 * info about local variables and optional exception tables.
4167 * This is a Mono runtime internal function.
4169 * LOCKING: Acquires the loader lock.
4171 * Returns: a transient MonoMethodHeader allocated from the heap.
4174 mono_metadata_parse_mh_full (MonoImage
*m
, MonoGenericContainer
*container
, const char *ptr
, MonoError
*error
)
4176 MonoMethodHeader
*mh
= NULL
;
4177 unsigned char flags
= *(const unsigned char *) ptr
;
4178 unsigned char format
= flags
& METHOD_HEADER_FORMAT_MASK
;
4180 guint32 local_var_sig_tok
, max_stack
, code_size
, init_locals
;
4181 const unsigned char *code
;
4182 MonoExceptionClause
* clauses
= NULL
;
4183 int num_clauses
= 0;
4184 MonoTableInfo
*t
= &m
->tables
[MONO_TABLE_STANDALONESIG
];
4185 guint32 cols
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
4190 mono_error_set_bad_image (error
, m
, "Method header with null pointer");
4195 case METHOD_HEADER_TINY_FORMAT
:
4196 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
);
4199 mh
->is_transient
= TRUE
;
4200 local_var_sig_tok
= 0;
4201 mh
->code_size
= flags
>> 2;
4202 mh
->code
= (unsigned char*)ptr
;
4204 case METHOD_HEADER_FAT_FORMAT
:
4205 fat_flags
= read16 (ptr
);
4207 max_stack
= read16 (ptr
);
4209 code_size
= read32 (ptr
);
4211 local_var_sig_tok
= read32 (ptr
);
4214 if (fat_flags
& METHOD_HEADER_INIT_LOCALS
)
4219 code
= (unsigned char*)ptr
;
4221 if (!(fat_flags
& METHOD_HEADER_MORE_SECTS
))
4225 * There are more sections
4227 ptr
= (char*)code
+ code_size
;
4230 mono_error_set_bad_image (error
, m
, "Invalid method header format %d", format
);
4234 if (local_var_sig_tok
) {
4235 int idx
= (local_var_sig_tok
& 0xffffff)-1;
4236 if (idx
>= t
->rows
|| idx
< 0) {
4237 mono_error_set_bad_image (error
, m
, "Invalid method header local vars signature token 0x%8x", idx
);
4240 mono_metadata_decode_row (t
, idx
, cols
, 1);
4242 if (!mono_verifier_verify_standalone_signature (m
, cols
[MONO_STAND_ALONE_SIGNATURE
], error
))
4245 if (fat_flags
& METHOD_HEADER_MORE_SECTS
) {
4246 clauses
= parse_section_data (m
, &num_clauses
, (const unsigned char*)ptr
, error
);
4247 goto_if_nok (error
, fail
);
4249 if (local_var_sig_tok
) {
4250 const char *locals_ptr
;
4253 locals_ptr
= mono_metadata_blob_heap (m
, cols
[MONO_STAND_ALONE_SIGNATURE
]);
4254 mono_metadata_decode_blob_size (locals_ptr
, &locals_ptr
);
4255 if (*locals_ptr
!= 0x07)
4256 g_warning ("wrong signature for locals blob");
4258 len
= mono_metadata_decode_value (locals_ptr
, &locals_ptr
);
4259 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ len
* sizeof (MonoType
*) + num_clauses
* sizeof (MonoExceptionClause
));
4260 mh
->num_locals
= len
;
4261 for (i
= 0; i
< len
; ++i
) {
4262 mh
->locals
[i
] = mono_metadata_parse_type_internal (m
, container
, 0, TRUE
, locals_ptr
, &locals_ptr
, error
);
4263 goto_if_nok (error
, fail
);
4266 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ num_clauses
* sizeof (MonoExceptionClause
));
4269 mh
->code_size
= code_size
;
4270 mh
->max_stack
= max_stack
;
4271 mh
->is_transient
= TRUE
;
4272 mh
->init_locals
= init_locals
;
4274 MonoExceptionClause
* clausesp
= (MonoExceptionClause
*)&mh
->locals
[mh
->num_locals
];
4275 memcpy (clausesp
, clauses
, num_clauses
* sizeof (MonoExceptionClause
));
4277 mh
->clauses
= clausesp
;
4278 mh
->num_clauses
= num_clauses
;
4289 * mono_metadata_parse_mh:
4290 * \param generic_context generics context
4291 * \param ptr pointer to the method header.
4293 * Decode the method header at \p ptr, including pointer to the IL code,
4294 * info about local variables and optional exception tables.
4296 * \returns a transient \c MonoMethodHeader allocated from the heap.
4299 mono_metadata_parse_mh (MonoImage
*m
, const char *ptr
)
4302 MonoMethodHeader
*header
= mono_metadata_parse_mh_full (m
, NULL
, ptr
, error
);
4303 mono_error_cleanup (error
);
4308 * mono_metadata_free_mh:
4309 * \param mh a method header
4311 * Free the memory allocated for the method header.
4314 mono_metadata_free_mh (MonoMethodHeader
*mh
)
4318 /* If it is not transient it means it's part of a wrapper method,
4319 * or a SRE-generated method, so the lifetime in that case is
4320 * dictated by the method's own lifetime
4322 if (mh
&& mh
->is_transient
) {
4323 for (i
= 0; i
< mh
->num_locals
; ++i
)
4324 mono_metadata_free_type (mh
->locals
[i
]);
4330 * mono_method_header_get_code:
4331 * \param header a \c MonoMethodHeader pointer
4332 * \param code_size memory location for returning the code size
4333 * \param max_stack memory location for returning the max stack
4335 * Method header accessor to retreive info about the IL code properties:
4336 * a pointer to the IL code itself, the size of the code and the max number
4337 * of stack slots used by the code.
4339 * \returns pointer to the IL code represented by the method header.
4341 const unsigned char*
4342 mono_method_header_get_code (MonoMethodHeader
*header
, guint32
* code_size
, guint32
* max_stack
)
4345 *code_size
= header
->code_size
;
4347 *max_stack
= header
->max_stack
;
4348 return header
->code
;
4352 * mono_method_header_get_locals:
4353 * \param header a \c MonoMethodHeader pointer
4354 * \param num_locals memory location for returning the number of local variables
4355 * \param init_locals memory location for returning the init_locals flag
4357 * Method header accessor to retreive info about the local variables:
4358 * an array of local types, the number of locals and whether the locals
4359 * are supposed to be initialized to 0 on method entry
4361 * \returns pointer to an array of types of the local variables
4364 mono_method_header_get_locals (MonoMethodHeader
*header
, guint32
* num_locals
, gboolean
*init_locals
)
4367 *num_locals
= header
->num_locals
;
4369 *init_locals
= header
->init_locals
;
4370 return header
->locals
;
4374 * mono_method_header_get_num_clauses:
4375 * @header: a MonoMethodHeader pointer
4377 * Method header accessor to retreive the number of exception clauses.
4379 * Returns: the number of exception clauses present
4382 mono_method_header_get_num_clauses (MonoMethodHeader
*header
)
4384 return header
->num_clauses
;
4388 * mono_method_header_get_clauses:
4389 * \param header a \c MonoMethodHeader pointer
4390 * \param method \c MonoMethod the header belongs to
4391 * \param iter pointer to a iterator
4392 * \param clause pointer to a \c MonoExceptionClause structure which will be filled with the info
4394 * Get the info about the exception clauses in the method. Set \c *iter to NULL to
4395 * initiate the iteration, then call the method repeatedly until it returns FALSE.
4396 * At each iteration, the structure pointed to by clause if filled with the
4397 * exception clause information.
4399 * \returns TRUE if clause was filled with info, FALSE if there are no more exception
4403 mono_method_header_get_clauses (MonoMethodHeader
*header
, MonoMethod
*method
, gpointer
*iter
, MonoExceptionClause
*clause
)
4405 MonoExceptionClause
*sc
;
4406 /* later we'll be able to use this interface to parse the clause info on demand,
4407 * without allocating anything.
4409 if (!iter
|| !header
->num_clauses
)
4412 *iter
= sc
= header
->clauses
;
4416 sc
= (MonoExceptionClause
*)*iter
;
4418 if (sc
< header
->clauses
+ header
->num_clauses
) {
4427 * mono_metadata_parse_field_type:
4428 * \param m metadata context to extract information from
4429 * \param ptr pointer to the field signature
4430 * \param rptr pointer updated to match the end of the decoded stream
4432 * Parses the field signature, and returns the type information for it.
4434 * \returns The \c MonoType that was extracted from \p ptr .
4437 mono_metadata_parse_field_type (MonoImage
*m
, short field_flags
, const char *ptr
, const char **rptr
)
4440 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, field_flags
, FALSE
, ptr
, rptr
, error
);
4441 mono_error_cleanup (error
);
4446 * mono_metadata_parse_param:
4447 * \param m metadata context to extract information from
4448 * \param ptr pointer to the param signature
4449 * \param rptr pointer updated to match the end of the decoded stream
4451 * Parses the param signature, and returns the type information for it.
4453 * \returns The \c MonoType that was extracted from \p ptr .
4456 mono_metadata_parse_param (MonoImage
*m
, const char *ptr
, const char **rptr
)
4459 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, 0, FALSE
, ptr
, rptr
, error
);
4460 mono_error_cleanup (error
);
4465 * mono_metadata_token_from_dor:
4466 * \param dor_token A \c TypeDefOrRef coded index
4468 * \p dor_token is a \c TypeDefOrRef coded index: it contains either
4469 * a \c TypeDef, \c TypeRef or \c TypeSpec in the lower bits, and the upper
4470 * bits contain an index into the table.
4472 * \returns an expanded token
4475 mono_metadata_token_from_dor (guint32 dor_index
)
4479 table
= dor_index
& 0x03;
4480 idx
= dor_index
>> 2;
4483 case 0: /* TypeDef */
4484 return MONO_TOKEN_TYPE_DEF
| idx
;
4485 case 1: /* TypeRef */
4486 return MONO_TOKEN_TYPE_REF
| idx
;
4487 case 2: /* TypeSpec */
4488 return MONO_TOKEN_TYPE_SPEC
| idx
;
4490 g_assert_not_reached ();
4497 * We use this to pass context information to the row locator
4500 int idx
; /* The index that we are trying to locate */
4501 int col_idx
; /* The index in the row where idx may be stored */
4502 MonoTableInfo
*t
; /* pointer to the table */
4507 * How the row locator works.
4512 * ___|___------> _______
4515 * A column in the rows of table A references an index in table B.
4516 * For example A may be the TYPEDEF table and B the METHODDEF table.
4518 * Given an index in table B we want to get the row in table A
4519 * where the column n references our index in B.
4521 * In the locator_t structure:
4523 * col_idx is the column number
4524 * index is the index in table B
4525 * result will be the index in table A
4528 * Table A Table B column (in table A)
4529 * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
4530 * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
4531 * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
4532 * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
4533 * METHODSEM PROPERTY ASSOCIATION (encoded index)
4535 * Note that we still don't support encoded indexes.
4539 typedef_locator (const void *a
, const void *b
)
4541 locator_t
*loc
= (locator_t
*) a
;
4542 const char *bb
= (const char *) b
;
4543 int typedef_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4544 guint32 col
, col_next
;
4546 col
= mono_metadata_decode_row_col (loc
->t
, typedef_index
, loc
->col_idx
);
4552 * Need to check that the next row is valid.
4554 if (typedef_index
+ 1 < loc
->t
->rows
) {
4555 col_next
= mono_metadata_decode_row_col (loc
->t
, typedef_index
+ 1, loc
->col_idx
);
4556 if (loc
->idx
>= col_next
)
4559 if (col
== col_next
)
4563 loc
->result
= typedef_index
;
4569 table_locator (const void *a
, const void *b
)
4571 locator_t
*loc
= (locator_t
*) a
;
4572 const char *bb
= (const char *) b
;
4573 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4576 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
4578 if (loc
->idx
== col
) {
4579 loc
->result
= table_index
;
4589 declsec_locator (const void *a
, const void *b
)
4591 locator_t
*loc
= (locator_t
*) a
;
4592 const char *bb
= (const char *) b
;
4593 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4596 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
4598 if (loc
->idx
== col
) {
4599 loc
->result
= table_index
;
4611 * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
4612 * which contains IDX.
4615 search_ptr_table (MonoImage
*image
, int table
, int idx
)
4617 MonoTableInfo
*ptrdef
= &image
->tables
[table
];
4620 /* Use a linear search to find our index in the table */
4621 for (i
= 0; i
< ptrdef
->rows
; i
++)
4622 /* All the Ptr tables have the same structure */
4623 if (mono_metadata_decode_row_col (ptrdef
, i
, 0) == idx
)
4626 if (i
< ptrdef
->rows
)
4633 * mono_metadata_typedef_from_field:
4634 * \param meta metadata context
4635 * \param index FieldDef token
4637 * \returns the 1-based index into the \c TypeDef table of the type that
4638 * declared the field described by \p index, or 0 if not found.
4641 mono_metadata_typedef_from_field (MonoImage
*meta
, guint32 index
)
4643 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
4649 loc
.idx
= mono_metadata_token_index (index
);
4650 loc
.col_idx
= MONO_TYPEDEF_FIELD_LIST
;
4653 if (meta
->uncompressed_metadata
)
4654 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
4656 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
4659 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4660 return loc
.result
+ 1;
4664 * mono_metadata_typedef_from_method:
4665 * \param meta metadata context
4666 * \param index \c MethodDef token
4667 * \returns the 1-based index into the \c TypeDef table of the type that
4668 * declared the method described by \p index. 0 if not found.
4671 mono_metadata_typedef_from_method (MonoImage
*meta
, guint32 index
)
4673 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
4679 loc
.idx
= mono_metadata_token_index (index
);
4680 loc
.col_idx
= MONO_TYPEDEF_METHOD_LIST
;
4683 if (meta
->uncompressed_metadata
)
4684 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_METHOD_POINTER
, loc
.idx
);
4686 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
4689 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4690 return loc
.result
+ 1;
4694 * mono_metadata_interfaces_from_typedef_full:
4695 * \param meta metadata context
4696 * \param index typedef token
4697 * \param interfaces Out parameter used to store the interface array
4698 * \param count Out parameter used to store the number of interfaces
4699 * \param heap_alloc_result if TRUE the result array will be \c g_malloc'd
4700 * \param context The generic context
4701 * \param error set on error
4703 * The array of interfaces that the \p index typedef token implements is returned in
4704 * \p interfaces. The number of elements in the array is returned in \p count.
4706 * \returns \c TRUE on success, \c FALSE on failure and sets \p error.
4709 mono_metadata_interfaces_from_typedef_full (MonoImage
*meta
, guint32 index
, MonoClass
***interfaces
, guint
*count
, gboolean heap_alloc_result
, MonoGenericContext
*context
, MonoError
*error
)
4711 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_INTERFACEIMPL
];
4714 guint32 cols
[MONO_INTERFACEIMPL_SIZE
];
4725 loc
.idx
= mono_metadata_token_index (index
);
4726 loc
.col_idx
= MONO_INTERFACEIMPL_CLASS
;
4729 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4734 * We may end up in the middle of the rows...
4737 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_INTERFACEIMPL_CLASS
))
4743 while (pos
< tdef
->rows
) {
4744 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
4745 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
4750 if (heap_alloc_result
)
4751 result
= g_new0 (MonoClass
*, pos
- start
);
4753 result
= (MonoClass
**)mono_image_alloc0 (meta
, sizeof (MonoClass
*) * (pos
- start
));
4756 while (pos
< tdef
->rows
) {
4759 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
4760 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
4762 iface
= mono_class_get_and_inflate_typespec_checked (
4763 meta
, mono_metadata_token_from_dor (cols
[MONO_INTERFACEIMPL_INTERFACE
]), context
, error
);
4766 result
[pos
- start
] = iface
;
4769 *count
= pos
- start
;
4770 *interfaces
= result
;
4775 * mono_metadata_interfaces_from_typedef:
4776 * \param meta metadata context
4777 * \param index typedef token
4778 * \param count Out parameter used to store the number of interfaces
4780 * The array of interfaces that the \p index typedef token implements is returned in
4781 * \p interfaces. The number of elements in the array is returned in \p count. The returned
4782 * array is allocated with \c g_malloc and the caller must free it.
4784 * LOCKING: Acquires the loader lock .
4786 * \returns the interface array on success, NULL on failure.
4789 mono_metadata_interfaces_from_typedef (MonoImage
*meta
, guint32 index
, guint
*count
)
4792 MonoClass
**interfaces
= NULL
;
4795 rv
= mono_metadata_interfaces_from_typedef_full (meta
, index
, &interfaces
, count
, TRUE
, NULL
, error
);
4796 mono_error_assert_ok (error
);
4804 * mono_metadata_nested_in_typedef:
4805 * \param meta metadata context
4806 * \param index typedef token
4807 * \returns the 1-based index into the TypeDef table of the type
4808 * where the type described by \p index is nested.
4809 * Returns 0 if \p index describes a non-nested type.
4812 mono_metadata_nested_in_typedef (MonoImage
*meta
, guint32 index
)
4814 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4820 loc
.idx
= mono_metadata_token_index (index
);
4821 loc
.col_idx
= MONO_NESTED_CLASS_NESTED
;
4824 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4827 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4828 return mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_NESTED_CLASS_ENCLOSING
) | MONO_TOKEN_TYPE_DEF
;
4832 * mono_metadata_nesting_typedef:
4833 * \param meta metadata context
4834 * \param index typedef token
4835 * \returns the 1-based index into the \c TypeDef table of the first type
4836 * that is nested inside the type described by \p index. The search starts at
4837 * \p start_index. Returns 0 if no such type is found.
4840 mono_metadata_nesting_typedef (MonoImage
*meta
, guint32 index
, guint32 start_index
)
4842 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4844 guint32 class_index
= mono_metadata_token_index (index
);
4849 start
= start_index
;
4851 while (start
<= tdef
->rows
) {
4852 if (class_index
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_NESTED_CLASS_ENCLOSING
))
4858 if (start
> tdef
->rows
)
4865 * mono_metadata_packing_from_typedef:
4866 * \param meta metadata context
4867 * \param index token representing a type
4868 * \returns the info stored in the \c ClassLayout table for the given typedef token
4869 * into the \p packing and \p size pointers.
4870 * Returns 0 if the info is not found.
4873 mono_metadata_packing_from_typedef (MonoImage
*meta
, guint32 index
, guint32
*packing
, guint32
*size
)
4875 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CLASSLAYOUT
];
4877 guint32 cols
[MONO_CLASS_LAYOUT_SIZE
];
4882 loc
.idx
= mono_metadata_token_index (index
);
4883 loc
.col_idx
= MONO_CLASS_LAYOUT_PARENT
;
4886 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4889 mono_metadata_decode_row (tdef
, loc
.result
, cols
, MONO_CLASS_LAYOUT_SIZE
);
4891 *packing
= cols
[MONO_CLASS_LAYOUT_PACKING_SIZE
];
4893 *size
= cols
[MONO_CLASS_LAYOUT_CLASS_SIZE
];
4895 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4896 return loc
.result
+ 1;
4900 * mono_metadata_custom_attrs_from_index:
4901 * \param meta metadata context
4902 * \param index token representing the parent
4903 * \returns: the 1-based index into the \c CustomAttribute table of the first
4904 * attribute which belongs to the metadata object described by \p index.
4905 * Returns 0 if no such attribute is found.
4908 mono_metadata_custom_attrs_from_index (MonoImage
*meta
, guint32 index
)
4910 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4917 loc
.col_idx
= MONO_CUSTOM_ATTR_PARENT
;
4920 /* FIXME: Index translation */
4922 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4925 /* Find the first entry by searching backwards */
4926 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_CUSTOM_ATTR_PARENT
) == index
))
4929 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4930 return loc
.result
+ 1;
4934 * mono_metadata_declsec_from_index:
4935 * \param meta metadata context
4936 * \param index token representing the parent
4937 * \returns the 0-based index into the \c DeclarativeSecurity table of the first
4938 * attribute which belongs to the metadata object described by \p index.
4939 * Returns \c -1 if no such attribute is found.
4942 mono_metadata_declsec_from_index (MonoImage
*meta
, guint32 index
)
4944 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_DECLSECURITY
];
4951 loc
.col_idx
= MONO_DECL_SECURITY_PARENT
;
4954 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, declsec_locator
))
4957 /* Find the first entry by searching backwards */
4958 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_DECL_SECURITY_PARENT
) == index
))
4965 * mono_metadata_localscope_from_methoddef:
4966 * @meta: metadata context
4967 * @index: methoddef index
4969 * Returns: the 1-based index into the LocalScope table of the first
4970 * scope which belongs to the method described by @index.
4971 * Returns 0 if no such row is found.
4974 mono_metadata_localscope_from_methoddef (MonoImage
*meta
, guint32 index
)
4976 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_LOCALSCOPE
];
4983 loc
.col_idx
= MONO_LOCALSCOPE_METHOD
;
4986 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4989 /* Find the first entry by searching backwards */
4990 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_LOCALSCOPE_METHOD
) == index
))
4993 return loc
.result
+ 1;
4998 mono_backtrace (int limit
)
5003 backtrace (array
, limit
);
5004 names
= backtrace_symbols (array
, limit
);
5005 for (i
=0; i
< limit
; ++i
) {
5006 g_print ("\t%s\n", names
[i
]);
5012 static int i8_align
;
5015 * mono_type_set_alignment:
5017 * Set the alignment used by runtime to layout fields etc. of type TYPE to ALIGN.
5018 * This should only be used in AOT mode since the resulting layout will not match the
5022 mono_type_set_alignment (MonoTypeEnum type
, int align
)
5024 /* Support only a few types whose alignment is abi dependent */
5030 g_assert_not_reached ();
5037 * \param t the type to return the size of
5038 * \returns The number of bytes required to hold an instance of this
5042 mono_type_size (MonoType
*t
, int *align
)
5044 MonoTypeEnum simple_type
;
5051 *align
= MONO_ABI_ALIGNOF (gpointer
);
5052 return MONO_ABI_SIZEOF (gpointer
);
5055 simple_type
= t
->type
;
5057 switch (simple_type
) {
5058 case MONO_TYPE_VOID
:
5061 case MONO_TYPE_BOOLEAN
:
5062 *align
= MONO_ABI_ALIGNOF (gint8
);
5066 *align
= MONO_ABI_ALIGNOF (gint8
);
5068 case MONO_TYPE_CHAR
:
5071 *align
= MONO_ABI_ALIGNOF (gint16
);
5075 *align
= MONO_ABI_ALIGNOF (gint32
);
5078 *align
= MONO_ABI_ALIGNOF (float);
5082 *align
= MONO_ABI_ALIGNOF (gint64
);
5085 *align
= MONO_ABI_ALIGNOF (double);
5089 *align
= MONO_ABI_ALIGNOF (gpointer
);
5090 return MONO_ABI_SIZEOF (gpointer
);
5091 case MONO_TYPE_VALUETYPE
: {
5092 if (m_class_is_enumtype (t
->data
.klass
))
5093 return mono_type_size (mono_class_enum_basetype_internal (t
->data
.klass
), align
);
5095 return mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
5097 case MONO_TYPE_STRING
:
5098 case MONO_TYPE_OBJECT
:
5099 case MONO_TYPE_CLASS
:
5100 case MONO_TYPE_SZARRAY
:
5102 case MONO_TYPE_FNPTR
:
5103 case MONO_TYPE_ARRAY
:
5104 *align
= MONO_ABI_ALIGNOF (gpointer
);
5105 return MONO_ABI_SIZEOF (gpointer
);
5106 case MONO_TYPE_TYPEDBYREF
:
5107 return mono_class_value_size (mono_defaults
.typed_reference_class
, (guint32
*)align
);
5108 case MONO_TYPE_GENERICINST
: {
5109 MonoGenericClass
*gclass
= t
->data
.generic_class
;
5110 MonoClass
*container_class
= gclass
->container_class
;
5112 // g_assert (!gclass->inst->is_open);
5114 if (m_class_is_valuetype (container_class
)) {
5115 if (m_class_is_enumtype (container_class
))
5116 return mono_type_size (mono_class_enum_basetype_internal (container_class
), align
);
5118 return mono_class_value_size (mono_class_from_mono_type_internal (t
), (guint32
*)align
);
5120 *align
= MONO_ABI_ALIGNOF (gpointer
);
5121 return MONO_ABI_SIZEOF (gpointer
);
5125 case MONO_TYPE_MVAR
:
5126 if (!t
->data
.generic_param
->gshared_constraint
|| t
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_VALUETYPE
) {
5127 *align
= MONO_ABI_ALIGNOF (gpointer
);
5128 return MONO_ABI_SIZEOF (gpointer
);
5130 /* The gparam can only match types given by gshared_constraint */
5131 return mono_type_size (t
->data
.generic_param
->gshared_constraint
, align
);
5135 g_error ("mono_type_size: type 0x%02x unknown", t
->type
);
5141 * mono_type_stack_size:
5142 * \param t the type to return the size it uses on the stack
5143 * \returns The number of bytes required to hold an instance of this
5144 * type on the runtime stack
5147 mono_type_stack_size (MonoType
*t
, int *align
)
5149 return mono_type_stack_size_internal (t
, align
, FALSE
);
5153 mono_type_stack_size_internal (MonoType
*t
, int *align
, gboolean allow_open
)
5156 MonoTypeEnum simple_type
;
5157 #if TARGET_SIZEOF_VOID_P == SIZEOF_REGISTER
5158 int stack_slot_size
= MONO_ABI_SIZEOF (gpointer
);
5159 int stack_slot_align
= MONO_ABI_ALIGNOF (gpointer
);
5160 #elif TARGET_SIZEOF_VOID_P < SIZEOF_REGISTER
5161 int stack_slot_size
= SIZEOF_REGISTER
;
5162 int stack_slot_align
= SIZEOF_REGISTER
;
5165 g_assert (t
!= NULL
);
5171 *align
= stack_slot_align
;
5172 return stack_slot_size
;
5175 simple_type
= t
->type
;
5176 switch (simple_type
) {
5177 case MONO_TYPE_BOOLEAN
:
5178 case MONO_TYPE_CHAR
:
5187 case MONO_TYPE_STRING
:
5188 case MONO_TYPE_OBJECT
:
5189 case MONO_TYPE_CLASS
:
5190 case MONO_TYPE_SZARRAY
:
5192 case MONO_TYPE_FNPTR
:
5193 case MONO_TYPE_ARRAY
:
5194 *align
= stack_slot_align
;
5195 return stack_slot_size
;
5197 case MONO_TYPE_MVAR
:
5198 g_assert (allow_open
);
5199 if (!t
->data
.generic_param
->gshared_constraint
|| t
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_VALUETYPE
) {
5200 *align
= stack_slot_align
;
5201 return stack_slot_size
;
5203 /* The gparam can only match types given by gshared_constraint */
5204 return mono_type_stack_size_internal (t
->data
.generic_param
->gshared_constraint
, align
, allow_open
);
5206 case MONO_TYPE_TYPEDBYREF
:
5207 *align
= stack_slot_align
;
5208 return stack_slot_size
* 3;
5210 *align
= MONO_ABI_ALIGNOF (float);
5211 return sizeof (float);
5214 *align
= MONO_ABI_ALIGNOF (gint64
);
5215 return sizeof (gint64
);
5217 *align
= MONO_ABI_ALIGNOF (double);
5218 return sizeof (double);
5219 case MONO_TYPE_VALUETYPE
: {
5222 if (m_class_is_enumtype (t
->data
.klass
))
5223 return mono_type_stack_size_internal (mono_class_enum_basetype_internal (t
->data
.klass
), align
, allow_open
);
5225 size
= mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
5227 *align
= *align
+ stack_slot_align
- 1;
5228 *align
&= ~(stack_slot_align
- 1);
5230 size
+= stack_slot_size
- 1;
5231 size
&= ~(stack_slot_size
- 1);
5236 case MONO_TYPE_GENERICINST
: {
5237 MonoGenericClass
*gclass
= t
->data
.generic_class
;
5238 MonoClass
*container_class
= gclass
->container_class
;
5241 g_assert (!gclass
->context
.class_inst
->is_open
);
5243 if (m_class_is_valuetype (container_class
)) {
5244 if (m_class_is_enumtype (container_class
))
5245 return mono_type_stack_size_internal (mono_class_enum_basetype_internal (container_class
), align
, allow_open
);
5247 guint32 size
= mono_class_value_size (mono_class_from_mono_type_internal (t
), (guint32
*)align
);
5249 *align
= *align
+ stack_slot_align
- 1;
5250 *align
&= ~(stack_slot_align
- 1);
5252 size
+= stack_slot_size
- 1;
5253 size
&= ~(stack_slot_size
- 1);
5258 *align
= stack_slot_align
;
5259 return stack_slot_size
;
5263 g_error ("type 0x%02x unknown", t
->type
);
5269 mono_type_generic_inst_is_valuetype (MonoType
*type
)
5271 g_assert (type
->type
== MONO_TYPE_GENERICINST
);
5272 return m_class_is_valuetype (type
->data
.generic_class
->container_class
);
5276 * mono_metadata_generic_class_is_valuetype:
5279 mono_metadata_generic_class_is_valuetype (MonoGenericClass
*gclass
)
5281 return m_class_is_valuetype (gclass
->container_class
);
5285 _mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
, gboolean signature_only
)
5287 MonoGenericInst
*i1
= g1
->context
.class_inst
;
5288 MonoGenericInst
*i2
= g2
->context
.class_inst
;
5290 if (g1
->is_dynamic
!= g2
->is_dynamic
)
5292 if (!mono_metadata_class_equal (g1
->container_class
, g2
->container_class
, signature_only
))
5294 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
5296 return g1
->is_tb_open
== g2
->is_tb_open
;
5300 _mono_metadata_generic_class_container_equal (const MonoGenericClass
*g1
, MonoClass
*c2
, gboolean signature_only
)
5302 MonoGenericInst
*i1
= g1
->context
.class_inst
;
5303 MonoGenericInst
*i2
= mono_class_get_generic_container (c2
)->context
.class_inst
;
5305 if (!mono_metadata_class_equal (g1
->container_class
, c2
, signature_only
))
5307 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
5309 return !g1
->is_tb_open
;
5313 mono_metadata_generic_context_hash (const MonoGenericContext
*context
)
5315 /* FIXME: check if this seed is good enough */
5316 guint hash
= 0xc01dfee7;
5317 if (context
->class_inst
)
5318 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->class_inst
);
5319 if (context
->method_inst
)
5320 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->method_inst
);
5325 mono_metadata_generic_context_equal (const MonoGenericContext
*g1
, const MonoGenericContext
*g2
)
5327 return g1
->class_inst
== g2
->class_inst
&& g1
->method_inst
== g2
->method_inst
;
5331 * mono_metadata_str_hash:
5333 * This should be used instead of g_str_hash for computing hash codes visible
5334 * outside this module, since g_str_hash () is not guaranteed to be stable
5335 * (its not the same in eglib for example).
5338 mono_metadata_str_hash (gconstpointer v1
)
5340 /* Same as g_str_hash () in glib */
5341 char *p
= (char *) v1
;
5346 hash
= (hash
<< 5) - hash
+ *p
;
5353 * mono_metadata_type_hash:
5355 * Computes a hash value for \p t1 to be used in \c GHashTable.
5356 * The returned hash is guaranteed to be the same across executions.
5359 mono_metadata_type_hash (MonoType
*t1
)
5361 guint hash
= t1
->type
;
5363 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
5365 case MONO_TYPE_VALUETYPE
:
5366 case MONO_TYPE_CLASS
:
5367 case MONO_TYPE_SZARRAY
: {
5368 MonoClass
*klass
= t1
->data
.klass
;
5370 * Dynamic classes must not be hashed on their type since it can change
5371 * during runtime. For example, if we hash a reference type that is
5372 * later made into a valuetype.
5374 * This is specially problematic with generic instances since they are
5375 * inserted in a bunch of hash tables before been finished.
5377 if (image_is_dynamic (m_class_get_image (klass
)))
5378 return (t1
->byref
<< 6) | mono_metadata_str_hash (m_class_get_name (klass
));
5379 return ((hash
<< 5) - hash
) ^ mono_metadata_str_hash (m_class_get_name (klass
));
5382 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (t1
->data
.type
);
5383 case MONO_TYPE_ARRAY
:
5384 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (m_class_get_byval_arg (t1
->data
.array
->eklass
));
5385 case MONO_TYPE_GENERICINST
:
5386 return ((hash
<< 5) - hash
) ^ mono_generic_class_hash (t1
->data
.generic_class
);
5388 case MONO_TYPE_MVAR
:
5389 return ((hash
<< 5) - hash
) ^ mono_metadata_generic_param_hash (t1
->data
.generic_param
);
5396 mono_metadata_generic_param_hash (MonoGenericParam
*p
)
5399 MonoGenericParamInfo
*info
;
5401 hash
= (mono_generic_param_num (p
) << 2);
5402 if (p
->gshared_constraint
)
5403 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (p
->gshared_constraint
);
5404 info
= mono_generic_param_info (p
);
5405 /* Can't hash on the owner klass/method, since those might not be set when this is called */
5406 if (!p
->owner
->is_anonymous
)
5407 hash
= ((hash
<< 5) - hash
) ^ info
->token
;
5412 mono_metadata_generic_param_equal_internal (MonoGenericParam
*p1
, MonoGenericParam
*p2
, gboolean signature_only
)
5416 if (mono_generic_param_num (p1
) != mono_generic_param_num (p2
))
5418 if (p1
->gshared_constraint
&& p2
->gshared_constraint
) {
5419 if (!mono_metadata_type_equal (p1
->gshared_constraint
, p2
->gshared_constraint
))
5422 if (p1
->gshared_constraint
!= p2
->gshared_constraint
)
5427 * We have to compare the image as well because if we didn't,
5428 * the generic_inst_cache lookup wouldn't care about the image
5429 * of generic params, so what could happen is that a generic
5430 * inst with params from image A is put into the cache, then
5431 * image B gets that generic inst from the cache, image A is
5432 * unloaded, so the inst is deleted, but image B still retains
5435 if (mono_generic_param_owner (p1
) == mono_generic_param_owner (p2
))
5439 * If `signature_only' is true, we're comparing two (method) signatures.
5440 * In this case, the owner of two type parameters doesn't need to match.
5443 return signature_only
;
5447 mono_metadata_generic_param_equal (MonoGenericParam
*p1
, MonoGenericParam
*p2
)
5449 return mono_metadata_generic_param_equal_internal (p1
, p2
, TRUE
);
5453 mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
)
5457 if (mono_class_is_ginst (c1
) && mono_class_is_ginst (c2
))
5458 return _mono_metadata_generic_class_equal (mono_class_get_generic_class (c1
), mono_class_get_generic_class (c2
), signature_only
);
5459 if (mono_class_is_ginst (c1
) && mono_class_is_gtd (c2
))
5460 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c1
), c2
, signature_only
);
5461 if (mono_class_is_gtd (c1
) && mono_class_is_ginst (c2
))
5462 return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c2
), c1
, signature_only
);
5463 MonoType
*c1_type
= m_class_get_byval_arg (c1
);
5464 MonoType
*c2_type
= m_class_get_byval_arg (c2
);
5465 if ((c1_type
->type
== MONO_TYPE_VAR
) && (c2_type
->type
== MONO_TYPE_VAR
))
5466 return mono_metadata_generic_param_equal_internal (
5467 c1_type
->data
.generic_param
, c2_type
->data
.generic_param
, signature_only
);
5468 if ((c1_type
->type
== MONO_TYPE_MVAR
) && (c2_type
->type
== MONO_TYPE_MVAR
))
5469 return mono_metadata_generic_param_equal_internal (
5470 c1_type
->data
.generic_param
, c2_type
->data
.generic_param
, signature_only
);
5471 if (signature_only
&&
5472 (c1_type
->type
== MONO_TYPE_SZARRAY
) && (c2_type
->type
== MONO_TYPE_SZARRAY
))
5473 return mono_metadata_class_equal (c1_type
->data
.klass
, c2_type
->data
.klass
, signature_only
);
5474 if (signature_only
&&
5475 (c1_type
->type
== MONO_TYPE_ARRAY
) && (c2_type
->type
== MONO_TYPE_ARRAY
))
5476 return do_mono_metadata_type_equal (c1_type
, c2_type
, signature_only
);
5481 mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
)
5483 gpointer iter1
= 0, iter2
= 0;
5487 if (s1
->call_convention
!= s2
->call_convention
)
5489 if (s1
->sentinelpos
!= s2
->sentinelpos
)
5491 if (s1
->hasthis
!= s2
->hasthis
)
5493 if (s1
->explicit_this
!= s2
->explicit_this
)
5495 if (! do_mono_metadata_type_equal (s1
->ret
, s2
->ret
, signature_only
))
5497 if (s1
->param_count
!= s2
->param_count
)
5501 MonoType
*t1
= mono_signature_get_params (s1
, &iter1
);
5502 MonoType
*t2
= mono_signature_get_params (s2
, &iter2
);
5504 if (t1
== NULL
|| t2
== NULL
)
5506 if (! do_mono_metadata_type_equal (t1
, t2
, signature_only
))
5512 * mono_metadata_type_equal:
5515 * @signature_only: If true, treat ginsts as equal which are instantiated separately but have equal positional value
5517 * Determine if @t1 and @t2 represent the same type.
5518 * Returns: #TRUE if @t1 and @t2 are equal.
5521 do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
5523 if (t1
->type
!= t2
->type
|| t1
->byref
!= t2
->byref
)
5526 gboolean cmod_reject
= FALSE
;
5528 gboolean is_pointer
= (t1
->type
== MONO_TYPE_PTR
);
5530 if (t1
->has_cmods
!= t2
->has_cmods
)
5532 else if (t1
->has_cmods
&& t2
->has_cmods
) {
5533 MonoCustomModContainer
*cm1
= mono_type_get_cmods (t1
);
5534 MonoCustomModContainer
*cm2
= mono_type_get_cmods (t2
);
5540 // The CLI itself shall treat required and optional modifiers in the same manner.
5541 // Two signatures that differ only by the addition of a custom modifier
5542 // (required or optional) shall not be considered to match.
5543 if (cm1
->count
!= cm2
->count
) {
5545 } else for (int i
=0; i
< cm1
->count
; i
++) {
5546 if (cm1
->modifiers
[i
].required
!= cm2
->modifiers
[i
].required
) {
5551 // FIXME: propagate error to caller
5553 MonoClass
*c1
= mono_class_get_checked (cm1
->image
, cm1
->modifiers
[i
].token
, error
);
5554 mono_error_assert_ok (error
);
5555 MonoClass
*c2
= mono_class_get_checked (cm2
->image
, cm2
->modifiers
[i
].token
, error
);
5556 mono_error_assert_ok (error
);
5565 gboolean result
= FALSE
;
5568 case MONO_TYPE_VOID
:
5569 case MONO_TYPE_BOOLEAN
:
5570 case MONO_TYPE_CHAR
:
5581 case MONO_TYPE_STRING
:
5584 case MONO_TYPE_OBJECT
:
5585 case MONO_TYPE_TYPEDBYREF
:
5588 case MONO_TYPE_VALUETYPE
:
5589 case MONO_TYPE_CLASS
:
5590 case MONO_TYPE_SZARRAY
:
5591 result
= mono_metadata_class_equal (t1
->data
.klass
, t2
->data
.klass
, signature_only
);
5594 result
= do_mono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
, signature_only
);
5596 case MONO_TYPE_ARRAY
:
5597 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
5600 result
= mono_metadata_class_equal (t1
->data
.array
->eklass
, t2
->data
.array
->eklass
, signature_only
);
5602 case MONO_TYPE_GENERICINST
:
5603 result
= _mono_metadata_generic_class_equal (
5604 t1
->data
.generic_class
, t2
->data
.generic_class
, signature_only
);
5607 result
= mono_metadata_generic_param_equal_internal (
5608 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
5610 case MONO_TYPE_MVAR
:
5611 result
= mono_metadata_generic_param_equal_internal (
5612 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
5614 case MONO_TYPE_FNPTR
:
5615 result
= mono_metadata_fnptr_equal (t1
->data
.method
, t2
->data
.method
, signature_only
);
5618 g_error ("implement type compare for %0x!", t1
->type
);
5622 if (cmod_reject
&& is_pointer
)
5629 * mono_metadata_type_equal:
5632 mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
5634 return do_mono_metadata_type_equal (t1
, t2
, FALSE
);
5638 * mono_metadata_type_equal_full:
5640 * \param t2 another type
5641 * \param signature_only if signature only comparison should be made
5643 * Determine if \p t1 and \p t2 are signature compatible if \p signature_only is TRUE, otherwise
5644 * behaves the same way as mono_metadata_type_equal.
5645 * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
5646 * \returns TRUE if \p t1 and \p t2 are equal taking \p signature_only into account.
5649 mono_metadata_type_equal_full (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
5651 return do_mono_metadata_type_equal (t1
, t2
, signature_only
);
5655 * mono_metadata_signature_equal:
5656 * \param sig1 a signature
5657 * \param sig2 another signature
5659 * Determine if \p sig1 and \p sig2 represent the same signature, with the
5660 * same number of arguments and the same types.
5661 * \returns TRUE if \p sig1 and \p sig2 are equal.
5664 mono_metadata_signature_equal (MonoMethodSignature
*sig1
, MonoMethodSignature
*sig2
)
5668 if (sig1
->hasthis
!= sig2
->hasthis
|| sig1
->param_count
!= sig2
->param_count
)
5671 if (sig1
->generic_param_count
!= sig2
->generic_param_count
)
5675 * We're just comparing the signatures of two methods here:
5677 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
5678 * U and V are equal here.
5680 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
5683 for (i
= 0; i
< sig1
->param_count
; i
++) {
5684 MonoType
*p1
= sig1
->params
[i
];
5685 MonoType
*p2
= sig2
->params
[i
];
5687 /* if (p1->attrs != p2->attrs)
5690 if (!do_mono_metadata_type_equal (p1
, p2
, TRUE
))
5694 if (!do_mono_metadata_type_equal (sig1
->ret
, sig2
->ret
, TRUE
))
5700 * mono_metadata_type_dup:
5701 * \param image image to alloc memory from
5702 * \param original type to duplicate
5703 * \returns copy of type allocated from the image's mempool (or from the heap, if \p image is null).
5706 mono_metadata_type_dup (MonoImage
*image
, const MonoType
*o
)
5708 return mono_metadata_type_dup_with_cmods (image
, o
, o
);
5712 * Works the same way as mono_metadata_type_dup but pick cmods from @cmods_source
5715 mono_metadata_type_dup_with_cmods (MonoImage
*image
, const MonoType
*o
, const MonoType
*cmods_source
)
5718 size_t sizeof_o
= mono_sizeof_type (cmods_source
);
5720 r
= image
? (MonoType
*)mono_image_alloc0 (image
, sizeof_o
) : (MonoType
*)g_malloc (sizeof_o
);
5722 if (cmods_source
->has_cmods
) {
5723 g_assert (!image
|| image
== mono_type_get_cmods (cmods_source
)->image
);
5724 memcpy (r
, cmods_source
, sizeof_o
);
5727 memcpy (r
, o
, sizeof (MonoType
));
5728 r
->has_cmods
= cmods_source
->has_cmods
;
5730 if (o
->type
== MONO_TYPE_PTR
) {
5731 r
->data
.type
= mono_metadata_type_dup (image
, o
->data
.type
);
5732 } else if (o
->type
== MONO_TYPE_ARRAY
) {
5733 r
->data
.array
= mono_dup_array_type (image
, o
->data
.array
);
5734 } else if (o
->type
== MONO_TYPE_FNPTR
) {
5735 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
5736 r
->data
.method
= mono_metadata_signature_deep_dup (image
, o
->data
.method
);
5742 * mono_signature_hash:
5745 mono_signature_hash (MonoMethodSignature
*sig
)
5747 guint i
, res
= sig
->ret
->type
;
5749 for (i
= 0; i
< sig
->param_count
; i
++)
5750 res
= (res
<< 5) - res
+ mono_type_hash (sig
->params
[i
]);
5756 * mono_metadata_encode_value:
5757 * @value: value to encode
5758 * @buf: buffer where to write the compressed representation
5759 * @endbuf: pointer updated to point at the end of the encoded output
5761 * Encodes the value @value in the compressed representation used
5762 * in metadata and stores the result in @buf. @buf needs to be big
5763 * enough to hold the data (4 bytes).
5766 mono_metadata_encode_value (guint32 value
, char *buf
, char **endbuf
)
5772 else if (value
< 0x4000) {
5773 p
[0] = 0x80 | (value
>> 8);
5774 p
[1] = value
& 0xff;
5777 p
[0] = (value
>> 24) | 0xc0;
5778 p
[1] = (value
>> 16) & 0xff;
5779 p
[2] = (value
>> 8) & 0xff;
5780 p
[3] = value
& 0xff;
5788 * mono_metadata_field_info:
5789 * \param meta the Image the field is defined in
5790 * \param index the index in the field table representing the field
5791 * \param offset a pointer to an integer where to store the offset that may have been specified for the field in a FieldLayout table
5792 * \param rva a pointer to the RVA of the field data in the image that may have been defined in a \c FieldRVA table
5793 * \param marshal_spec a pointer to the marshal spec that may have been defined for the field in a \c FieldMarshal table.
5795 * Gather info for field \p index that may have been defined in the \c FieldLayout,
5796 * \c FieldRVA and \c FieldMarshal tables.
5797 * Either of \p offset, \p rva and \p marshal_spec can be NULL if you're not interested
5801 mono_metadata_field_info (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5802 MonoMarshalSpec
**marshal_spec
)
5804 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, FALSE
);
5808 mono_metadata_field_info_with_mempool (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5809 MonoMarshalSpec
**marshal_spec
)
5811 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, TRUE
);
5815 mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5816 MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
)
5818 MonoTableInfo
*tdef
;
5821 loc
.idx
= index
+ 1;
5822 if (meta
->uncompressed_metadata
)
5823 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
5826 tdef
= &meta
->tables
[MONO_TABLE_FIELDLAYOUT
];
5828 loc
.col_idx
= MONO_FIELD_LAYOUT_FIELD
;
5831 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5832 *offset
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_LAYOUT_OFFSET
);
5834 *offset
= (guint32
)-1;
5838 tdef
= &meta
->tables
[MONO_TABLE_FIELDRVA
];
5840 loc
.col_idx
= MONO_FIELD_RVA_FIELD
;
5843 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5845 * LAMESPEC: There is no signature, no nothing, just the raw data.
5847 *rva
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_RVA_RVA
);
5855 if ((p
= mono_metadata_get_marshal_info (meta
, index
, TRUE
))) {
5856 *marshal_spec
= mono_metadata_parse_marshal_spec_full (alloc_from_image
? meta
: NULL
, meta
, p
);
5863 * mono_metadata_get_constant_index:
5864 * \param meta the Image the field is defined in
5865 * \param index the token that may have a row defined in the constants table
5866 * \param hint possible position for the row
5868 * \p token must be a \c FieldDef, \c ParamDef or \c PropertyDef token.
5870 * \returns the index into the \c Constants table or 0 if not found.
5873 mono_metadata_get_constant_index (MonoImage
*meta
, guint32 token
, guint32 hint
)
5875 MonoTableInfo
*tdef
;
5877 guint32 index
= mono_metadata_token_index (token
);
5879 tdef
= &meta
->tables
[MONO_TABLE_CONSTANT
];
5880 index
<<= MONO_HASCONSTANT_BITS
;
5881 switch (mono_metadata_token_table (token
)) {
5882 case MONO_TABLE_FIELD
:
5883 index
|= MONO_HASCONSTANT_FIEDDEF
;
5885 case MONO_TABLE_PARAM
:
5886 index
|= MONO_HASCONSTANT_PARAM
;
5888 case MONO_TABLE_PROPERTY
:
5889 index
|= MONO_HASCONSTANT_PROPERTY
;
5892 g_warning ("Not a valid token for the constant table: 0x%08x", token
);
5896 loc
.col_idx
= MONO_CONSTANT_PARENT
;
5899 /* FIXME: Index translation */
5901 if ((hint
> 0) && (hint
< tdef
->rows
) && (mono_metadata_decode_row_col (tdef
, hint
- 1, MONO_CONSTANT_PARENT
) == index
))
5904 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5905 return loc
.result
+ 1;
5911 * mono_metadata_events_from_typedef:
5912 * \param meta metadata context
5913 * \param index 0-based index (in the \c TypeDef table) describing a type
5914 * \returns the 0-based index in the \c Event table for the events in the
5915 * type. The last event that belongs to the type (plus 1) is stored
5916 * in the \p end_idx pointer.
5919 mono_metadata_events_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5923 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_EVENTMAP
];
5931 loc
.col_idx
= MONO_EVENT_MAP_PARENT
;
5932 loc
.idx
= index
+ 1;
5934 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5937 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_EVENT_MAP_EVENTLIST
);
5938 if (loc
.result
+ 1 < tdef
->rows
) {
5939 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_EVENT_MAP_EVENTLIST
) - 1;
5941 end
= meta
->tables
[MONO_TABLE_EVENT
].rows
;
5949 * mono_metadata_methods_from_event:
5950 * \param meta metadata context
5951 * \param index 0-based index (in the \c Event table) describing a event
5952 * \returns the 0-based index in the \c MethodDef table for the methods in the
5953 * event. The last method that belongs to the event (plus 1) is stored
5954 * in the \p end_idx pointer.
5957 mono_metadata_methods_from_event (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5961 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
5962 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
5968 if (meta
->uncompressed_metadata
)
5969 index
= search_ptr_table (meta
, MONO_TABLE_EVENT_POINTER
, index
+ 1) - 1;
5972 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
5973 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
; /* Method association coded index */
5975 if (!mono_binary_search (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
5980 * We may end up in the middle of the rows...
5983 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
5989 while (end
< msemt
->rows
) {
5990 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
5991 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
6000 * mono_metadata_properties_from_typedef:
6001 * \param meta metadata context
6002 * \param index 0-based index (in the \c TypeDef table) describing a type
6003 * \returns the 0-based index in the \c Property table for the properties in the
6004 * type. The last property that belongs to the type (plus 1) is stored
6005 * in the \p end_idx pointer.
6008 mono_metadata_properties_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
6012 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_PROPERTYMAP
];
6020 loc
.col_idx
= MONO_PROPERTY_MAP_PARENT
;
6021 loc
.idx
= index
+ 1;
6023 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6026 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_PROPERTY_MAP_PROPERTY_LIST
);
6027 if (loc
.result
+ 1 < tdef
->rows
) {
6028 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_PROPERTY_MAP_PROPERTY_LIST
) - 1;
6030 end
= meta
->tables
[MONO_TABLE_PROPERTY
].rows
;
6038 * mono_metadata_methods_from_property:
6039 * \param meta metadata context
6040 * \param index 0-based index (in the \c PropertyDef table) describing a property
6041 * \returns the 0-based index in the \c MethodDef table for the methods in the
6042 * property. The last method that belongs to the property (plus 1) is stored
6043 * in the \p end_idx pointer.
6046 mono_metadata_methods_from_property (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
6050 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
6051 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
6057 if (meta
->uncompressed_metadata
)
6058 index
= search_ptr_table (meta
, MONO_TABLE_PROPERTY_POINTER
, index
+ 1) - 1;
6061 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
6062 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
; /* Method association coded index */
6064 if (!mono_binary_search (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
6069 * We may end up in the middle of the rows...
6072 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
6078 while (end
< msemt
->rows
) {
6079 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
6080 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
6089 * mono_metadata_implmap_from_method:
6092 mono_metadata_implmap_from_method (MonoImage
*meta
, guint32 method_idx
)
6095 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_IMPLMAP
];
6100 /* No index translation seems to be needed */
6103 loc
.col_idx
= MONO_IMPLMAP_MEMBER
;
6104 loc
.idx
= ((method_idx
+ 1) << MONO_MEMBERFORWD_BITS
) | MONO_MEMBERFORWD_METHODDEF
;
6106 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6109 return loc
.result
+ 1;
6113 * mono_type_create_from_typespec:
6114 * \param image context where the image is created
6115 * \param type_spec typespec token
6116 * \deprecated use \c mono_type_create_from_typespec_checked that has proper error handling
6118 * Creates a \c MonoType representing the \c TypeSpec indexed by the \p type_spec
6122 mono_type_create_from_typespec (MonoImage
*image
, guint32 type_spec
)
6125 MonoType
*type
= mono_type_create_from_typespec_checked (image
, type_spec
, error
);
6127 g_error ("Could not create typespec %x due to %s", type_spec
, mono_error_get_message (error
));
6132 mono_type_create_from_typespec_checked (MonoImage
*image
, guint32 type_spec
, MonoError
*error
)
6135 guint32 idx
= mono_metadata_token_index (type_spec
);
6137 guint32 cols
[MONO_TYPESPEC_SIZE
];
6139 MonoType
*type
, *type2
;
6143 type
= (MonoType
*)mono_conc_hashtable_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
6147 t
= &image
->tables
[MONO_TABLE_TYPESPEC
];
6149 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPESPEC_SIZE
);
6150 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_TYPESPEC_SIGNATURE
]);
6152 if (!mono_verifier_verify_typespec_signature (image
, cols
[MONO_TYPESPEC_SIGNATURE
], type_spec
, error
))
6155 mono_metadata_decode_value (ptr
, &ptr
);
6157 type
= mono_metadata_parse_type_checked (image
, NULL
, 0, TRUE
, ptr
, &ptr
, error
);
6161 type2
= mono_metadata_type_dup (image
, type
);
6162 mono_metadata_free_type (type
);
6164 mono_image_lock (image
);
6166 /* We might leak some data in the image mempool if found */
6167 type
= (MonoType
*)mono_conc_hashtable_insert (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
), type2
);
6171 mono_image_unlock (image
);
6178 mono_image_strndup (MonoImage
*image
, const char *data
, guint len
)
6182 return g_strndup (data
, len
);
6183 res
= (char *)mono_image_alloc (image
, len
+ 1);
6184 memcpy (res
, data
, len
);
6190 * mono_metadata_parse_marshal_spec:
6193 mono_metadata_parse_marshal_spec (MonoImage
*image
, const char *ptr
)
6195 return mono_metadata_parse_marshal_spec_full (NULL
, image
, ptr
);
6199 * If IMAGE is non-null, memory will be allocated from its mempool, otherwise it will be allocated using malloc.
6200 * PARENT_IMAGE is the image containing the marshal spec.
6203 mono_metadata_parse_marshal_spec_full (MonoImage
*image
, MonoImage
*parent_image
, const char *ptr
)
6205 MonoMarshalSpec
*res
;
6207 const char *start
= ptr
;
6209 /* fixme: this is incomplete, but I cant find more infos in the specs */
6212 res
= (MonoMarshalSpec
*)mono_image_alloc0 (image
, sizeof (MonoMarshalSpec
));
6214 res
= g_new0 (MonoMarshalSpec
, 1);
6216 len
= mono_metadata_decode_value (ptr
, &ptr
);
6217 res
->native
= (MonoMarshalNative
)*ptr
++;
6219 if (res
->native
== MONO_NATIVE_LPARRAY
) {
6220 res
->data
.array_data
.param_num
= -1;
6221 res
->data
.array_data
.num_elem
= -1;
6222 res
->data
.array_data
.elem_mult
= -1;
6224 if (ptr
- start
<= len
)
6225 res
->data
.array_data
.elem_type
= (MonoMarshalNative
)*ptr
++;
6226 if (ptr
- start
<= len
)
6227 res
->data
.array_data
.param_num
= mono_metadata_decode_value (ptr
, &ptr
);
6228 if (ptr
- start
<= len
)
6229 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
6230 if (ptr
- start
<= len
) {
6232 * LAMESPEC: Older spec versions say this parameter comes before
6233 * num_elem. Never spec versions don't talk about elem_mult at
6234 * all, but csc still emits it, and it is used to distinguish
6235 * between param_num being 0, and param_num being omitted.
6236 * So if (param_num == 0) && (num_elem > 0), then
6237 * elem_mult == 0 -> the array size is num_elem
6238 * elem_mult == 1 -> the array size is @param_num + num_elem
6240 res
->data
.array_data
.elem_mult
= mono_metadata_decode_value (ptr
, &ptr
);
6244 if (res
->native
== MONO_NATIVE_BYVALTSTR
) {
6245 if (ptr
- start
<= len
)
6246 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
6249 if (res
->native
== MONO_NATIVE_BYVALARRAY
) {
6250 if (ptr
- start
<= len
)
6251 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
6254 if (res
->native
== MONO_NATIVE_CUSTOM
) {
6255 /* skip unused type guid */
6256 len
= mono_metadata_decode_value (ptr
, &ptr
);
6258 /* skip unused native type name */
6259 len
= mono_metadata_decode_value (ptr
, &ptr
);
6261 /* read custom marshaler type name */
6262 len
= mono_metadata_decode_value (ptr
, &ptr
);
6263 res
->data
.custom_data
.custom_name
= mono_image_strndup (image
, ptr
, len
);
6265 /* read cookie string */
6266 len
= mono_metadata_decode_value (ptr
, &ptr
);
6267 res
->data
.custom_data
.cookie
= mono_image_strndup (image
, ptr
, len
);
6268 res
->data
.custom_data
.image
= parent_image
;
6271 if (res
->native
== MONO_NATIVE_SAFEARRAY
) {
6272 res
->data
.safearray_data
.elem_type
= (MonoMarshalVariant
)0;
6273 res
->data
.safearray_data
.num_elem
= 0;
6274 if (ptr
- start
<= len
)
6275 res
->data
.safearray_data
.elem_type
= (MonoMarshalVariant
)*ptr
++;
6276 if (ptr
- start
<= len
)
6277 res
->data
.safearray_data
.num_elem
= *ptr
++;
6283 * mono_metadata_free_marshal_spec:
6286 mono_metadata_free_marshal_spec (MonoMarshalSpec
*spec
)
6291 if (spec
->native
== MONO_NATIVE_CUSTOM
) {
6292 g_free (spec
->data
.custom_data
.custom_name
);
6293 g_free (spec
->data
.custom_data
.cookie
);
6299 * mono_type_to_unmanaged:
6300 * The value pointed to by \p conv will contain the kind of marshalling required for this
6301 * particular type one of the \c MONO_MARSHAL_CONV_ enumeration values.
6302 * \returns A \c MonoMarshalNative enumeration value (<code>MONO_NATIVE_</code>) value
6303 * describing the underlying native reprensetation of the type.
6305 guint32
// FIXMEcxx MonoMarshalNative
6306 mono_type_to_unmanaged (MonoType
*type
, MonoMarshalSpec
*mspec
, gboolean as_field
,
6307 gboolean unicode
, MonoMarshalConv
*conv
)
6309 MonoMarshalConv dummy_conv
;
6315 *conv
= MONO_MARSHAL_CONV_NONE
;
6318 return MONO_NATIVE_UINT
;
6322 case MONO_TYPE_BOOLEAN
:
6324 switch (mspec
->native
) {
6325 case MONO_NATIVE_VARIANTBOOL
:
6326 *conv
= MONO_MARSHAL_CONV_BOOL_VARIANTBOOL
;
6327 return MONO_NATIVE_VARIANTBOOL
;
6328 case MONO_NATIVE_BOOLEAN
:
6329 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
6330 return MONO_NATIVE_BOOLEAN
;
6331 case MONO_NATIVE_I1
:
6332 case MONO_NATIVE_U1
:
6333 return mspec
->native
;
6335 g_error ("cant marshal bool to native type %02x", mspec
->native
);
6338 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
6339 return MONO_NATIVE_BOOLEAN
;
6340 case MONO_TYPE_CHAR
:
6342 switch (mspec
->native
) {
6343 case MONO_NATIVE_U2
:
6344 case MONO_NATIVE_U1
:
6345 return mspec
->native
;
6347 g_error ("cant marshal char to native type %02x", mspec
->native
);
6350 return unicode
? MONO_NATIVE_U2
: MONO_NATIVE_U1
;
6351 case MONO_TYPE_I1
: return MONO_NATIVE_I1
;
6352 case MONO_TYPE_U1
: return MONO_NATIVE_U1
;
6353 case MONO_TYPE_I2
: return MONO_NATIVE_I2
;
6354 case MONO_TYPE_U2
: return MONO_NATIVE_U2
;
6355 case MONO_TYPE_I4
: return MONO_NATIVE_I4
;
6356 case MONO_TYPE_U4
: return MONO_NATIVE_U4
;
6357 case MONO_TYPE_I8
: return MONO_NATIVE_I8
;
6358 case MONO_TYPE_U8
: return MONO_NATIVE_U8
;
6359 case MONO_TYPE_R4
: return MONO_NATIVE_R4
;
6360 case MONO_TYPE_R8
: return MONO_NATIVE_R8
;
6361 case MONO_TYPE_STRING
:
6363 switch (mspec
->native
) {
6364 case MONO_NATIVE_BSTR
:
6365 *conv
= MONO_MARSHAL_CONV_STR_BSTR
;
6366 return MONO_NATIVE_BSTR
;
6367 case MONO_NATIVE_LPSTR
:
6368 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
6369 return MONO_NATIVE_LPSTR
;
6370 case MONO_NATIVE_LPWSTR
:
6371 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
6372 return MONO_NATIVE_LPWSTR
;
6373 case MONO_NATIVE_LPTSTR
:
6374 *conv
= MONO_MARSHAL_CONV_STR_LPTSTR
;
6375 return MONO_NATIVE_LPTSTR
;
6376 case MONO_NATIVE_ANSIBSTR
:
6377 *conv
= MONO_MARSHAL_CONV_STR_ANSIBSTR
;
6378 return MONO_NATIVE_ANSIBSTR
;
6379 case MONO_NATIVE_TBSTR
:
6380 *conv
= MONO_MARSHAL_CONV_STR_TBSTR
;
6381 return MONO_NATIVE_TBSTR
;
6382 case MONO_NATIVE_UTF8STR
:
6383 *conv
= MONO_MARSHAL_CONV_STR_UTF8STR
;
6384 return MONO_NATIVE_UTF8STR
;
6385 case MONO_NATIVE_BYVALTSTR
:
6387 *conv
= MONO_MARSHAL_CONV_STR_BYVALWSTR
;
6389 *conv
= MONO_MARSHAL_CONV_STR_BYVALSTR
;
6390 return MONO_NATIVE_BYVALTSTR
;
6392 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
);
6396 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
6397 return MONO_NATIVE_LPWSTR
;
6400 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
6401 return MONO_NATIVE_LPSTR
;
6403 case MONO_TYPE_PTR
: return MONO_NATIVE_UINT
;
6404 case MONO_TYPE_VALUETYPE
: /*FIXME*/
6405 if (m_class_is_enumtype (type
->data
.klass
)) {
6406 t
= mono_class_enum_basetype_internal (type
->data
.klass
)->type
;
6409 if (type
->data
.klass
== mono_class_try_get_handleref_class ()){
6410 *conv
= MONO_MARSHAL_CONV_HANDLEREF
;
6411 return MONO_NATIVE_INT
;
6413 return MONO_NATIVE_STRUCT
;
6414 case MONO_TYPE_SZARRAY
:
6415 case MONO_TYPE_ARRAY
:
6417 switch (mspec
->native
) {
6418 case MONO_NATIVE_BYVALARRAY
:
6419 if ((m_class_get_element_class (type
->data
.klass
) == mono_defaults
.char_class
) && !unicode
)
6420 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY
;
6422 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALARRAY
;
6423 return MONO_NATIVE_BYVALARRAY
;
6424 case MONO_NATIVE_SAFEARRAY
:
6425 *conv
= MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
;
6426 return MONO_NATIVE_SAFEARRAY
;
6427 case MONO_NATIVE_LPARRAY
:
6428 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
6429 return MONO_NATIVE_LPARRAY
;
6431 g_error ("cant marshal array as native type %02x", mspec
->native
);
6435 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
6436 return MONO_NATIVE_LPARRAY
;
6437 case MONO_TYPE_I
: return MONO_NATIVE_INT
;
6438 case MONO_TYPE_U
: return MONO_NATIVE_UINT
;
6439 case MONO_TYPE_CLASS
:
6440 case MONO_TYPE_OBJECT
: {
6441 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
6443 switch (mspec
->native
) {
6444 case MONO_NATIVE_STRUCT
:
6445 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
6446 return MONO_NATIVE_STRUCT
;
6447 case MONO_NATIVE_CUSTOM
:
6448 return MONO_NATIVE_CUSTOM
;
6449 case MONO_NATIVE_INTERFACE
:
6450 *conv
= MONO_MARSHAL_CONV_OBJECT_INTERFACE
;
6451 return MONO_NATIVE_INTERFACE
;
6452 case MONO_NATIVE_IDISPATCH
:
6453 *conv
= MONO_MARSHAL_CONV_OBJECT_IDISPATCH
;
6454 return MONO_NATIVE_IDISPATCH
;
6455 case MONO_NATIVE_IUNKNOWN
:
6456 *conv
= MONO_MARSHAL_CONV_OBJECT_IUNKNOWN
;
6457 return MONO_NATIVE_IUNKNOWN
;
6458 case MONO_NATIVE_FUNC
:
6459 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
6460 type
->data
.klass
== mono_defaults
.delegate_class
||
6461 m_class_get_parent (type
->data
.klass
) == mono_defaults
.multicastdelegate_class
)) {
6462 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
6463 return MONO_NATIVE_FUNC
;
6467 g_error ("cant marshal object as native type %02x", mspec
->native
);
6470 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
6471 type
->data
.klass
== mono_defaults
.delegate_class
||
6472 m_class_get_parent (type
->data
.klass
) == mono_defaults
.multicastdelegate_class
)) {
6473 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
6474 return MONO_NATIVE_FUNC
;
6476 if (mono_class_try_get_safehandle_class () && type
->data
.klass
== mono_class_try_get_safehandle_class ()){
6477 *conv
= MONO_MARSHAL_CONV_SAFEHANDLE
;
6478 return MONO_NATIVE_INT
;
6480 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
6481 return MONO_NATIVE_STRUCT
;
6483 case MONO_TYPE_FNPTR
: return MONO_NATIVE_FUNC
;
6484 case MONO_TYPE_GENERICINST
:
6485 type
= m_class_get_byval_arg (type
->data
.generic_class
->container_class
);
6488 case MONO_TYPE_TYPEDBYREF
:
6490 g_error ("type 0x%02x not handled in marshal", t
);
6492 return MONO_NATIVE_MAX
;
6496 * mono_metadata_get_marshal_info:
6499 mono_metadata_get_marshal_info (MonoImage
*meta
, guint32 idx
, gboolean is_field
)
6502 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_FIELDMARSHAL
];
6508 loc
.col_idx
= MONO_FIELD_MARSHAL_PARENT
;
6509 loc
.idx
= ((idx
+ 1) << MONO_HAS_FIELD_MARSHAL_BITS
) | (is_field
? MONO_HAS_FIELD_MARSHAL_FIELDSREF
: MONO_HAS_FIELD_MARSHAL_PARAMDEF
);
6511 /* FIXME: Index translation */
6513 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6516 return mono_metadata_blob_heap (meta
, mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_MARSHAL_NATIVE_TYPE
));
6520 mono_method_from_method_def_or_ref (MonoImage
*m
, guint32 tok
, MonoGenericContext
*context
, MonoError
*error
)
6522 MonoMethod
*result
= NULL
;
6523 guint32 idx
= tok
>> MONO_METHODDEFORREF_BITS
;
6527 switch (tok
& MONO_METHODDEFORREF_MASK
) {
6528 case MONO_METHODDEFORREF_METHODDEF
:
6529 result
= mono_get_method_checked (m
, MONO_TOKEN_METHOD_DEF
| idx
, NULL
, context
, error
);
6531 case MONO_METHODDEFORREF_METHODREF
:
6532 result
= mono_get_method_checked (m
, MONO_TOKEN_MEMBER_REF
| idx
, NULL
, context
, error
);
6535 mono_error_set_bad_image (error
, m
, "Invalid MethodDefOfRef token %x", tok
);
6542 * mono_class_get_overrides_full:
6544 * Compute the method overrides belonging to class @type_token in @overrides, and the number of overrides in @num_overrides.
6548 mono_class_get_overrides_full (MonoImage
*image
, guint32 type_token
, MonoMethod
***overrides
, gint32
*num_overrides
, MonoGenericContext
*generic_context
, MonoError
*error
)
6551 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_METHODIMPL
];
6554 guint32 cols
[MONO_METHODIMPL_SIZE
];
6555 MonoMethod
**result
;
6567 loc
.col_idx
= MONO_METHODIMPL_CLASS
;
6568 loc
.idx
= mono_metadata_token_index (type_token
);
6570 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6576 * We may end up in the middle of the rows...
6579 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_METHODIMPL_CLASS
))
6584 while (end
< tdef
->rows
) {
6585 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, end
, MONO_METHODIMPL_CLASS
))
6591 result
= g_new (MonoMethod
*, num
* 2);
6592 for (i
= 0; i
< num
; ++i
) {
6595 if (!mono_verifier_verify_methodimpl_row (image
, start
+ i
, error
))
6598 mono_metadata_decode_row (tdef
, start
+ i
, cols
, MONO_METHODIMPL_SIZE
);
6599 method
= mono_method_from_method_def_or_ref (image
, cols
[MONO_METHODIMPL_DECLARATION
], generic_context
, error
);
6603 result
[i
* 2] = method
;
6604 method
= mono_method_from_method_def_or_ref (image
, cols
[MONO_METHODIMPL_BODY
], generic_context
, error
);
6608 result
[i
* 2 + 1] = method
;
6611 if (!is_ok (error
)) {
6617 *overrides
= result
;
6619 *num_overrides
= num
;
6624 * mono_guid_to_string:
6626 * Converts a 16 byte Microsoft GUID to the standard string representation.
6629 mono_guid_to_string (const guint8
*guid
)
6631 return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
6632 guid
[3], guid
[2], guid
[1], guid
[0],
6636 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
6640 * mono_guid_to_string_minimal:
6642 * Converts a 16 byte Microsoft GUID to lower case no '-' representation..
6645 mono_guid_to_string_minimal (const guint8
*guid
)
6647 return g_strdup_printf ("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
6648 guid
[3], guid
[2], guid
[1], guid
[0],
6652 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
6655 get_constraints (MonoImage
*image
, int owner
, MonoClass
***constraints
, MonoGenericContainer
*container
, MonoError
*error
)
6657 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
6658 guint32 cols
[MONO_GENPARCONSTRAINT_SIZE
];
6659 guint32 i
, token
, found
;
6660 MonoClass
*klass
, **res
;
6661 GSList
*cons
= NULL
, *tmp
;
6662 MonoGenericContext
*context
= &container
->context
;
6666 *constraints
= NULL
;
6668 for (i
= 0; i
< tdef
->rows
; ++i
) {
6669 mono_metadata_decode_row (tdef
, i
, cols
, MONO_GENPARCONSTRAINT_SIZE
);
6670 if (cols
[MONO_GENPARCONSTRAINT_GENERICPAR
] == owner
) {
6671 token
= mono_metadata_token_from_dor (cols
[MONO_GENPARCONSTRAINT_CONSTRAINT
]);
6672 klass
= mono_class_get_and_inflate_typespec_checked (image
, token
, context
, error
);
6674 g_slist_free (cons
);
6677 cons
= g_slist_append (cons
, klass
);
6680 /* contiguous list finished */
6687 res
= (MonoClass
**)mono_image_alloc0 (image
, sizeof (MonoClass
*) * (found
+ 1));
6688 for (i
= 0, tmp
= cons
; i
< found
; ++i
, tmp
= tmp
->next
) {
6689 res
[i
] = (MonoClass
*)tmp
->data
;
6691 g_slist_free (cons
);
6697 * mono_metadata_get_generic_param_row:
6700 * @token: TypeOrMethodDef token, owner for GenericParam
6701 * @owner: coded token, set on return
6703 * Returns: 1-based row-id in the GenericParam table whose
6704 * owner is @token. 0 if not found.
6707 mono_metadata_get_generic_param_row (MonoImage
*image
, guint32 token
, guint32
*owner
)
6709 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
6716 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPEDEF
)
6717 *owner
= MONO_TYPEORMETHOD_TYPE
;
6718 else if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
6719 *owner
= MONO_TYPEORMETHOD_METHOD
;
6721 g_error ("wrong token %x to get_generic_param_row", token
);
6724 *owner
|= mono_metadata_token_index (token
) << MONO_TYPEORMETHOD_BITS
;
6727 loc
.col_idx
= MONO_GENERICPARAM_OWNER
;
6730 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6733 /* Find the first entry by searching backwards */
6734 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_GENERICPARAM_OWNER
) == loc
.idx
))
6737 return loc
.result
+ 1;
6741 mono_metadata_has_generic_params (MonoImage
*image
, guint32 token
)
6744 return mono_metadata_get_generic_param_row (image
, token
, &owner
);
6748 * Memory is allocated from IMAGE's mempool.
6751 mono_metadata_load_generic_param_constraints_checked (MonoImage
*image
, guint32 token
,
6752 MonoGenericContainer
*container
, MonoError
*error
)
6755 guint32 start_row
, i
, owner
;
6758 if (! (start_row
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
6760 for (i
= 0; i
< container
->type_argc
; i
++) {
6761 if (!get_constraints (image
, start_row
+ i
, &mono_generic_container_get_param_info (container
, i
)->constraints
, container
, error
)) {
6769 * mono_metadata_load_generic_params:
6771 * Load the type parameters from the type or method definition @token.
6773 * Use this method after parsing a type or method definition to figure out whether it's a generic
6774 * type / method. When parsing a method definition, @parent_container points to the generic container
6775 * of the current class, if any.
6777 * Note: This method does not load the constraints: for typedefs, this has to be done after fully
6778 * creating the type.
6780 * Returns: NULL if @token is not a generic type or method definition or the new generic container.
6782 * LOCKING: Acquires the loader lock
6785 MonoGenericContainer
*
6786 mono_metadata_load_generic_params (MonoImage
*image
, guint32 token
, MonoGenericContainer
*parent_container
, gpointer real_owner
)
6788 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
6789 guint32 cols
[MONO_GENERICPARAM_SIZE
];
6790 guint32 i
, owner
= 0, n
;
6791 MonoGenericContainer
*container
;
6792 MonoGenericParamFull
*params
;
6793 MonoGenericContext
*context
;
6794 gboolean is_method
= mono_metadata_token_table (token
) == MONO_TABLE_METHOD
;
6795 gboolean is_anonymous
= real_owner
== NULL
;
6797 if (!(i
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
6799 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
6802 container
= (MonoGenericContainer
*)mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
6803 container
->is_anonymous
= is_anonymous
;
6805 container
->owner
.image
= image
;
6808 container
->owner
.method
= (MonoMethod
*)real_owner
;
6810 container
->owner
.klass
= (MonoClass
*)real_owner
;
6814 params
= (MonoGenericParamFull
*)g_realloc (params
, sizeof (MonoGenericParamFull
) * n
);
6815 memset (¶ms
[n
- 1], 0, sizeof (MonoGenericParamFull
));
6816 params
[n
- 1].owner
= container
;
6817 params
[n
- 1].num
= cols
[MONO_GENERICPARAM_NUMBER
];
6818 params
[n
- 1].info
.token
= i
| MONO_TOKEN_GENERIC_PARAM
;
6819 params
[n
- 1].info
.flags
= cols
[MONO_GENERICPARAM_FLAGS
];
6820 params
[n
- 1].info
.name
= mono_metadata_string_heap (image
, cols
[MONO_GENERICPARAM_NAME
]);
6821 if (params
[n
- 1].num
!= n
- 1)
6822 g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i
);
6823 if (++i
> tdef
->rows
)
6825 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
6826 } while (cols
[MONO_GENERICPARAM_OWNER
] == owner
);
6828 container
->type_argc
= n
;
6829 container
->type_params
= (MonoGenericParamFull
*)mono_image_alloc0 (image
, sizeof (MonoGenericParamFull
) * n
);
6830 memcpy (container
->type_params
, params
, sizeof (MonoGenericParamFull
) * n
);
6832 container
->parent
= parent_container
;
6835 container
->is_method
= 1;
6837 g_assert (container
->parent
== NULL
|| container
->is_method
);
6839 context
= &container
->context
;
6840 if (container
->is_method
) {
6841 context
->class_inst
= container
->parent
? container
->parent
->context
.class_inst
: NULL
;
6842 context
->method_inst
= mono_get_shared_generic_inst (container
);
6844 context
->class_inst
= mono_get_shared_generic_inst (container
);
6851 mono_get_shared_generic_inst (MonoGenericContainer
*container
)
6853 MonoType
**type_argv
;
6855 MonoGenericInst
*nginst
;
6858 type_argv
= g_new0 (MonoType
*, container
->type_argc
);
6859 helper
= g_new0 (MonoType
, container
->type_argc
);
6861 for (i
= 0; i
< container
->type_argc
; i
++) {
6862 MonoType
*t
= &helper
[i
];
6864 t
->type
= container
->is_method
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
6865 t
->data
.generic_param
= mono_generic_container_get_param (container
, i
);
6870 nginst
= mono_metadata_get_generic_inst (container
->type_argc
, type_argv
);
6879 * mono_type_is_byref:
6880 * \param type the \c MonoType operated on
6881 * \returns TRUE if \p type represents a type passed by reference,
6885 mono_type_is_byref (MonoType
*type
)
6888 MONO_ENTER_GC_UNSAFE
;
6889 result
= type
->byref
;
6890 MONO_EXIT_GC_UNSAFE
;
6895 * mono_type_get_type:
6896 * \param type the \c MonoType operated on
6897 * \returns the IL type value for \p type. This is one of the \c MonoTypeEnum
6898 * enum members like \c MONO_TYPE_I4 or \c MONO_TYPE_STRING.
6901 mono_type_get_type (MonoType
*type
)
6907 * mono_type_get_signature:
6908 * \param type the \c MonoType operated on
6909 * It is only valid to call this function if \p type is a \c MONO_TYPE_FNPTR .
6910 * \returns the \c MonoMethodSignature pointer that describes the signature
6911 * of the function pointer \p type represents.
6913 MonoMethodSignature
*
6914 mono_type_get_signature (MonoType
*type
)
6916 g_assert (type
->type
== MONO_TYPE_FNPTR
);
6917 return type
->data
.method
;
6921 * mono_type_get_class:
6922 * \param type the \c MonoType operated on
6923 * It is only valid to call this function if \p type is a \c MONO_TYPE_CLASS or a
6924 * \c MONO_TYPE_VALUETYPE . For more general functionality, use \c mono_class_from_mono_type_internal,
6926 * \returns the \c MonoClass pointer that describes the class that \p type represents.
6929 mono_type_get_class (MonoType
*type
)
6931 /* FIXME: review the runtime users before adding the assert here */
6932 return type
->data
.klass
;
6936 * mono_type_get_array_type:
6937 * \param type the \c MonoType operated on
6938 * It is only valid to call this function if \p type is a \c MONO_TYPE_ARRAY .
6939 * \returns a \c MonoArrayType struct describing the array type that \p type
6940 * represents. The info includes details such as rank, array element type
6941 * and the sizes and bounds of multidimensional arrays.
6944 mono_type_get_array_type (MonoType
*type
)
6946 return type
->data
.array
;
6950 * mono_type_get_ptr_type:
6951 * \pararm type the \c MonoType operated on
6952 * It is only valid to call this function if \p type is a \c MONO_TYPE_PTR .
6953 * \returns the \c MonoType pointer that describes the type that \p type
6954 * represents a pointer to.
6957 mono_type_get_ptr_type (MonoType
*type
)
6959 g_assert (type
->type
== MONO_TYPE_PTR
);
6960 return type
->data
.type
;
6964 * mono_type_get_modifiers:
6967 mono_type_get_modifiers (MonoType
*type
, gboolean
*is_required
, gpointer
*iter
)
6969 /* FIXME: implement */
6974 * mono_type_is_struct:
6975 * \param type the \c MonoType operated on
6976 * \returns TRUE if \p type is a struct, that is a \c ValueType but not an enum
6977 * or a basic type like \c System.Int32 . FALSE otherwise.
6980 mono_type_is_struct (MonoType
*type
)
6982 return (!type
->byref
&& ((type
->type
== MONO_TYPE_VALUETYPE
&&
6983 !m_class_is_enumtype (type
->data
.klass
)) || (type
->type
== MONO_TYPE_TYPEDBYREF
) ||
6984 ((type
->type
== MONO_TYPE_GENERICINST
) &&
6985 mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
) &&
6986 !m_class_is_enumtype (type
->data
.generic_class
->container_class
))));
6990 * mono_type_is_void:
6991 * \param type the \c MonoType operated on
6992 * \returns TRUE if \p type is \c System.Void . FALSE otherwise.
6995 mono_type_is_void (MonoType
*type
)
6997 return (type
&& (type
->type
== MONO_TYPE_VOID
) && !type
->byref
);
7001 * mono_type_is_pointer:
7002 * \param type the \c MonoType operated on
7003 * \returns TRUE if \p type is a managed or unmanaged pointer type. FALSE otherwise.
7006 mono_type_is_pointer (MonoType
*type
)
7008 return (type
&& ((type
->byref
|| (type
->type
== MONO_TYPE_I
) || type
->type
== MONO_TYPE_STRING
)
7009 || (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
7010 (type
->type
== MONO_TYPE_U
) || (type
->type
== MONO_TYPE_OBJECT
) ||
7011 (type
->type
== MONO_TYPE_ARRAY
) || (type
->type
== MONO_TYPE_PTR
) ||
7012 (type
->type
== MONO_TYPE_FNPTR
)));
7016 * mono_type_is_reference:
7017 * \param type the \c MonoType operated on
7018 * \returns TRUE if \p type represents an object reference. FALSE otherwise.
7021 mono_type_is_reference (MonoType
*type
)
7023 return (type
&& (((type
->type
== MONO_TYPE_STRING
) ||
7024 (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
7025 (type
->type
== MONO_TYPE_OBJECT
) || (type
->type
== MONO_TYPE_ARRAY
)) ||
7026 ((type
->type
== MONO_TYPE_GENERICINST
) &&
7027 !mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
))));
7031 mono_type_is_generic_parameter (MonoType
*type
)
7033 return !type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
);
7037 * mono_signature_get_return_type:
7038 * \param sig the method signature inspected
7039 * \returns the return type of the method signature \p sig
7042 mono_signature_get_return_type (MonoMethodSignature
*sig
)
7045 MONO_ENTER_GC_UNSAFE
;
7047 MONO_EXIT_GC_UNSAFE
;
7052 * mono_signature_get_params:
7053 * \param sig the method signature inspected
7054 * \param iter pointer to an iterator
7055 * Iterates over the parameters for the method signature \p sig.
7056 * A \c void* pointer must be initialized to NULL to start the iteration
7057 * and its address is passed to this function repeteadly until it returns
7059 * \returns the next parameter type of the method signature \p sig,
7060 * NULL when finished.
7063 mono_signature_get_params (MonoMethodSignature
*sig
, gpointer
*iter
)
7066 MONO_ENTER_GC_UNSAFE
;
7067 result
= mono_signature_get_params_internal (sig
, iter
);
7068 MONO_EXIT_GC_UNSAFE
;
7073 mono_signature_get_params_internal (MonoMethodSignature
*sig
, gpointer
*iter
)
7079 /* start from the first */
7080 if (sig
->param_count
) {
7081 *iter
= &sig
->params
[0];
7082 return sig
->params
[0];
7088 type
= (MonoType
**)*iter
;
7090 if (type
< &sig
->params
[sig
->param_count
]) {
7098 * mono_signature_get_param_count:
7099 * \param sig the method signature inspected
7100 * \returns the number of parameters in the method signature \p sig.
7103 mono_signature_get_param_count (MonoMethodSignature
*sig
)
7105 return sig
->param_count
;
7109 * mono_signature_get_call_conv:
7110 * \param sig the method signature inspected
7111 * \returns the call convention of the method signature \p sig.
7114 mono_signature_get_call_conv (MonoMethodSignature
*sig
)
7116 return sig
->call_convention
;
7120 * mono_signature_vararg_start:
7121 * \param sig the method signature inspected
7122 * \returns the number of the first vararg parameter in the
7123 * method signature \param sig. \c -1 if this is not a vararg signature.
7126 mono_signature_vararg_start (MonoMethodSignature
*sig
)
7128 return sig
->sentinelpos
;
7132 * mono_signature_is_instance:
7133 * \param sig the method signature inspected
7134 * \returns TRUE if this the method signature \p sig has an implicit
7135 * first instance argument. FALSE otherwise.
7138 mono_signature_is_instance (MonoMethodSignature
*sig
)
7140 return sig
->hasthis
;
7144 * mono_signature_param_is_out
7145 * \param sig the method signature inspected
7146 * \param param_num the 0-based index of the inspected parameter
7147 * \returns TRUE if the parameter is an out parameter, FALSE
7151 mono_signature_param_is_out (MonoMethodSignature
*sig
, int param_num
)
7153 g_assert (param_num
>= 0 && param_num
< sig
->param_count
);
7154 return (sig
->params
[param_num
]->attrs
& PARAM_ATTRIBUTE_OUT
) != 0;
7158 * mono_signature_explicit_this:
7159 * \param sig the method signature inspected
7160 * \returns TRUE if this the method signature \p sig has an explicit
7161 * instance argument. FALSE otherwise.
7164 mono_signature_explicit_this (MonoMethodSignature
*sig
)
7166 return sig
->explicit_this
;
7169 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
7171 mono_aligned_addr_hash (gconstpointer ptr
)
7173 /* Same hashing we use for objects */
7174 return (GPOINTER_TO_UINT (ptr
) >> 3) * 2654435761u;
7178 * If @field belongs to an inflated generic class, return the corresponding field of the
7179 * generic type definition class.
7182 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField
*field
)
7187 if (!mono_class_is_ginst (field
->parent
))
7190 gtd
= mono_class_get_generic_class (field
->parent
)->container_class
;
7191 offset
= field
- m_class_get_fields (field
->parent
);
7192 return m_class_get_fields (gtd
) + offset
;
7196 * If @event belongs to an inflated generic class, return the corresponding event of the
7197 * generic type definition class.
7200 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent
*event
)
7205 if (!mono_class_is_ginst (event
->parent
))
7208 gtd
= mono_class_get_generic_class (event
->parent
)->container_class
;
7209 offset
= event
- mono_class_get_event_info (event
->parent
)->events
;
7210 return mono_class_get_event_info (gtd
)->events
+ offset
;
7214 * If @property belongs to an inflated generic class, return the corresponding property of the
7215 * generic type definition class.
7218 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty
*property
)
7220 MonoClassPropertyInfo
*info
;
7224 if (!mono_class_is_ginst (property
->parent
))
7227 info
= mono_class_get_property_info (property
->parent
);
7228 gtd
= mono_class_get_generic_class (property
->parent
)->container_class
;
7229 offset
= property
- info
->properties
;
7230 return mono_class_get_property_info (gtd
)->properties
+ offset
;
7234 mono_method_get_wrapper_cache (MonoMethod
*method
)
7236 if (method
->is_inflated
) {
7237 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
7238 return &imethod
->owner
->wrapper_caches
;
7240 return &m_class_get_image (method
->klass
)->wrapper_caches
;
7244 // 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.
7247 * mono_find_image_set_owner:
7249 * Find the imageset, if any, which a given pointer is located in the memory of.
7252 mono_find_image_set_owner (void *ptr
)
7254 MonoImageSet
*owner
= NULL
;
7261 for (i
= 0; !owner
&& i
< image_sets
->len
; ++i
) {
7262 MonoImageSet
*set
= (MonoImageSet
*)g_ptr_array_index (image_sets
, i
);
7263 if (mono_mempool_contains_addr (set
->mempool
, ptr
))
7268 image_sets_unlock ();
7274 mono_loader_set_strict_strong_names (gboolean enabled
)
7276 check_strong_names_strictly
= enabled
;
7280 mono_loader_get_strict_strong_names (void)
7282 return check_strong_names_strictly
;
7286 MonoCustomModContainer
*
7287 mono_type_get_cmods (const MonoType
*t
)
7292 MonoTypeWithModifiers
*full
= (MonoTypeWithModifiers
*)t
;
7294 return &full
->cmods
;
7298 mono_sizeof_type_with_mods (uint8_t num_mods
)
7301 accum
+= sizeof (MonoType
);
7305 accum
+= offsetof (struct _MonoCustomModContainer
, modifiers
);
7306 accum
+= sizeof (MonoCustomMod
) * num_mods
;
7311 mono_sizeof_type (const MonoType
*ty
)
7313 MonoCustomModContainer
*cmods
= mono_type_get_cmods (ty
);
7315 return mono_sizeof_type_with_mods (cmods
->count
);
7317 return sizeof (MonoType
);