2 * metadata.c: Routines for accessing the metadata
5 * Miguel de Icaza (miguel@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
19 #include "tabledefs.h"
20 #include "mono-endian.h"
22 #include "tokentype.h"
23 #include "class-internals.h"
24 #include "metadata-internals.h"
25 #include "verify-internals.h"
28 #include "debug-helpers.h"
29 #include "abi-details.h"
30 #include <mono/utils/mono-error-internals.h>
31 #include <mono/utils/bsearch.h>
32 #include <mono/utils/atomic.h>
34 /* Auxiliary structure used for caching inflated signatures */
36 MonoMethodSignature
*sig
;
37 MonoGenericContext context
;
38 } MonoInflatedMethodSignature
;
40 static gboolean
do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
, gboolean transient
,
41 const char *ptr
, const char **rptr
, MonoError
*error
);
43 static gboolean
do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
);
44 static gboolean
mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
);
45 static gboolean
mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
);
46 static gboolean
_mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
,
47 gboolean signature_only
);
48 static void free_generic_inst (MonoGenericInst
*ginst
);
49 static void free_generic_class (MonoGenericClass
*ginst
);
50 static void free_inflated_method (MonoMethodInflated
*method
);
51 static void free_inflated_signature (MonoInflatedMethodSignature
*sig
);
52 static void mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
, MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
);
55 * This enumeration is used to describe the data types in the metadata
66 /* Index into Blob heap */
69 /* Index into String heap */
75 /* Pointer into a table */
78 /* HasConstant:Parent pointer (Param, Field or Property) */
81 /* HasCustomAttribute index. Indexes any table except CustomAttribute */
84 /* CustomAttributeType encoded index */
87 /* HasDeclSecurity index: TypeDef Method or Assembly */
90 /* Implementation coded index: File, Export AssemblyRef */
93 /* HasFieldMarshal coded index: Field or Param table */
96 /* MemberForwardedIndex: Field or Method */
99 /* TypeDefOrRef coded index: typedef, typeref, typespec */
102 /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
105 /* MethodDefOrRef coded index: Method or Member Ref table */
108 /* HasSemantic coded index: Event or Property */
111 /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
115 const static unsigned char TableSchemas
[] = {
116 #define ASSEMBLY_SCHEMA_OFFSET 0
117 MONO_MT_UINT32
, /* "HashId" }, */
118 MONO_MT_UINT16
, /* "Major" }, */
119 MONO_MT_UINT16
, /* "Minor" }, */
120 MONO_MT_UINT16
, /* "BuildNumber" }, */
121 MONO_MT_UINT16
, /* "RevisionNumber" }, */
122 MONO_MT_UINT32
, /* "Flags" }, */
123 MONO_MT_BLOB_IDX
, /* "PublicKey" }, */
124 MONO_MT_STRING_IDX
, /* "Name" }, */
125 MONO_MT_STRING_IDX
, /* "Culture" }, */
128 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
129 MONO_MT_UINT32
, /* "OSPlatformID" }, */
130 MONO_MT_UINT32
, /* "OSMajor" }, */
131 MONO_MT_UINT32
, /* "OSMinor" }, */
134 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
135 MONO_MT_UINT32
, /* "Processor" }, */
138 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
139 MONO_MT_UINT16
, /* "Major" }, */
140 MONO_MT_UINT16
, /* "Minor" }, */
141 MONO_MT_UINT16
, /* "Build" }, */
142 MONO_MT_UINT16
, /* "Revision" }, */
143 MONO_MT_UINT32
, /* "Flags" }, */
144 MONO_MT_BLOB_IDX
, /* "PublicKeyOrToken" }, */
145 MONO_MT_STRING_IDX
, /* "Name" }, */
146 MONO_MT_STRING_IDX
, /* "Culture" }, */
147 MONO_MT_BLOB_IDX
, /* "HashValue" }, */
150 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
151 MONO_MT_UINT32
, /* "OSPlatformID" }, */
152 MONO_MT_UINT32
, /* "OSMajorVersion" }, */
153 MONO_MT_UINT32
, /* "OSMinorVersion" }, */
154 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
157 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
158 MONO_MT_UINT32
, /* "Processor" }, */
159 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
162 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
163 MONO_MT_UINT16
, /* "PackingSize" }, */
164 MONO_MT_UINT32
, /* "ClassSize" }, */
165 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
168 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
169 MONO_MT_UINT8
, /* "Type" }, */
170 MONO_MT_UINT8
, /* "PaddingZero" }, */
171 MONO_MT_CONST_IDX
, /* "Parent" }, */
172 MONO_MT_BLOB_IDX
, /* "Value" }, */
175 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
176 MONO_MT_HASCAT_IDX
, /* "Parent" }, */
177 MONO_MT_CAT_IDX
, /* "Type" }, */
178 MONO_MT_BLOB_IDX
, /* "Value" }, */
181 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
182 MONO_MT_UINT16
, /* "Action" }, */
183 MONO_MT_HASDEC_IDX
, /* "Parent" }, */
184 MONO_MT_BLOB_IDX
, /* "PermissionSet" }, */
187 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
188 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
189 MONO_MT_TABLE_IDX
, /* "EventList:Event" }, */
192 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
193 MONO_MT_UINT16
, /* "EventFlags#EventAttribute" }, */
194 MONO_MT_STRING_IDX
, /* "Name" }, */
195 MONO_MT_TDOR_IDX
, /* "EventType" }, TypeDef or TypeRef or TypeSpec */
198 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
199 MONO_MT_TABLE_IDX
, /* "Event" }, */
202 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
203 MONO_MT_UINT32
, /* "Flags" }, */
204 MONO_MT_TABLE_IDX
, /* "TypeDefId" }, */
205 MONO_MT_STRING_IDX
, /* "TypeName" }, */
206 MONO_MT_STRING_IDX
, /* "TypeNameSpace" }, */
207 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
210 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
211 MONO_MT_UINT16
, /* "Flags" }, */
212 MONO_MT_STRING_IDX
, /* "Name" }, */
213 MONO_MT_BLOB_IDX
, /* "Signature" }, */
216 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
217 MONO_MT_UINT32
, /* "Offset" }, */
218 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
221 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
222 MONO_MT_HFM_IDX
, /* "Parent" }, */
223 MONO_MT_BLOB_IDX
, /* "NativeType" }, */
226 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
227 MONO_MT_UINT32
, /* "RVA" }, */
228 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
231 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
232 MONO_MT_TABLE_IDX
, /* "Field" }, */
235 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
236 MONO_MT_UINT32
, /* "Flags" }, */
237 MONO_MT_STRING_IDX
, /* "Name" }, */
238 MONO_MT_BLOB_IDX
, /* "Value" }, */
241 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
242 MONO_MT_UINT16
, /* "MappingFlag" }, */
243 MONO_MT_MF_IDX
, /* "MemberForwarded" }, */
244 MONO_MT_STRING_IDX
, /* "ImportName" }, */
245 MONO_MT_TABLE_IDX
, /* "ImportScope:ModuleRef" }, */
248 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
249 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
250 MONO_MT_TDOR_IDX
, /* "Interface=TypeDefOrRef" }, */
253 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
254 MONO_MT_UINT32
, /* "Offset" }, */
255 MONO_MT_UINT32
, /* "Flags" }, */
256 MONO_MT_STRING_IDX
, /* "Name" }, */
257 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
260 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
261 MONO_MT_MRP_IDX
, /* "Class" }, */
262 MONO_MT_STRING_IDX
, /* "Name" }, */
263 MONO_MT_BLOB_IDX
, /* "Signature" }, */
266 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
267 MONO_MT_UINT32
, /* "RVA" }, */
268 MONO_MT_UINT16
, /* "ImplFlags#MethodImplAttributes" }, */
269 MONO_MT_UINT16
, /* "Flags#MethodAttribute" }, */
270 MONO_MT_STRING_IDX
, /* "Name" }, */
271 MONO_MT_BLOB_IDX
, /* "Signature" }, */
272 MONO_MT_TABLE_IDX
, /* "ParamList:Param" }, */
275 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
276 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
277 MONO_MT_MDOR_IDX
, /* "MethodBody" }, */
278 MONO_MT_MDOR_IDX
, /* "MethodDeclaration" }, */
281 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
282 MONO_MT_UINT16
, /* "MethodSemantic" }, */
283 MONO_MT_TABLE_IDX
, /* "Method:Method" }, */
284 MONO_MT_HS_IDX
, /* "Association" }, */
287 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
288 MONO_MT_TABLE_IDX
, /* "Method" }, */
291 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
292 MONO_MT_UINT16
, /* "Generation" }, */
293 MONO_MT_STRING_IDX
, /* "Name" }, */
294 MONO_MT_GUID_IDX
, /* "MVID" }, */
295 MONO_MT_GUID_IDX
, /* "EncID" }, */
296 MONO_MT_GUID_IDX
, /* "EncBaseID" }, */
299 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
300 MONO_MT_STRING_IDX
, /* "Name" }, */
303 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
304 MONO_MT_TABLE_IDX
, /* "NestedClass:TypeDef" }, */
305 MONO_MT_TABLE_IDX
, /* "EnclosingClass:TypeDef" }, */
308 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
309 MONO_MT_UINT16
, /* "Flags" }, */
310 MONO_MT_UINT16
, /* "Sequence" }, */
311 MONO_MT_STRING_IDX
, /* "Name" }, */
314 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
315 MONO_MT_TABLE_IDX
, /* "Param" }, */
318 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
319 MONO_MT_UINT16
, /* "Flags" }, */
320 MONO_MT_STRING_IDX
, /* "Name" }, */
321 MONO_MT_BLOB_IDX
, /* "Type" }, */
324 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
325 MONO_MT_TABLE_IDX
, /* "Property" }, */
328 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
329 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
330 MONO_MT_TABLE_IDX
, /* "PropertyList:Property" }, */
333 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
334 MONO_MT_BLOB_IDX
, /* "Signature" }, */
337 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
338 MONO_MT_UINT32
, /* "Flags" }, */
339 MONO_MT_STRING_IDX
, /* "Name" }, */
340 MONO_MT_STRING_IDX
, /* "Namespace" }, */
341 MONO_MT_TDOR_IDX
, /* "Extends" }, */
342 MONO_MT_TABLE_IDX
, /* "FieldList:Field" }, */
343 MONO_MT_TABLE_IDX
, /* "MethodList:Method" }, */
346 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
347 MONO_MT_RS_IDX
, /* "ResolutionScope=ResolutionScope" }, */
348 MONO_MT_STRING_IDX
, /* "Name" }, */
349 MONO_MT_STRING_IDX
, /* "Namespace" }, */
352 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
353 MONO_MT_BLOB_IDX
, /* "Signature" }, */
356 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
357 MONO_MT_UINT16
, /* "Number" }, */
358 MONO_MT_UINT16
, /* "Flags" }, */
359 MONO_MT_TABLE_IDX
, /* "Owner" }, TypeDef or MethodDef */
360 MONO_MT_STRING_IDX
, /* "Name" }, */
363 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
364 MONO_MT_MDOR_IDX
, /* "Method" }, */
365 MONO_MT_BLOB_IDX
, /* "Signature" }, */
368 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
369 MONO_MT_TABLE_IDX
, /* "GenericParam" }, */
370 MONO_MT_TDOR_IDX
, /* "Constraint" }, */
373 #define DOCUMENT_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
374 MONO_MT_BLOB_IDX
, /* Name */
375 MONO_MT_GUID_IDX
, /* HashAlgorithm */
376 MONO_MT_BLOB_IDX
, /* Hash */
377 MONO_MT_GUID_IDX
, /* Language */
380 #define METHODBODY_SCHEMA_OFFSET DOCUMENT_SCHEMA_OFFSET + 5
381 MONO_MT_TABLE_IDX
, /* Document */
382 MONO_MT_BLOB_IDX
, /* SequencePoints */
385 #define LOCALSCOPE_SCHEMA_OFFSET METHODBODY_SCHEMA_OFFSET + 3
386 MONO_MT_TABLE_IDX
, /* Method */
387 MONO_MT_TABLE_IDX
, /* ImportScope */
388 MONO_MT_TABLE_IDX
, /* VariableList */
389 MONO_MT_TABLE_IDX
, /* ConstantList */
390 MONO_MT_UINT32
, /* StartOffset */
391 MONO_MT_UINT32
, /* Length */
394 #define LOCALVARIABLE_SCHEMA_OFFSET LOCALSCOPE_SCHEMA_OFFSET + 7
395 MONO_MT_UINT16
, /* Attributes */
396 MONO_MT_UINT16
, /* Index */
397 MONO_MT_STRING_IDX
, /* Name */
400 #define NULL_SCHEMA_OFFSET LOCALVARIABLE_SCHEMA_OFFSET + 4
404 /* Must be the same order as MONO_TABLE_* */
405 const static unsigned char
406 table_description
[] = {
407 MODULE_SCHEMA_OFFSET
,
408 TYPEREF_SCHEMA_OFFSET
,
409 TYPEDEF_SCHEMA_OFFSET
,
410 FIELD_POINTER_SCHEMA_OFFSET
,
412 METHOD_POINTER_SCHEMA_OFFSET
,
413 METHOD_SCHEMA_OFFSET
,
414 PARAM_POINTER_SCHEMA_OFFSET
,
416 IFACEMAP_SCHEMA_OFFSET
,
417 MEMBERREF_SCHEMA_OFFSET
, /* 0xa */
418 CONSTANT_SCHEMA_OFFSET
,
419 CUSTOM_ATTR_SCHEMA_OFFSET
,
420 FIELD_MARSHAL_SCHEMA_OFFSET
,
421 DECL_SEC_SCHEMA_OFFSET
,
422 CLASS_LAYOUT_SCHEMA_OFFSET
,
423 FIELD_LAYOUT_SCHEMA_OFFSET
, /* 0x10 */
424 STDALON_SIG_SCHEMA_OFFSET
,
425 EVENTMAP_SCHEMA_OFFSET
,
426 EVENT_POINTER_SCHEMA_OFFSET
,
428 PROPERTY_MAP_SCHEMA_OFFSET
,
429 PROPERTY_POINTER_SCHEMA_OFFSET
,
430 PROPERTY_SCHEMA_OFFSET
,
431 METHOD_SEMA_SCHEMA_OFFSET
,
432 METHOD_IMPL_SCHEMA_OFFSET
,
433 MODULEREF_SCHEMA_OFFSET
, /* 0x1a */
434 TYPESPEC_SCHEMA_OFFSET
,
435 IMPLMAP_SCHEMA_OFFSET
,
436 FIELD_RVA_SCHEMA_OFFSET
,
439 ASSEMBLY_SCHEMA_OFFSET
, /* 0x20 */
440 ASSEMBLYPROC_SCHEMA_OFFSET
,
441 ASSEMBLYOS_SCHEMA_OFFSET
,
442 ASSEMBLYREF_SCHEMA_OFFSET
,
443 ASSEMBLYREFPROC_SCHEMA_OFFSET
,
444 ASSEMBLYREFOS_SCHEMA_OFFSET
,
446 EXPORTED_TYPE_SCHEMA_OFFSET
,
447 MANIFEST_SCHEMA_OFFSET
,
448 NESTED_CLASS_SCHEMA_OFFSET
,
449 GENPARAM_SCHEMA_OFFSET
, /* 0x2a */
450 METHOD_SPEC_SCHEMA_OFFSET
,
451 GEN_CONSTRAINT_SCHEMA_OFFSET
,
455 DOCUMENT_SCHEMA_OFFSET
, /* 0x30 */
456 METHODBODY_SCHEMA_OFFSET
,
457 LOCALSCOPE_SCHEMA_OFFSET
,
458 LOCALVARIABLE_SCHEMA_OFFSET
461 #ifdef HAVE_ARRAY_ELEM_INIT
462 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
463 #define MSGSTRFIELD1(line) str##line
464 static const struct msgstr_t
{
465 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
466 #include "mono/cil/tables.def"
469 #define TABLEDEF(a,b) b,
470 #include "mono/cil/tables.def"
473 static const gint16 tableidx
[] = {
474 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
475 #include "mono/cil/tables.def"
480 #define TABLEDEF(a,b) b,
481 static const char* const
482 mono_tables_names
[] = {
483 #include "mono/cil/tables.def"
489 // Amount initially reserved in each imageset's mempool.
490 // FIXME: This number is arbitrary, a more practical number should be found
491 #define INITIAL_IMAGE_SET_SIZE 1024
494 * mono_meta_table_name:
495 * @table: table index
497 * Returns the name of the given ECMA metadata logical format table
498 * as described in ECMA 335, Partition II, Section 22.
500 * Returns: the name for the @table index
503 mono_meta_table_name (int table
)
505 if ((table
< 0) || (table
> MONO_TABLE_LAST
))
508 #ifdef HAVE_ARRAY_ELEM_INIT
509 return (const char*)&tablestr
+ tableidx
[table
];
511 return mono_tables_names
[table
];
515 /* The guy who wrote the spec for this should not be allowed near a
518 If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
519 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
520 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
521 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
522 inverse of this mapping.
525 #define rtsize(meta,s,b) (((s) < (1 << (b)) ? 2 : 4))
526 #define idx_size(meta,tableidx) ((meta)->tables [(tableidx)].rows < 65536 ? 2 : 4)
528 /* Reference: Partition II - 23.2.6 */
530 * mono_metadata_compute_size:
531 * @meta: metadata context
532 * @tableindex: metadata table number
533 * @result_bitfield: pointer to guint32 where to store additional info
535 * mono_metadata_compute_size() computes the lenght in bytes of a single
536 * row in a metadata table. The size of each column is encoded in the
537 * @result_bitfield return value along with the number of columns in the table.
538 * the resulting bitfield should be handed to the mono_metadata_table_size()
539 * and mono_metadata_table_count() macros.
540 * This is a Mono runtime internal only function.
543 mono_metadata_compute_size (MonoImage
*meta
, int tableindex
, guint32
*result_bitfield
)
545 guint32 bitfield
= 0;
546 int size
= 0, field_size
= 0;
549 const unsigned char *description
= TableSchemas
+ table_description
[tableindex
];
551 for (i
= 0; (code
= description
[i
]) != MONO_MT_END
; i
++){
554 field_size
= 4; break;
557 field_size
= 2; break;
560 field_size
= 1; break;
562 case MONO_MT_BLOB_IDX
:
563 field_size
= meta
->idx_blob_wide
? 4 : 2; break;
565 case MONO_MT_STRING_IDX
:
566 field_size
= meta
->idx_string_wide
? 4 : 2; break;
568 case MONO_MT_GUID_IDX
:
569 field_size
= meta
->idx_guid_wide
? 4 : 2; break;
571 case MONO_MT_TABLE_IDX
:
572 /* Uhm, a table index can point to other tables besides the current one
573 * so, it's not correct to use the rowcount of the current table to
574 * get the size for this column - lupus
576 switch (tableindex
) {
577 case MONO_TABLE_ASSEMBLYREFOS
:
579 field_size
= idx_size (meta
, MONO_TABLE_ASSEMBLYREF
); break;
580 case MONO_TABLE_ASSEMBLYREFPROCESSOR
:
582 field_size
= idx_size (meta
, MONO_TABLE_ASSEMBLYREF
); break;
583 case MONO_TABLE_CLASSLAYOUT
:
585 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
586 case MONO_TABLE_EVENTMAP
:
587 g_assert (i
== 0 || i
== 1);
588 field_size
= i
? idx_size (meta
, MONO_TABLE_EVENT
):
589 idx_size (meta
, MONO_TABLE_TYPEDEF
);
591 case MONO_TABLE_EVENT_POINTER
:
593 field_size
= idx_size (meta
, MONO_TABLE_EVENT
); break;
594 case MONO_TABLE_EXPORTEDTYPE
:
596 /* the index is in another metadata file, so it must be 4 */
597 field_size
= 4; break;
598 case MONO_TABLE_FIELDLAYOUT
:
600 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
601 case MONO_TABLE_FIELDRVA
:
603 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
604 case MONO_TABLE_FIELD_POINTER
:
606 field_size
= idx_size (meta
, MONO_TABLE_FIELD
); break;
607 case MONO_TABLE_IMPLMAP
:
609 field_size
= idx_size (meta
, MONO_TABLE_MODULEREF
); break;
610 case MONO_TABLE_INTERFACEIMPL
:
612 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
613 case MONO_TABLE_METHOD
:
615 field_size
= idx_size (meta
, MONO_TABLE_PARAM
); break;
616 case MONO_TABLE_METHODIMPL
:
618 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
619 case MONO_TABLE_METHODSEMANTICS
:
621 field_size
= idx_size (meta
, MONO_TABLE_METHOD
); break;
622 case MONO_TABLE_METHOD_POINTER
:
624 field_size
= idx_size (meta
, MONO_TABLE_METHOD
); break;
625 case MONO_TABLE_NESTEDCLASS
:
626 g_assert (i
== 0 || i
== 1);
627 field_size
= idx_size (meta
, MONO_TABLE_TYPEDEF
); break;
628 case MONO_TABLE_PARAM_POINTER
:
630 field_size
= idx_size (meta
, MONO_TABLE_PARAM
); break;
631 case MONO_TABLE_PROPERTYMAP
:
632 g_assert (i
== 0 || i
== 1);
633 field_size
= i
? idx_size (meta
, MONO_TABLE_PROPERTY
):
634 idx_size (meta
, MONO_TABLE_TYPEDEF
);
636 case MONO_TABLE_PROPERTY_POINTER
:
638 field_size
= idx_size (meta
, MONO_TABLE_PROPERTY
); break;
639 case MONO_TABLE_TYPEDEF
:
640 g_assert (i
== 4 || i
== 5);
641 field_size
= i
== 4 ? idx_size (meta
, MONO_TABLE_FIELD
):
642 idx_size (meta
, MONO_TABLE_METHOD
);
644 case MONO_TABLE_GENERICPARAM
:
646 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
, meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
647 /*This is a coded token for 2 tables, so takes 1 bit */
648 field_size
= rtsize (meta
, n
, 16 - MONO_TYPEORMETHOD_BITS
);
650 case MONO_TABLE_GENERICPARAMCONSTRAINT
:
652 field_size
= idx_size (meta
, MONO_TABLE_GENERICPARAM
);
654 case MONO_TABLE_LOCALSCOPE
:
657 // FIXME: This table is in another file
658 field_size
= idx_size (meta
, MONO_TABLE_METHOD
);
661 field_size
= idx_size (meta
, MONO_TABLE_IMPORTSCOPE
);
664 field_size
= idx_size (meta
, MONO_TABLE_LOCALVARIABLE
);
667 field_size
= idx_size (meta
, MONO_TABLE_LOCALCONSTANT
);
670 g_assert_not_reached ();
674 case MONO_TABLE_METHODBODY
:
676 field_size
= idx_size (meta
, MONO_TABLE_DOCUMENT
);
679 g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex
, i
);
684 * HasConstant: ParamDef, FieldDef, Property
686 case MONO_MT_CONST_IDX
:
687 n
= MAX (meta
->tables
[MONO_TABLE_PARAM
].rows
,
688 meta
->tables
[MONO_TABLE_FIELD
].rows
);
689 n
= MAX (n
, meta
->tables
[MONO_TABLE_PROPERTY
].rows
);
691 /* 2 bits to encode tag */
692 field_size
= rtsize (meta
, n
, 16-2);
696 * HasCustomAttribute: points to any table but
699 case MONO_MT_HASCAT_IDX
:
701 * We believe that since the signature and
702 * permission are indexing the Blob heap,
703 * we should consider the blob size first
705 /* I'm not a believer - lupus
706 if (meta->idx_blob_wide){
711 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
,
712 meta
->tables
[MONO_TABLE_FIELD
].rows
);
713 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
714 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
715 n
= MAX (n
, meta
->tables
[MONO_TABLE_PARAM
].rows
);
716 n
= MAX (n
, meta
->tables
[MONO_TABLE_INTERFACEIMPL
].rows
);
717 n
= MAX (n
, meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
718 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULE
].rows
);
719 n
= MAX (n
, meta
->tables
[MONO_TABLE_DECLSECURITY
].rows
);
720 n
= MAX (n
, meta
->tables
[MONO_TABLE_PROPERTY
].rows
);
721 n
= MAX (n
, meta
->tables
[MONO_TABLE_EVENT
].rows
);
722 n
= MAX (n
, meta
->tables
[MONO_TABLE_STANDALONESIG
].rows
);
723 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
724 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
725 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLY
].rows
);
726 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
727 n
= MAX (n
, meta
->tables
[MONO_TABLE_FILE
].rows
);
728 n
= MAX (n
, meta
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
);
729 n
= MAX (n
, meta
->tables
[MONO_TABLE_MANIFESTRESOURCE
].rows
);
731 /* 5 bits to encode */
732 field_size
= rtsize (meta
, n
, 16-5);
736 * CustomAttributeType: TypeDef, TypeRef, MethodDef,
737 * MemberRef and String.
739 case MONO_MT_CAT_IDX
:
740 /* String is a heap, if it is wide, we know the size */
742 if (meta->idx_string_wide){
747 n
= MAX (meta
->tables
[MONO_TABLE_TYPEREF
].rows
,
748 meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
749 n
= MAX (n
, meta
->tables
[MONO_TABLE_METHOD
].rows
);
750 n
= MAX (n
, meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
752 /* 3 bits to encode */
753 field_size
= rtsize (meta
, n
, 16-3);
757 * HasDeclSecurity: Typedef, MethodDef, Assembly
759 case MONO_MT_HASDEC_IDX
:
760 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
761 meta
->tables
[MONO_TABLE_METHOD
].rows
);
762 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLY
].rows
);
764 /* 2 bits to encode */
765 field_size
= rtsize (meta
, n
, 16-2);
769 * Implementation: File, AssemblyRef, ExportedType
771 case MONO_MT_IMPL_IDX
:
772 n
= MAX (meta
->tables
[MONO_TABLE_FILE
].rows
,
773 meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
774 n
= MAX (n
, meta
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
);
776 /* 2 bits to encode tag */
777 field_size
= rtsize (meta
, n
, 16-2);
781 * HasFieldMarshall: FieldDef, ParamDef
783 case MONO_MT_HFM_IDX
:
784 n
= MAX (meta
->tables
[MONO_TABLE_FIELD
].rows
,
785 meta
->tables
[MONO_TABLE_PARAM
].rows
);
787 /* 1 bit used to encode tag */
788 field_size
= rtsize (meta
, n
, 16-1);
792 * MemberForwarded: FieldDef, MethodDef
795 n
= MAX (meta
->tables
[MONO_TABLE_FIELD
].rows
,
796 meta
->tables
[MONO_TABLE_METHOD
].rows
);
798 /* 1 bit used to encode tag */
799 field_size
= rtsize (meta
, n
, 16-1);
803 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
805 * It is TypeDef, _TypeRef_, TypeSpec, instead.
807 case MONO_MT_TDOR_IDX
:
808 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
809 meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
810 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
812 /* 2 bits to encode */
813 field_size
= rtsize (meta
, n
, 16-2);
817 * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
819 case MONO_MT_MRP_IDX
:
820 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
821 meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
822 n
= MAX (n
, meta
->tables
[MONO_TABLE_METHOD
].rows
);
823 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
824 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
826 /* 3 bits to encode */
827 field_size
= rtsize (meta
, n
, 16 - 3);
831 * MethodDefOrRef: MethodDef, MemberRef
833 case MONO_MT_MDOR_IDX
:
834 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
,
835 meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
837 /* 1 bit used to encode tag */
838 field_size
= rtsize (meta
, n
, 16-1);
842 * HasSemantics: Property, Event
845 n
= MAX (meta
->tables
[MONO_TABLE_PROPERTY
].rows
,
846 meta
->tables
[MONO_TABLE_EVENT
].rows
);
848 /* 1 bit used to encode tag */
849 field_size
= rtsize (meta
, n
, 16-1);
853 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
856 n
= MAX (meta
->tables
[MONO_TABLE_MODULE
].rows
,
857 meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
858 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
859 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
861 /* 2 bits used to encode tag (ECMA spec claims 3) */
862 field_size
= rtsize (meta
, n
, 16 - 2);
867 * encode field size as follows (we just need to
874 bitfield
|= (field_size
-1) << shift
;
877 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
880 *result_bitfield
= (i
<< 24) | bitfield
;
885 * mono_metadata_compute_table_bases:
886 * @meta: metadata context to compute table values
888 * Computes the table bases for the metadata structure.
889 * This is an internal function used by the image loader code.
892 mono_metadata_compute_table_bases (MonoImage
*meta
)
895 const char *base
= meta
->tables_base
;
897 for (i
= 0; i
< MONO_TABLE_NUM
; i
++) {
898 MonoTableInfo
*table
= &meta
->tables
[i
];
899 if (table
->rows
== 0)
902 table
->row_size
= mono_metadata_compute_size (meta
, i
, &table
->size_bitfield
);
904 base
+= table
->rows
* table
->row_size
;
909 * mono_metadata_locate:
910 * @meta: metadata context
911 * @table: table code.
912 * @idx: index of element to retrieve from @table.
914 * Returns: a pointer to the @idx element in the metadata table
915 * whose code is @table.
918 mono_metadata_locate (MonoImage
*meta
, int table
, int idx
)
920 /* idx == 0 refers always to NULL */
921 g_return_val_if_fail (idx
> 0 && idx
<= meta
->tables
[table
].rows
, ""); /*FIXME shouldn't we return NULL here?*/
923 return meta
->tables
[table
].base
+ (meta
->tables
[table
].row_size
* (idx
- 1));
927 * mono_metadata_locate_token:
928 * @meta: metadata context
929 * @token: metadata token
931 * Returns: a pointer to the data in the metadata represented by the
935 mono_metadata_locate_token (MonoImage
*meta
, guint32 token
)
937 return mono_metadata_locate (meta
, token
>> 24, token
& 0xffffff);
941 * mono_metadata_string_heap:
942 * @meta: metadata context
943 * @index: index into the string heap.
945 * Returns: an in-memory pointer to the @index in the string heap.
948 mono_metadata_string_heap (MonoImage
*meta
, guint32 index
)
950 g_assert (index
< meta
->heap_strings
.size
);
951 g_return_val_if_fail (index
< meta
->heap_strings
.size
, "");
952 return meta
->heap_strings
.data
+ index
;
956 * mono_metadata_user_string:
957 * @meta: metadata context
958 * @index: index into the user string heap.
960 * Returns: an in-memory pointer to the @index in the user string heap ("#US").
963 mono_metadata_user_string (MonoImage
*meta
, guint32 index
)
965 g_assert (index
< meta
->heap_us
.size
);
966 g_return_val_if_fail (index
< meta
->heap_us
.size
, "");
967 return meta
->heap_us
.data
+ index
;
971 * mono_metadata_blob_heap:
972 * @meta: metadata context
973 * @index: index into the blob.
975 * Returns: an in-memory pointer to the @index in the Blob heap.
978 mono_metadata_blob_heap (MonoImage
*meta
, guint32 index
)
980 g_assert (index
< meta
->heap_blob
.size
);
981 g_return_val_if_fail (index
< meta
->heap_blob
.size
, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
982 return meta
->heap_blob
.data
+ index
;
986 * mono_metadata_guid_heap:
987 * @meta: metadata context
988 * @index: index into the guid heap.
990 * Returns: an in-memory pointer to the @index in the guid heap.
993 mono_metadata_guid_heap (MonoImage
*meta
, guint32 index
)
996 index
*= 16; /* adjust for guid size and 1-based index */
997 g_return_val_if_fail (index
< meta
->heap_guid
.size
, "");
998 return meta
->heap_guid
.data
+ index
;
1001 static const unsigned char *
1002 dword_align (const unsigned char *ptr
)
1004 #if SIZEOF_VOID_P == 8
1005 return (const unsigned char *) (((guint64
) (ptr
+ 3)) & ~3);
1007 return (const unsigned char *) (((guint32
) (ptr
+ 3)) & ~3);
1012 * mono_metadata_decode_row:
1013 * @t: table to extract information from.
1014 * @idx: index in table.
1015 * @res: array of @res_size cols to store the results in
1017 * This decompresses the metadata element @idx in table @t
1018 * into the guint32 @res array that has res_size elements
1021 mono_metadata_decode_row (const MonoTableInfo
*t
, int idx
, guint32
*res
, int res_size
)
1023 guint32 bitfield
= t
->size_bitfield
;
1024 int i
, count
= mono_metadata_table_count (bitfield
);
1027 g_assert (idx
< t
->rows
);
1028 g_assert (idx
>= 0);
1029 data
= t
->base
+ idx
* t
->row_size
;
1031 g_assert (res_size
== count
);
1033 for (i
= 0; i
< count
; i
++) {
1034 int n
= mono_metadata_table_size (bitfield
, i
);
1038 res
[i
] = *data
; break;
1040 res
[i
] = read16 (data
); break;
1042 res
[i
] = read32 (data
); break;
1044 g_assert_not_reached ();
1051 * mono_metadata_decode_row_col:
1052 * @t: table to extract information from.
1053 * @idx: index for row in table.
1054 * @col: column in the row.
1056 * This function returns the value of column @col from the @idx
1057 * row in the table @t.
1060 mono_metadata_decode_row_col (const MonoTableInfo
*t
, int idx
, guint col
)
1062 guint32 bitfield
= t
->size_bitfield
;
1064 register const char *data
;
1067 g_assert (idx
< t
->rows
);
1068 g_assert (col
< mono_metadata_table_count (bitfield
));
1069 data
= t
->base
+ idx
* t
->row_size
;
1071 n
= mono_metadata_table_size (bitfield
, 0);
1072 for (i
= 0; i
< col
; ++i
) {
1074 n
= mono_metadata_table_size (bitfield
, i
+ 1);
1080 return read16 (data
);
1082 return read32 (data
);
1084 g_assert_not_reached ();
1090 * mono_metadata_decode_blob_size:
1091 * @ptr: pointer to a blob object
1092 * @rptr: the new position of the pointer
1094 * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
1096 * Returns: the size of the blob object
1099 mono_metadata_decode_blob_size (const char *xptr
, const char **rptr
)
1101 const unsigned char *ptr
= (const unsigned char *)xptr
;
1104 if ((*ptr
& 0x80) == 0){
1105 size
= ptr
[0] & 0x7f;
1107 } else if ((*ptr
& 0x40) == 0){
1108 size
= ((ptr
[0] & 0x3f) << 8) + ptr
[1];
1111 size
= ((ptr
[0] & 0x1f) << 24) +
1123 * mono_metadata_decode_value:
1124 * @ptr: pointer to decode from
1125 * @rptr: the new position of the pointer
1127 * This routine decompresses 32-bit values as specified in the "Blob and
1128 * Signature" section (22.2)
1130 * Returns: the decoded value
1133 mono_metadata_decode_value (const char *_ptr
, const char **rptr
)
1135 const unsigned char *ptr
= (const unsigned char *) _ptr
;
1136 unsigned char b
= *ptr
;
1139 if ((b
& 0x80) == 0){
1142 } else if ((b
& 0x40) == 0){
1143 len
= ((b
& 0x3f) << 8 | ptr
[1]);
1146 len
= ((b
& 0x1f) << 24) |
1159 * mono_metadata_decode_signed_value:
1160 * @ptr: pointer to decode from
1161 * @rptr: the new position of the pointer
1163 * This routine decompresses 32-bit signed values
1164 * (not specified in the spec)
1166 * Returns: the decoded value
1169 mono_metadata_decode_signed_value (const char *ptr
, const char **rptr
)
1171 guint32 uval
= mono_metadata_decode_value (ptr
, rptr
);
1172 gint32 ival
= uval
>> 1;
1175 /* ival is a truncated 2's complement negative number. */
1177 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1180 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1181 return ival
- 0x2000;
1182 if (ival
< 0x10000000)
1183 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1184 return ival
- 0x10000000;
1185 g_assert (ival
< 0x20000000);
1186 g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival
, uval
);
1187 return ival
- 0x20000000;
1191 * Translates the given 1-based index into the Method, Field, Event, or Param tables
1192 * using the *Ptr tables in uncompressed metadata, if they are available.
1194 * FIXME: The caller is not forced to call this function, which is error-prone, since
1195 * forgetting to call it would only show up as a bug on uncompressed metadata.
1198 mono_metadata_translate_token_index (MonoImage
*image
, int table
, guint32 idx
)
1200 if (!image
->uncompressed_metadata
)
1204 case MONO_TABLE_METHOD
:
1205 if (image
->tables
[MONO_TABLE_METHOD_POINTER
].rows
)
1206 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_METHOD_POINTER
], idx
- 1, MONO_METHOD_POINTER_METHOD
);
1209 case MONO_TABLE_FIELD
:
1210 if (image
->tables
[MONO_TABLE_FIELD_POINTER
].rows
)
1211 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_FIELD_POINTER
], idx
- 1, MONO_FIELD_POINTER_FIELD
);
1214 case MONO_TABLE_EVENT
:
1215 if (image
->tables
[MONO_TABLE_EVENT_POINTER
].rows
)
1216 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_EVENT_POINTER
], idx
- 1, MONO_EVENT_POINTER_EVENT
);
1219 case MONO_TABLE_PROPERTY
:
1220 if (image
->tables
[MONO_TABLE_PROPERTY_POINTER
].rows
)
1221 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PROPERTY_POINTER
], idx
- 1, MONO_PROPERTY_POINTER_PROPERTY
);
1224 case MONO_TABLE_PARAM
:
1225 if (image
->tables
[MONO_TABLE_PARAM_POINTER
].rows
)
1226 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PARAM_POINTER
], idx
- 1, MONO_PARAM_POINTER_PARAM
);
1235 * mono_metadata_decode_table_row:
1237 * Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
1238 * uncompressed metadata into account, so it should be used to access the
1239 * Method, Field, Param and Event tables when the access is made from metadata, i.e.
1240 * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
1243 mono_metadata_decode_table_row (MonoImage
*image
, int table
, int idx
, guint32
*res
, int res_size
)
1245 if (image
->uncompressed_metadata
)
1246 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1248 mono_metadata_decode_row (&image
->tables
[table
], idx
, res
, res_size
);
1252 * mono_metadata_decode_table_row_col:
1254 * Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
1255 * uncompressed metadata into account, so it should be used to access the
1256 * Method, Field, Param and Event tables.
1258 guint32
mono_metadata_decode_table_row_col (MonoImage
*image
, int table
, int idx
, guint col
)
1260 if (image
->uncompressed_metadata
)
1261 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1263 return mono_metadata_decode_row_col (&image
->tables
[table
], idx
, col
);
1267 * mono_metadata_parse_typedef_or_ref:
1268 * @m: a metadata context.
1269 * @ptr: a pointer to an encoded TypedefOrRef in @m
1270 * @rptr: pointer updated to match the end of the decoded stream
1272 * Returns: a token valid in the @m metadata decoded from
1273 * the compressed representation.
1276 mono_metadata_parse_typedef_or_ref (MonoImage
*m
, const char *ptr
, const char **rptr
)
1279 token
= mono_metadata_decode_value (ptr
, &ptr
);
1282 return mono_metadata_token_from_dor (token
);
1286 * mono_metadata_parse_custom_mod:
1287 * @m: a metadata context.
1288 * @dest: storage where the info about the custom modifier is stored (may be NULL)
1289 * @ptr: a pointer to (possibly) the start of a custom modifier list
1290 * @rptr: pointer updated to match the end of the decoded stream
1292 * Checks if @ptr points to a type custom modifier compressed representation.
1294 * Returns: #TRUE if a custom modifier was found, #FALSE if not.
1297 mono_metadata_parse_custom_mod (MonoImage
*m
, MonoCustomMod
*dest
, const char *ptr
, const char **rptr
)
1299 MonoCustomMod local
;
1300 if ((*ptr
== MONO_TYPE_CMOD_OPT
) || (*ptr
== MONO_TYPE_CMOD_REQD
)) {
1303 dest
->required
= *ptr
== MONO_TYPE_CMOD_REQD
? 1 : 0;
1304 dest
->token
= mono_metadata_parse_typedef_or_ref (m
, ptr
+ 1, rptr
);
1311 * mono_metadata_parse_array_internal:
1312 * @m: a metadata context.
1313 * @transient: whenever to allocate data from the heap
1314 * @ptr: a pointer to an encoded array description.
1315 * @rptr: pointer updated to match the end of the decoded stream
1317 * Decodes the compressed array description found in the metadata @m at @ptr.
1319 * Returns: a #MonoArrayType structure describing the array type
1320 * and dimensions. Memory is allocated from the heap or from the image mempool, depending
1321 * on the value of @transient.
1323 * LOCKING: Acquires the loader lock
1325 static MonoArrayType
*
1326 mono_metadata_parse_array_internal (MonoImage
*m
, MonoGenericContainer
*container
,
1327 gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1330 MonoArrayType
*array
;
1333 etype
= mono_metadata_parse_type_checked (m
, container
, 0, FALSE
, ptr
, &ptr
, error
); //FIXME this doesn't respect @transient
1337 array
= transient
? (MonoArrayType
*)g_malloc0 (sizeof (MonoArrayType
)) : (MonoArrayType
*)mono_image_alloc0 (m
, sizeof (MonoArrayType
));
1338 array
->eklass
= mono_class_from_mono_type (etype
);
1339 array
->rank
= mono_metadata_decode_value (ptr
, &ptr
);
1341 array
->numsizes
= mono_metadata_decode_value (ptr
, &ptr
);
1342 if (array
->numsizes
)
1343 array
->sizes
= transient
? (int *)g_malloc0 (sizeof (int) * array
->numsizes
) : (int *)mono_image_alloc0 (m
, sizeof (int) * array
->numsizes
);
1344 for (i
= 0; i
< array
->numsizes
; ++i
)
1345 array
->sizes
[i
] = mono_metadata_decode_value (ptr
, &ptr
);
1347 array
->numlobounds
= mono_metadata_decode_value (ptr
, &ptr
);
1348 if (array
->numlobounds
)
1349 array
->lobounds
= transient
? (int *)g_malloc0 (sizeof (int) * array
->numlobounds
) : (int *)mono_image_alloc0 (m
, sizeof (int) * array
->numlobounds
);
1350 for (i
= 0; i
< array
->numlobounds
; ++i
)
1351 array
->lobounds
[i
] = mono_metadata_decode_signed_value (ptr
, &ptr
);
1359 mono_metadata_parse_array (MonoImage
*m
, const char *ptr
, const char **rptr
)
1362 MonoArrayType
*ret
= mono_metadata_parse_array_internal (m
, NULL
, FALSE
, ptr
, rptr
, &error
);
1363 mono_error_cleanup (&error
);
1369 * mono_metadata_free_array:
1370 * @array: array description
1372 * Frees the array description returned from mono_metadata_parse_array().
1375 mono_metadata_free_array (MonoArrayType
*array
)
1377 g_free (array
->sizes
);
1378 g_free (array
->lobounds
);
1383 * need to add common field and param attributes combinations:
1386 * public static literal
1389 * private static literal
1391 static const MonoType
1393 /* data, attrs, type, nmods, byref, pinned */
1394 {{NULL
}, 0, MONO_TYPE_VOID
, 0, 0, 0},
1395 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 0, 0},
1396 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 1, 0},
1397 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 0, 0},
1398 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 1, 0},
1399 {{NULL
}, 0, MONO_TYPE_I1
, 0, 0, 0},
1400 {{NULL
}, 0, MONO_TYPE_I1
, 0, 1, 0},
1401 {{NULL
}, 0, MONO_TYPE_U1
, 0, 0, 0},
1402 {{NULL
}, 0, MONO_TYPE_U1
, 0, 1, 0},
1403 {{NULL
}, 0, MONO_TYPE_I2
, 0, 0, 0},
1404 {{NULL
}, 0, MONO_TYPE_I2
, 0, 1, 0},
1405 {{NULL
}, 0, MONO_TYPE_U2
, 0, 0, 0},
1406 {{NULL
}, 0, MONO_TYPE_U2
, 0, 1, 0},
1407 {{NULL
}, 0, MONO_TYPE_I4
, 0, 0, 0},
1408 {{NULL
}, 0, MONO_TYPE_I4
, 0, 1, 0},
1409 {{NULL
}, 0, MONO_TYPE_U4
, 0, 0, 0},
1410 {{NULL
}, 0, MONO_TYPE_U4
, 0, 1, 0},
1411 {{NULL
}, 0, MONO_TYPE_I8
, 0, 0, 0},
1412 {{NULL
}, 0, MONO_TYPE_I8
, 0, 1, 0},
1413 {{NULL
}, 0, MONO_TYPE_U8
, 0, 0, 0},
1414 {{NULL
}, 0, MONO_TYPE_U8
, 0, 1, 0},
1415 {{NULL
}, 0, MONO_TYPE_R4
, 0, 0, 0},
1416 {{NULL
}, 0, MONO_TYPE_R4
, 0, 1, 0},
1417 {{NULL
}, 0, MONO_TYPE_R8
, 0, 0, 0},
1418 {{NULL
}, 0, MONO_TYPE_R8
, 0, 1, 0},
1419 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 0, 0},
1420 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 1, 0},
1421 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 0, 0},
1422 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 1, 0},
1423 {{NULL
}, 0, MONO_TYPE_TYPEDBYREF
, 0, 0, 0},
1424 {{NULL
}, 0, MONO_TYPE_I
, 0, 0, 0},
1425 {{NULL
}, 0, MONO_TYPE_I
, 0, 1, 0},
1426 {{NULL
}, 0, MONO_TYPE_U
, 0, 0, 0},
1427 {{NULL
}, 0, MONO_TYPE_U
, 0, 1, 0},
1430 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1432 static GHashTable
*type_cache
= NULL
;
1433 static int next_generic_inst_id
= 0;
1435 /* Protected by image_sets_mutex */
1436 static MonoImageSet
*mscorlib_image_set
;
1437 /* Protected by image_sets_mutex */
1438 static GPtrArray
*image_sets
;
1439 static mono_mutex_t image_sets_mutex
;
1441 static guint
mono_generic_class_hash (gconstpointer data
);
1444 * MonoTypes with modifies are never cached, so we never check or use that field.
1447 mono_type_hash (gconstpointer data
)
1449 const MonoType
*type
= (const MonoType
*) data
;
1450 if (type
->type
== MONO_TYPE_GENERICINST
)
1451 return mono_generic_class_hash (type
->data
.generic_class
);
1453 return type
->type
| (type
->byref
<< 8) | (type
->attrs
<< 9);
1457 mono_type_equal (gconstpointer ka
, gconstpointer kb
)
1459 const MonoType
*a
= (const MonoType
*) ka
;
1460 const MonoType
*b
= (const MonoType
*) kb
;
1462 if (a
->type
!= b
->type
|| a
->byref
!= b
->byref
|| a
->attrs
!= b
->attrs
|| a
->pinned
!= b
->pinned
)
1464 /* need other checks */
1469 mono_metadata_generic_inst_hash (gconstpointer data
)
1471 const MonoGenericInst
*ginst
= (const MonoGenericInst
*) data
;
1475 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
1477 hash
+= mono_metadata_type_hash (ginst
->type_argv
[i
]);
1480 return hash
^ (ginst
->is_open
<< 8);
1484 mono_generic_inst_equal_full (const MonoGenericInst
*a
, const MonoGenericInst
*b
, gboolean signature_only
)
1488 // An optimization: if the ids of two insts are the same, we know they are the same inst and don't check contents.
1489 // Furthermore, because we perform early de-duping, if the ids differ, we know the contents differ.
1490 #ifndef MONO_SMALL_CONFIG // Optimization does not work in MONO_SMALL_CONFIG: There are no IDs
1491 if (a
->id
&& b
->id
) { // "id 0" means "object has no id"-- de-duping hasn't been performed yet, must check contents.
1494 // In signature-comparison mode id equality implies object equality, but this is not true for inequality.
1495 // Two separate objects could have signature-equavalent contents.
1496 if (!signature_only
)
1501 if (a
->is_open
!= b
->is_open
|| a
->type_argc
!= b
->type_argc
)
1503 for (i
= 0; i
< a
->type_argc
; ++i
) {
1504 if (!do_mono_metadata_type_equal (a
->type_argv
[i
], b
->type_argv
[i
], signature_only
))
1511 mono_metadata_generic_inst_equal (gconstpointer ka
, gconstpointer kb
)
1513 const MonoGenericInst
*a
= (const MonoGenericInst
*) ka
;
1514 const MonoGenericInst
*b
= (const MonoGenericInst
*) kb
;
1516 return mono_generic_inst_equal_full (a
, b
, FALSE
);
1520 mono_generic_class_hash (gconstpointer data
)
1522 const MonoGenericClass
*gclass
= (const MonoGenericClass
*) data
;
1523 guint hash
= mono_metadata_type_hash (&gclass
->container_class
->byval_arg
);
1526 hash
+= gclass
->is_tb_open
;
1527 hash
+= mono_metadata_generic_context_hash (&gclass
->context
);
1533 mono_generic_class_equal (gconstpointer ka
, gconstpointer kb
)
1535 const MonoGenericClass
*a
= (const MonoGenericClass
*) ka
;
1536 const MonoGenericClass
*b
= (const MonoGenericClass
*) kb
;
1538 return _mono_metadata_generic_class_equal (a
, b
, FALSE
);
1542 * mono_metadata_init:
1544 * Initialize the global variables of this module.
1545 * This is a Mono runtime internal function.
1548 mono_metadata_init (void)
1552 type_cache
= g_hash_table_new (mono_type_hash
, mono_type_equal
);
1554 for (i
= 0; i
< NBUILTIN_TYPES (); ++i
)
1555 g_hash_table_insert (type_cache
, (gpointer
) &builtin_types
[i
], (gpointer
) &builtin_types
[i
]);
1557 mono_os_mutex_init_recursive (&image_sets_mutex
);
1561 * mono_metadata_cleanup:
1563 * Free all resources used by this module.
1564 * This is a Mono runtime internal function.
1567 mono_metadata_cleanup (void)
1569 g_hash_table_destroy (type_cache
);
1571 g_ptr_array_free (image_sets
, TRUE
);
1573 mono_os_mutex_destroy (&image_sets_mutex
);
1577 * mono_metadata_parse_type:
1578 * @m: metadata context
1579 * @mode: king of type that may be found at @ptr
1580 * @opt_attrs: optional attributes to store in the returned type
1581 * @ptr: pointer to the type representation
1582 * @rptr: pointer updated to match the end of the decoded stream
1583 * @transient: whenever to allocate the result from the heap or from a mempool
1585 * Decode a compressed type description found at @ptr in @m.
1586 * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
1587 * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
1588 * This function can be used to decode type descriptions in method signatures,
1589 * field signatures, locals signatures etc.
1591 * To parse a generic type, `generic_container' points to the current class'es
1592 * (the `generic_container' field in the MonoClass) or the current generic method's
1593 * (stored in image->property_hash) generic container.
1594 * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
1595 * this MonoGenericContainer.
1597 * LOCKING: Acquires the loader lock.
1599 * Returns: a #MonoType structure representing the decoded type.
1602 mono_metadata_parse_type_internal (MonoImage
*m
, MonoGenericContainer
*container
,
1603 short opt_attrs
, gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1605 MonoType
*type
, *cached
;
1607 gboolean byref
= FALSE
;
1608 gboolean pinned
= FALSE
;
1609 const char *tmp_ptr
;
1610 int count
= 0; // Number of mod arguments
1613 mono_error_init (error
);
1616 * According to the spec, custom modifiers should come before the byref
1617 * flag, but the IL produced by ilasm from the following signature:
1618 * object modopt(...) &
1619 * starts with a byref flag, followed by the modifiers. (bug #49802)
1620 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1621 * it would be better to treat byref as real type constructor instead of
1623 * Also, pinned should come before anything else, but some MSV++ produced
1624 * assemblies violate this (#bug 61990).
1627 /* Count the modifiers first */
1632 case MONO_TYPE_PINNED
:
1633 case MONO_TYPE_BYREF
:
1636 case MONO_TYPE_CMOD_REQD
:
1637 case MONO_TYPE_CMOD_OPT
:
1639 mono_metadata_parse_custom_mod (m
, NULL
, tmp_ptr
, &tmp_ptr
);
1646 if (count
) { // There are mods, so the MonoType will be of nonstandard size.
1649 size
= MONO_SIZEOF_TYPE
+ ((gint32
)count
) * sizeof (MonoCustomMod
);
1650 type
= transient
? (MonoType
*)g_malloc0 (size
) : (MonoType
*)mono_image_alloc0 (m
, size
);
1651 type
->num_mods
= count
;
1653 mono_error_set_bad_image (error
, m
, "Invalid type with more than 64 modifiers");
1656 } else { // The type is of standard size, so we can allocate it on the stack.
1658 memset (type
, 0, MONO_SIZEOF_TYPE
);
1661 /* Iterate again, but now parse pinned, byref and custom modifiers */
1666 case MONO_TYPE_PINNED
:
1670 case MONO_TYPE_BYREF
:
1674 case MONO_TYPE_CMOD_REQD
:
1675 case MONO_TYPE_CMOD_OPT
:
1676 mono_metadata_parse_custom_mod (m
, &(type
->modifiers
[count
]), ptr
, &ptr
);
1684 type
->attrs
= opt_attrs
;
1685 type
->byref
= byref
;
1686 type
->pinned
= pinned
? 1 : 0;
1688 if (!do_mono_metadata_parse_type (type
, m
, container
, transient
, ptr
, &ptr
, error
))
1694 // Possibly we can return an already-allocated type instead of the one we decoded
1695 if (!type
->num_mods
&& !transient
) {
1696 /* no need to free type here, because it is on the stack */
1697 if ((type
->type
== MONO_TYPE_CLASS
|| type
->type
== MONO_TYPE_VALUETYPE
) && !type
->pinned
&& !type
->attrs
) {
1698 MonoType
*ret
= type
->byref
? &type
->data
.klass
->this_arg
: &type
->data
.klass
->byval_arg
;
1700 /* Consider the case:
1702 class Foo<T> { class Bar {} }
1703 class Test : Foo<Test>.Bar {}
1705 When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
1706 a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1708 We ensure that the MonoClass is in a state that we can canonicalize to:
1710 klass->byval_arg.data.klass == klass
1711 klass->this_arg.data.klass == klass
1713 If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1715 LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1716 of a MonoClass which currently holds the loader lock. 'type' is local.
1718 if (ret
->data
.klass
== type
->data
.klass
) {
1722 /* No need to use locking since nobody is modifying the hash table */
1723 if ((cached
= (MonoType
*)g_hash_table_lookup (type_cache
, type
))) {
1728 /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1730 if (type
== &stype
) { // Type was allocated on the stack, so we need to copy it to safety
1731 type
= transient
? (MonoType
*)g_malloc (MONO_SIZEOF_TYPE
) : (MonoType
*)mono_image_alloc (m
, MONO_SIZEOF_TYPE
);
1732 memcpy (type
, &stype
, MONO_SIZEOF_TYPE
);
1739 mono_metadata_parse_type_checked (MonoImage
*m
, MonoGenericContainer
*container
,
1740 short opt_attrs
, gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
1742 return mono_metadata_parse_type_internal (m
, container
, opt_attrs
, transient
, ptr
, rptr
, error
);
1746 * LOCKING: Acquires the loader lock.
1749 mono_metadata_parse_type (MonoImage
*m
, MonoParseTypeMode mode
, short opt_attrs
,
1750 const char *ptr
, const char **rptr
)
1753 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, opt_attrs
, FALSE
, ptr
, rptr
, &error
);
1754 mono_error_cleanup (&error
);
1759 mono_metadata_method_has_param_attrs (MonoImage
*m
, int def
)
1761 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1762 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1763 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1765 if (def
< methodt
->rows
)
1766 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1768 lastp
= m
->tables
[MONO_TABLE_PARAM
].rows
+ 1;
1770 for (i
= param_index
; i
< lastp
; ++i
) {
1771 guint32 flags
= mono_metadata_decode_row_col (paramt
, i
- 1, MONO_PARAM_FLAGS
);
1780 * mono_metadata_get_param_attrs:
1782 * @m The image to loader parameter attributes from
1783 * @def method def token (one based)
1784 * @param_count number of params to decode including the return value
1786 * Return the parameter attributes for the method whose MethodDef index is DEF. The
1787 * returned memory needs to be freed by the caller. If all the param attributes are
1788 * 0, then NULL is returned.
1791 mono_metadata_get_param_attrs (MonoImage
*m
, int def
, int param_count
)
1793 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1794 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1795 guint32 cols
[MONO_PARAM_SIZE
];
1796 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1799 if (def
< methodt
->rows
)
1800 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1802 lastp
= paramt
->rows
+ 1;
1804 for (i
= param_index
; i
< lastp
; ++i
) {
1805 mono_metadata_decode_row (paramt
, i
- 1, cols
, MONO_PARAM_SIZE
);
1806 if (cols
[MONO_PARAM_FLAGS
]) {
1808 pattrs
= g_new0 (int, param_count
);
1809 /* at runtime we just ignore this kind of malformed file:
1810 * the verifier can signal the error to the user
1812 if (cols
[MONO_PARAM_SEQUENCE
] >= param_count
)
1814 pattrs
[cols
[MONO_PARAM_SEQUENCE
]] = cols
[MONO_PARAM_FLAGS
];
1823 * mono_metadata_parse_signature:
1824 * @image: metadata context
1825 * @token: metadata token
1827 * Decode a method signature stored in the STANDALONESIG table
1829 * Returns: a MonoMethodSignature describing the signature.
1831 MonoMethodSignature
*
1832 mono_metadata_parse_signature (MonoImage
*image
, guint32 token
)
1835 MonoMethodSignature
*ret
;
1836 ret
= mono_metadata_parse_signature_checked (image
, token
, &error
);
1837 mono_error_cleanup (&error
);
1842 * mono_metadata_parse_signature_checked:
1843 * @image: metadata context
1844 * @token: metadata token
1845 * @error: set on error
1847 * Decode a method signature stored in the STANDALONESIG table
1849 * Returns: a MonoMethodSignature describing the signature. On failure
1850 * returns NULL and sets @error.
1852 MonoMethodSignature
*
1853 mono_metadata_parse_signature_checked (MonoImage
*image
, guint32 token
, MonoError
*error
)
1856 mono_error_init (error
);
1857 MonoTableInfo
*tables
= image
->tables
;
1858 guint32 idx
= mono_metadata_token_index (token
);
1862 if (image_is_dynamic (image
)) {
1863 return (MonoMethodSignature
*)mono_lookup_dynamic_token (image
, token
, NULL
, error
);
1866 g_assert (mono_metadata_token_table(token
) == MONO_TABLE_STANDALONESIG
);
1868 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
1870 ptr
= mono_metadata_blob_heap (image
, sig
);
1871 mono_metadata_decode_blob_size (ptr
, &ptr
);
1873 return mono_metadata_parse_method_signature_full (image
, NULL
, 0, ptr
, NULL
, error
);
1877 * mono_metadata_signature_alloc:
1878 * @image: metadata context
1879 * @nparmas: number of parameters in the signature
1881 * Allocate a MonoMethodSignature structure with the specified number of params.
1882 * The return type and the params types need to be filled later.
1883 * This is a Mono runtime internal function.
1885 * LOCKING: Assumes the loader lock is held.
1887 * Returns: the new MonoMethodSignature structure.
1889 MonoMethodSignature
*
1890 mono_metadata_signature_alloc (MonoImage
*m
, guint32 nparams
)
1892 MonoMethodSignature
*sig
;
1894 sig
= (MonoMethodSignature
*)mono_image_alloc0 (m
, MONO_SIZEOF_METHOD_SIGNATURE
+ ((gint32
)nparams
) * sizeof (MonoType
*));
1895 sig
->param_count
= nparams
;
1896 sig
->sentinelpos
= -1;
1901 static MonoMethodSignature
*
1902 mono_metadata_signature_dup_internal_with_padding (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
, size_t padding
)
1904 int sigsize
, sig_header_size
;
1905 MonoMethodSignature
*ret
;
1906 sigsize
= sig_header_size
= MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*) + padding
;
1908 sigsize
+= MONO_SIZEOF_TYPE
;
1911 ret
= (MonoMethodSignature
*)mono_image_alloc (image
, sigsize
);
1913 ret
= (MonoMethodSignature
*)mono_mempool_alloc (mp
, sigsize
);
1915 ret
= (MonoMethodSignature
*)g_malloc (sigsize
);
1918 memcpy (ret
, sig
, sig_header_size
- padding
);
1920 // Copy return value because of ownership semantics.
1922 // Danger! Do not alter padding use without changing the dup_add_this below
1923 intptr_t end_of_header
= (intptr_t)( (char*)(ret
) + sig_header_size
);
1924 ret
->ret
= (MonoType
*)end_of_header
;
1925 memcpy (ret
->ret
, sig
->ret
, MONO_SIZEOF_TYPE
);
1931 static MonoMethodSignature
*
1932 mono_metadata_signature_dup_internal (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1934 return mono_metadata_signature_dup_internal_with_padding (image
, mp
, sig
, 0);
1937 * signature_dup_add_this:
1939 * Make a copy of @sig, adding an explicit this argument.
1941 MonoMethodSignature
*
1942 mono_metadata_signature_dup_add_this (MonoImage
*image
, MonoMethodSignature
*sig
, MonoClass
*klass
)
1944 MonoMethodSignature
*ret
;
1945 ret
= mono_metadata_signature_dup_internal_with_padding (image
, NULL
, sig
, sizeof (MonoType
*));
1947 ret
->param_count
= sig
->param_count
+ 1;
1948 ret
->hasthis
= FALSE
;
1950 for (int i
= sig
->param_count
- 1; i
>= 0; i
--)
1951 ret
->params
[i
+ 1] = sig
->params
[i
];
1952 ret
->params
[0] = klass
->valuetype
? &klass
->this_arg
: &klass
->byval_arg
;
1954 for (int i
= sig
->param_count
- 1; i
>= 0; i
--)
1955 g_assert(ret
->params
[i
+ 1]->type
== sig
->params
[i
]->type
&& ret
->params
[i
+1]->type
!= MONO_TYPE_END
);
1956 g_assert (ret
->ret
->type
== sig
->ret
->type
&& ret
->ret
->type
!= MONO_TYPE_END
);
1963 MonoMethodSignature
*
1964 mono_metadata_signature_dup_full (MonoImage
*image
, MonoMethodSignature
*sig
)
1966 MonoMethodSignature
*ret
= mono_metadata_signature_dup_internal (image
, NULL
, sig
);
1968 for (int i
= 0 ; i
< sig
->param_count
; i
++)
1969 g_assert(ret
->params
[i
]->type
== sig
->params
[i
]->type
);
1970 g_assert (ret
->ret
->type
== sig
->ret
->type
);
1975 /*The mempool is accessed without synchronization*/
1976 MonoMethodSignature
*
1977 mono_metadata_signature_dup_mempool (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1979 return mono_metadata_signature_dup_internal (NULL
, mp
, sig
);
1983 * mono_metadata_signature_dup:
1984 * @sig: method signature
1986 * Duplicate an existing MonoMethodSignature so it can be modified.
1987 * This is a Mono runtime internal function.
1989 * Returns: the new MonoMethodSignature structure.
1991 MonoMethodSignature
*
1992 mono_metadata_signature_dup (MonoMethodSignature
*sig
)
1994 return mono_metadata_signature_dup_full (NULL
, sig
);
1998 * mono_metadata_signature_size:
2000 * Return the amount of memory allocated to SIG.
2003 mono_metadata_signature_size (MonoMethodSignature
*sig
)
2005 return MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*);
2009 * mono_metadata_parse_method_signature:
2010 * @m: metadata context
2011 * @generic_container: generics container
2012 * @def: the MethodDef index or 0 for Ref signatures.
2013 * @ptr: pointer to the signature metadata representation
2014 * @rptr: pointer updated to match the end of the decoded stream
2016 * Decode a method signature stored at @ptr.
2017 * This is a Mono runtime internal function.
2019 * LOCKING: Assumes the loader lock is held.
2021 * Returns: a MonoMethodSignature describing the signature.
2023 MonoMethodSignature
*
2024 mono_metadata_parse_method_signature_full (MonoImage
*m
, MonoGenericContainer
*container
,
2025 int def
, const char *ptr
, const char **rptr
, MonoError
*error
)
2027 MonoMethodSignature
*method
;
2028 int i
, *pattrs
= NULL
;
2029 guint32 hasthis
= 0, explicit_this
= 0, call_convention
, param_count
;
2030 guint32 gen_param_count
= 0;
2031 gboolean is_open
= FALSE
;
2033 mono_error_init (error
);
2036 gen_param_count
= 1;
2041 call_convention
= *ptr
& 0x0F;
2043 if (gen_param_count
)
2044 gen_param_count
= mono_metadata_decode_value (ptr
, &ptr
);
2045 param_count
= mono_metadata_decode_value (ptr
, &ptr
);
2048 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 */
2050 method
= mono_metadata_signature_alloc (m
, param_count
);
2051 method
->hasthis
= hasthis
;
2052 method
->explicit_this
= explicit_this
;
2053 method
->call_convention
= call_convention
;
2054 method
->generic_param_count
= gen_param_count
;
2056 if (call_convention
!= 0xa) {
2057 method
->ret
= mono_metadata_parse_type_checked (m
, container
, pattrs
? pattrs
[0] : 0, FALSE
, ptr
, &ptr
, error
);
2059 mono_metadata_free_method_signature (method
);
2063 is_open
= mono_class_is_open_constructed_type (method
->ret
);
2066 for (i
= 0; i
< method
->param_count
; ++i
) {
2067 if (*ptr
== MONO_TYPE_SENTINEL
) {
2068 if (method
->call_convention
!= MONO_CALL_VARARG
|| def
) {
2069 mono_error_set_bad_image (error
, m
, "Found sentinel for methoddef or no vararg");
2073 if (method
->sentinelpos
>= 0) {
2074 mono_error_set_bad_image (error
, m
, "Found sentinel twice in the same signature.");
2078 method
->sentinelpos
= i
;
2081 method
->params
[i
] = mono_metadata_parse_type_checked (m
, container
, pattrs
? pattrs
[i
+1] : 0, FALSE
, ptr
, &ptr
, error
);
2082 if (!method
->params
[i
]) {
2083 mono_metadata_free_method_signature (method
);
2088 is_open
= mono_class_is_open_constructed_type (method
->params
[i
]);
2091 /* The sentinel could be missing if the caller does not pass any additional arguments */
2092 if (!def
&& method
->call_convention
== MONO_CALL_VARARG
&& method
->sentinelpos
< 0)
2093 method
->sentinelpos
= method
->param_count
;
2095 method
->has_type_parameters
= is_open
;
2097 if (def
&& (method
->call_convention
== MONO_CALL_VARARG
))
2098 method
->sentinelpos
= method
->param_count
;
2105 * Add signature to a cache and increase ref count...
2112 * mono_metadata_parse_method_signature:
2113 * @m: metadata context
2114 * @def: the MethodDef index or 0 for Ref signatures.
2115 * @ptr: pointer to the signature metadata representation
2116 * @rptr: pointer updated to match the end of the decoded stream
2118 * Decode a method signature stored at @ptr.
2119 * This is a Mono runtime internal function.
2121 * LOCKING: Assumes the loader lock is held.
2123 * Returns: a MonoMethodSignature describing the signature.
2125 MonoMethodSignature
*
2126 mono_metadata_parse_method_signature (MonoImage
*m
, int def
, const char *ptr
, const char **rptr
)
2129 * This function MUST NOT be called by runtime code as it does error handling incorrectly.
2130 * Use mono_metadata_parse_method_signature_full instead.
2131 * It's ok to asser on failure as we no longer use it.
2134 MonoMethodSignature
*ret
;
2135 ret
= mono_metadata_parse_method_signature_full (m
, NULL
, def
, ptr
, rptr
, &error
);
2136 g_assert (mono_error_ok (&error
));
2142 * mono_metadata_free_method_signature:
2143 * @sig: signature to destroy
2145 * Free the memory allocated in the signature @sig.
2146 * This method needs to be robust and work also on partially-built
2147 * signatures, so it does extra checks.
2150 mono_metadata_free_method_signature (MonoMethodSignature
*sig
)
2152 /* Everything is allocated from mempools */
2156 mono_metadata_free_type (sig->ret);
2157 for (i = 0; i < sig->param_count; ++i) {
2158 if (sig->params [i])
2159 mono_metadata_free_type (sig->params [i]);
2165 mono_metadata_free_inflated_signature (MonoMethodSignature
*sig
)
2169 /* Allocated in inflate_generic_signature () */
2171 mono_metadata_free_type (sig
->ret
);
2172 for (i
= 0; i
< sig
->param_count
; ++i
) {
2173 if (sig
->params
[i
])
2174 mono_metadata_free_type (sig
->params
[i
]);
2180 inflated_method_equal (gconstpointer a
, gconstpointer b
)
2182 const MonoMethodInflated
*ma
= (const MonoMethodInflated
*)a
;
2183 const MonoMethodInflated
*mb
= (const MonoMethodInflated
*)b
;
2184 if (ma
->declaring
!= mb
->declaring
)
2186 return mono_metadata_generic_context_equal (&ma
->context
, &mb
->context
);
2190 inflated_method_hash (gconstpointer a
)
2192 const MonoMethodInflated
*ma
= (const MonoMethodInflated
*)a
;
2193 return (mono_metadata_generic_context_hash (&ma
->context
) ^ mono_aligned_addr_hash (ma
->declaring
));
2197 inflated_signature_equal (gconstpointer a
, gconstpointer b
)
2199 const MonoInflatedMethodSignature
*sig1
= (const MonoInflatedMethodSignature
*)a
;
2200 const MonoInflatedMethodSignature
*sig2
= (const MonoInflatedMethodSignature
*)b
;
2202 /* sig->sig is assumed to be canonized */
2203 if (sig1
->sig
!= sig2
->sig
)
2205 /* The generic instances are canonized */
2206 return mono_metadata_generic_context_equal (&sig1
->context
, &sig2
->context
);
2210 inflated_signature_hash (gconstpointer a
)
2212 const MonoInflatedMethodSignature
*sig
= (const MonoInflatedMethodSignature
*)a
;
2214 /* sig->sig is assumed to be canonized */
2215 return mono_metadata_generic_context_hash (&sig
->context
) ^ mono_aligned_addr_hash (sig
->sig
);
2219 dump_ginst (MonoGenericInst *ginst)
2224 g_print ("Ginst: <");
2225 for (i = 0; i < ginst->type_argc; ++i) {
2228 name = mono_type_get_name (ginst->type_argv [i]);
2229 g_print ("%s", name);
2235 static gboolean
type_in_image (MonoType
*type
, MonoImage
*image
);
2238 signature_in_image (MonoMethodSignature
*sig
, MonoImage
*image
)
2240 gpointer iter
= NULL
;
2243 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2244 if (type_in_image (p
, image
))
2247 return type_in_image (mono_signature_get_return_type (sig
), image
);
2251 ginst_in_image (MonoGenericInst
*ginst
, MonoImage
*image
)
2255 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2256 if (type_in_image (ginst
->type_argv
[i
], image
))
2264 gclass_in_image (MonoGenericClass
*gclass
, MonoImage
*image
)
2266 return gclass
->container_class
->image
== image
||
2267 ginst_in_image (gclass
->context
.class_inst
, image
);
2271 type_in_image (MonoType
*type
, MonoImage
*image
)
2274 switch (type
->type
) {
2275 case MONO_TYPE_GENERICINST
:
2276 return gclass_in_image (type
->data
.generic_class
, image
);
2278 type
= type
->data
.type
;
2280 case MONO_TYPE_SZARRAY
:
2281 type
= &type
->data
.klass
->byval_arg
;
2283 case MONO_TYPE_ARRAY
:
2284 type
= &type
->data
.array
->eklass
->byval_arg
;
2286 case MONO_TYPE_FNPTR
:
2287 return signature_in_image (type
->data
.method
, image
);
2289 case MONO_TYPE_MVAR
:
2290 return image
== get_image_for_generic_param (type
->data
.generic_param
);
2292 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2293 return image
== mono_class_from_mono_type (type
)->image
;
2298 image_sets_lock (void)
2300 mono_os_mutex_lock (&image_sets_mutex
);
2304 image_sets_unlock (void)
2306 mono_os_mutex_unlock (&image_sets_mutex
);
2312 * Return a MonoImageSet representing the set of images in IMAGES.
2314 static MonoImageSet
*
2315 get_image_set (MonoImage
**images
, int nimages
)
2321 /* Common case: Image set contains corlib only. If we've seen that case before, we cached the set. */
2322 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
&& mscorlib_image_set
)
2323 return mscorlib_image_set
;
2325 /* Happens with empty generic instances */
2326 // 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.
2328 return mscorlib_image_set
;
2333 image_sets
= g_ptr_array_new ();
2335 // Before we go on, we should check to see whether a MonoImageSet with these images already exists.
2336 // We can search the referred-by imagesets of any one of our images to do this. Arbitrarily pick one here:
2337 if (images
[0] == mono_defaults
.corlib
&& nimages
> 1)
2338 l
= images
[1]->image_sets
; // Prefer not to search the imagesets of corlib-- that will be a long list.
2340 l
= images
[0]->image_sets
;
2343 while (l
) // Iterate over selected list, looking for an imageset with members equal to our target one
2345 set
= (MonoImageSet
*)l
->data
;
2347 if (set
->nimages
== nimages
) { // Member count differs, this can't be it
2348 // Compare all members to all members-- order might be different
2349 for (j
= 0; j
< nimages
; ++j
) {
2350 for (k
= 0; k
< nimages
; ++k
)
2351 if (set
->images
[k
] == images
[j
])
2352 break; // Break on match
2354 // If we iterated all the way through set->images, images[j] was *not* found.
2356 break; // Break on "image not found"
2359 // If we iterated all the way through images without breaking, all items in images were found in set->images
2361 break; // Break on "found a set with equal members"
2367 // If we iterated all the way through l without breaking, the imageset does not already exist and we shuold create it
2369 set
= g_new0 (MonoImageSet
, 1);
2370 set
->nimages
= nimages
;
2371 set
->images
= g_new0 (MonoImage
*, nimages
);
2372 mono_os_mutex_init_recursive (&set
->lock
);
2373 for (i
= 0; i
< nimages
; ++i
)
2374 set
->images
[i
] = images
[i
];
2375 set
->gclass_cache
= g_hash_table_new_full (mono_generic_class_hash
, mono_generic_class_equal
, NULL
, (GDestroyNotify
)free_generic_class
);
2376 set
->ginst_cache
= g_hash_table_new_full (mono_metadata_generic_inst_hash
, mono_metadata_generic_inst_equal
, NULL
, (GDestroyNotify
)free_generic_inst
);
2377 set
->gmethod_cache
= g_hash_table_new_full (inflated_method_hash
, inflated_method_equal
, NULL
, (GDestroyNotify
)free_inflated_method
);
2378 set
->gsignature_cache
= g_hash_table_new_full (inflated_signature_hash
, inflated_signature_equal
, NULL
, (GDestroyNotify
)free_inflated_signature
);
2380 for (i
= 0; i
< nimages
; ++i
)
2381 set
->images
[i
]->image_sets
= g_slist_prepend (set
->images
[i
]->image_sets
, set
);
2383 g_ptr_array_add (image_sets
, set
);
2386 if (nimages
== 1 && images
[0] == mono_defaults
.corlib
) {
2387 mono_memory_barrier ();
2388 mscorlib_image_set
= set
;
2391 image_sets_unlock ();
2397 delete_image_set (MonoImageSet
*set
)
2401 g_hash_table_destroy (set
->gclass_cache
);
2402 g_hash_table_destroy (set
->ginst_cache
);
2403 g_hash_table_destroy (set
->gmethod_cache
);
2404 g_hash_table_destroy (set
->gsignature_cache
);
2406 mono_wrapper_caches_free (&set
->wrapper_caches
);
2410 for (i
= 0; i
< set
->nimages
; ++i
)
2411 set
->images
[i
]->image_sets
= g_slist_remove (set
->images
[i
]->image_sets
, set
);
2413 g_ptr_array_remove (image_sets
, set
);
2415 image_sets_unlock ();
2418 mono_mempool_destroy (set
->mempool
);
2419 g_free (set
->images
);
2420 mono_os_mutex_destroy (&set
->lock
);
2425 mono_image_set_lock (MonoImageSet
*set
)
2427 mono_os_mutex_lock (&set
->lock
);
2431 mono_image_set_unlock (MonoImageSet
*set
)
2433 mono_os_mutex_unlock (&set
->lock
);
2437 mono_image_set_alloc (MonoImageSet
*set
, guint size
)
2441 mono_image_set_lock (set
);
2443 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2444 res
= mono_mempool_alloc (set
->mempool
, size
);
2445 mono_image_set_unlock (set
);
2451 mono_image_set_alloc0 (MonoImageSet
*set
, guint size
)
2455 mono_image_set_lock (set
);
2457 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2458 res
= mono_mempool_alloc0 (set
->mempool
, size
);
2459 mono_image_set_unlock (set
);
2465 mono_image_set_strdup (MonoImageSet
*set
, const char *s
)
2469 mono_image_set_lock (set
);
2471 set
->mempool
= mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE
);
2472 res
= mono_mempool_strdup (set
->mempool
, s
);
2473 mono_image_set_unlock (set
);
2478 // Get a descriptive string for a MonoImageSet
2479 // Callers are obligated to free buffer with g_free after use
2481 mono_image_set_description (MonoImageSet
*set
)
2483 GString
*result
= g_string_new (NULL
);
2485 g_string_append (result
, "[");
2486 for (img
= 0; img
< set
->nimages
; img
++)
2489 g_string_append (result
, ", ");
2490 g_string_append (result
, set
->images
[img
]->name
);
2492 g_string_append (result
, "]");
2493 return g_string_free (result
, FALSE
);
2497 * Structure used by the collect_..._images functions to store the image list.
2500 MonoImage
*image_buf
[64];
2502 int nimages
, images_len
;
2506 collect_data_init (CollectData
*data
)
2508 data
->images
= data
->image_buf
;
2509 data
->images_len
= 64;
2514 collect_data_free (CollectData
*data
)
2516 if (data
->images
!= data
->image_buf
)
2517 g_free (data
->images
);
2521 enlarge_data (CollectData
*data
)
2523 int new_len
= data
->images_len
< 16 ? 16 : data
->images_len
* 2;
2524 MonoImage
**d
= g_new (MonoImage
*, new_len
);
2527 g_assert_not_reached ();
2528 memcpy (d
, data
->images
, data
->images_len
);
2529 if (data
->images
!= data
->image_buf
)
2530 g_free (data
->images
);
2532 data
->images_len
= new_len
;
2536 add_image (MonoImage
*image
, CollectData
*data
)
2540 /* The arrays are small, so use a linear search instead of a hash table */
2541 for (i
= 0; i
< data
->nimages
; ++i
)
2542 if (data
->images
[i
] == image
)
2545 if (data
->nimages
== data
->images_len
)
2546 enlarge_data (data
);
2548 data
->images
[data
->nimages
++] = image
;
2552 collect_type_images (MonoType
*type
, CollectData
*data
);
2555 collect_ginst_images (MonoGenericInst
*ginst
, CollectData
*data
)
2559 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2560 collect_type_images (ginst
->type_argv
[i
], data
);
2565 collect_gclass_images (MonoGenericClass
*gclass
, CollectData
*data
)
2567 add_image (gclass
->container_class
->image
, data
);
2568 if (gclass
->context
.class_inst
)
2569 collect_ginst_images (gclass
->context
.class_inst
, data
);
2573 collect_signature_images (MonoMethodSignature
*sig
, CollectData
*data
)
2575 gpointer iter
= NULL
;
2578 collect_type_images (mono_signature_get_return_type (sig
), data
);
2579 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2580 collect_type_images (p
, data
);
2584 collect_inflated_signature_images (MonoInflatedMethodSignature
*sig
, CollectData
*data
)
2586 collect_signature_images (sig
->sig
, data
);
2587 if (sig
->context
.class_inst
)
2588 collect_ginst_images (sig
->context
.class_inst
, data
);
2589 if (sig
->context
.method_inst
)
2590 collect_ginst_images (sig
->context
.method_inst
, data
);
2594 collect_method_images (MonoMethodInflated
*method
, CollectData
*data
)
2596 MonoMethod
*m
= method
->declaring
;
2598 add_image (method
->declaring
->klass
->image
, data
);
2599 if (method
->context
.class_inst
)
2600 collect_ginst_images (method
->context
.class_inst
, data
);
2601 if (method
->context
.method_inst
)
2602 collect_ginst_images (method
->context
.method_inst
, data
);
2604 * Dynamic assemblies have no references, so the images they depend on can be unloaded before them.
2606 if (image_is_dynamic (m
->klass
->image
))
2607 collect_signature_images (mono_method_signature (m
), data
);
2611 collect_type_images (MonoType
*type
, CollectData
*data
)
2614 switch (type
->type
) {
2615 case MONO_TYPE_GENERICINST
:
2616 collect_gclass_images (type
->data
.generic_class
, data
);
2619 type
= type
->data
.type
;
2621 case MONO_TYPE_SZARRAY
:
2622 type
= &type
->data
.klass
->byval_arg
;
2624 case MONO_TYPE_ARRAY
:
2625 type
= &type
->data
.array
->eklass
->byval_arg
;
2627 case MONO_TYPE_FNPTR
:
2628 //return signature_in_image (type->data.method, image);
2629 g_assert_not_reached ();
2631 case MONO_TYPE_MVAR
:
2633 MonoImage
*image
= get_image_for_generic_param (type
->data
.generic_param
);
2634 add_image (image
, data
);
2637 case MONO_TYPE_CLASS
:
2638 case MONO_TYPE_VALUETYPE
:
2639 add_image (mono_class_from_mono_type (type
)->image
, data
);
2642 add_image (mono_defaults
.corlib
, data
);
2649 } CleanForImageUserData
;
2652 steal_gclass_in_image (gpointer key
, gpointer value
, gpointer data
)
2654 MonoGenericClass
*gclass
= (MonoGenericClass
*)key
;
2655 CleanForImageUserData
*user_data
= (CleanForImageUserData
*)data
;
2657 g_assert (gclass_in_image (gclass
, user_data
->image
));
2659 user_data
->list
= g_slist_prepend (user_data
->list
, gclass
);
2664 steal_ginst_in_image (gpointer key
, gpointer value
, gpointer data
)
2666 MonoGenericInst
*ginst
= (MonoGenericInst
*)key
;
2667 CleanForImageUserData
*user_data
= (CleanForImageUserData
*)data
;
2669 // This doesn't work during corlib compilation
2670 //g_assert (ginst_in_image (ginst, user_data->image));
2672 user_data
->list
= g_slist_prepend (user_data
->list
, ginst
);
2677 inflated_method_in_image (gpointer key
, gpointer value
, gpointer data
)
2679 MonoImage
*image
= (MonoImage
*)data
;
2680 MonoMethodInflated
*method
= (MonoMethodInflated
*)key
;
2683 // https://bugzilla.novell.com/show_bug.cgi?id=458168
2684 g_assert (method
->declaring
->klass
->image
== image
||
2685 (method
->context
.class_inst
&& ginst_in_image (method
->context
.class_inst
, image
)) ||
2686 (method
->context
.method_inst
&& ginst_in_image (method
->context
.method_inst
, image
)) || (((MonoMethod
*)method
)->signature
&& signature_in_image (mono_method_signature ((MonoMethod
*)method
), image
)));
2692 inflated_signature_in_image (gpointer key
, gpointer value
, gpointer data
)
2694 MonoImage
*image
= (MonoImage
*)data
;
2695 MonoInflatedMethodSignature
*sig
= (MonoInflatedMethodSignature
*)key
;
2697 return signature_in_image (sig
->sig
, image
) ||
2698 (sig
->context
.class_inst
&& ginst_in_image (sig
->context
.class_inst
, image
)) ||
2699 (sig
->context
.method_inst
&& ginst_in_image (sig
->context
.method_inst
, image
));
2703 check_gmethod (gpointer key
, gpointer value
, gpointer data
)
2705 MonoMethodInflated
*method
= (MonoMethodInflated
*)key
;
2706 MonoImage
*image
= (MonoImage
*)data
;
2708 if (method
->context
.class_inst
)
2709 g_assert (!ginst_in_image (method
->context
.class_inst
, image
));
2710 if (method
->context
.method_inst
)
2711 g_assert (!ginst_in_image (method
->context
.method_inst
, image
));
2712 if (((MonoMethod
*)method
)->signature
)
2713 g_assert (!signature_in_image (mono_method_signature ((MonoMethod
*)method
), image
));
2719 * Run a consistency check on the image set data structures.
2721 static G_GNUC_UNUSED
void
2722 check_image_sets (MonoImage
*image
)
2725 GSList
*l
= image
->image_sets
;
2730 for (i
= 0; i
< image_sets
->len
; ++i
) {
2731 MonoImageSet
*set
= (MonoImageSet
*)g_ptr_array_index (image_sets
, i
);
2733 if (!g_slist_find (l
, set
)) {
2734 g_hash_table_foreach (set
->gmethod_cache
, check_gmethod
, image
);
2740 mono_metadata_clean_for_image (MonoImage
*image
)
2742 CleanForImageUserData ginst_data
, gclass_data
;
2743 GSList
*l
, *set_list
;
2745 //check_image_sets (image);
2748 * The data structures could reference each other so we delete them in two phases.
2749 * This is required because of the hashing functions in gclass/ginst_cache.
2751 ginst_data
.image
= gclass_data
.image
= image
;
2752 ginst_data
.list
= gclass_data
.list
= NULL
;
2754 /* Collect the items to delete */
2755 /* delete_image_set () modifies the lists so make a copy */
2756 for (l
= image
->image_sets
; l
; l
= l
->next
) {
2757 MonoImageSet
*set
= (MonoImageSet
*)l
->data
;
2759 mono_image_set_lock (set
);
2760 g_hash_table_foreach_steal (set
->gclass_cache
, steal_gclass_in_image
, &gclass_data
);
2761 g_hash_table_foreach_steal (set
->ginst_cache
, steal_ginst_in_image
, &ginst_data
);
2762 g_hash_table_foreach_remove (set
->gmethod_cache
, inflated_method_in_image
, image
);
2763 g_hash_table_foreach_remove (set
->gsignature_cache
, inflated_signature_in_image
, image
);
2764 mono_image_set_unlock (set
);
2767 /* Delete the removed items */
2768 for (l
= ginst_data
.list
; l
; l
= l
->next
)
2769 free_generic_inst ((MonoGenericInst
*)l
->data
);
2770 for (l
= gclass_data
.list
; l
; l
= l
->next
)
2771 free_generic_class ((MonoGenericClass
*)l
->data
);
2772 g_slist_free (ginst_data
.list
);
2773 g_slist_free (gclass_data
.list
);
2774 /* delete_image_set () modifies the lists so make a copy */
2775 set_list
= g_slist_copy (image
->image_sets
);
2776 for (l
= set_list
; l
; l
= l
->next
) {
2777 MonoImageSet
*set
= (MonoImageSet
*)l
->data
;
2779 delete_image_set (set
);
2781 g_slist_free (set_list
);
2785 free_inflated_method (MonoMethodInflated
*imethod
)
2787 MonoMethod
*method
= (MonoMethod
*)imethod
;
2789 if (method
->signature
)
2790 mono_metadata_free_inflated_signature (method
->signature
);
2796 free_generic_inst (MonoGenericInst
*ginst
)
2800 /* The ginst itself is allocated from the image set mempool */
2801 for (i
= 0; i
< ginst
->type_argc
; ++i
)
2802 mono_metadata_free_type (ginst
->type_argv
[i
]);
2806 free_generic_class (MonoGenericClass
*gclass
)
2808 /* The gclass itself is allocated from the image set mempool */
2809 if (gclass
->is_dynamic
)
2810 mono_reflection_free_dynamic_generic_class (gclass
);
2811 if (gclass
->cached_class
&& gclass
->cached_class
->interface_id
)
2812 mono_unload_interface_id (gclass
->cached_class
);
2816 free_inflated_signature (MonoInflatedMethodSignature
*sig
)
2818 mono_metadata_free_inflated_signature (sig
->sig
);
2823 * mono_metadata_get_inflated_signature:
2825 * Given an inflated signature and a generic context, return a canonical copy of the
2826 * signature. The returned signature might be equal to SIG or it might be a cached copy.
2828 MonoMethodSignature
*
2829 mono_metadata_get_inflated_signature (MonoMethodSignature
*sig
, MonoGenericContext
*context
)
2831 MonoInflatedMethodSignature helper
;
2832 MonoInflatedMethodSignature
*res
;
2837 helper
.context
.class_inst
= context
->class_inst
;
2838 helper
.context
.method_inst
= context
->method_inst
;
2840 collect_data_init (&data
);
2842 collect_inflated_signature_images (&helper
, &data
);
2844 set
= get_image_set (data
.images
, data
.nimages
);
2846 collect_data_free (&data
);
2848 mono_image_set_lock (set
);
2850 res
= (MonoInflatedMethodSignature
*)g_hash_table_lookup (set
->gsignature_cache
, &helper
);
2852 res
= g_new0 (MonoInflatedMethodSignature
, 1);
2854 res
->context
.class_inst
= context
->class_inst
;
2855 res
->context
.method_inst
= context
->method_inst
;
2856 g_hash_table_insert (set
->gsignature_cache
, res
, res
);
2859 mono_image_set_unlock (set
);
2865 mono_metadata_get_image_set_for_method (MonoMethodInflated
*method
)
2868 CollectData image_set_data
;
2870 collect_data_init (&image_set_data
);
2871 collect_method_images (method
, &image_set_data
);
2872 set
= get_image_set (image_set_data
.images
, image_set_data
.nimages
);
2873 collect_data_free (&image_set_data
);
2879 * mono_metadata_get_generic_inst:
2881 * Given a list of types, return a MonoGenericInst that represents that list.
2882 * The returned MonoGenericInst has its own copy of the list of types. The list
2883 * passed in the argument can be freed, modified or disposed of.
2887 mono_metadata_get_generic_inst (int type_argc
, MonoType
**type_argv
)
2889 MonoGenericInst
*ginst
;
2892 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
2896 for (i
= 0; i
< type_argc
; ++i
)
2897 if (mono_class_is_open_constructed_type (type_argv
[i
]))
2899 is_open
= (i
< type_argc
);
2901 ginst
= (MonoGenericInst
*)g_alloca (size
);
2902 memset (ginst
, 0, sizeof (MonoGenericInst
));
2903 ginst
->is_open
= is_open
;
2904 ginst
->type_argc
= type_argc
;
2905 memcpy (ginst
->type_argv
, type_argv
, type_argc
* sizeof (MonoType
*));
2907 collect_data_init (&data
);
2909 collect_ginst_images (ginst
, &data
);
2911 set
= get_image_set (data
.images
, data
.nimages
);
2913 collect_data_free (&data
);
2915 mono_image_set_lock (set
);
2917 ginst
= (MonoGenericInst
*)g_hash_table_lookup (set
->ginst_cache
, ginst
);
2919 ginst
= (MonoGenericInst
*)mono_image_set_alloc0 (set
, size
);
2920 #ifndef MONO_SMALL_CONFIG
2921 ginst
->id
= ++next_generic_inst_id
;
2923 ginst
->is_open
= is_open
;
2924 ginst
->type_argc
= type_argc
;
2926 for (i
= 0; i
< type_argc
; ++i
)
2927 ginst
->type_argv
[i
] = mono_metadata_type_dup (NULL
, type_argv
[i
]);
2929 g_hash_table_insert (set
->ginst_cache
, ginst
, ginst
);
2932 mono_image_set_unlock (set
);
2937 mono_metadata_is_type_builder_generic_type_definition (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
2939 MonoGenericContainer
*container
= container_class
->generic_container
;
2941 if (!is_dynamic
|| container_class
->wastypebuilder
|| container
->type_argc
!= inst
->type_argc
)
2943 return inst
== container
->context
.class_inst
;
2947 * mono_metadata_lookup_generic_class:
2949 * Returns a MonoGenericClass with the given properties.
2953 mono_metadata_lookup_generic_class (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
2955 MonoGenericClass
*gclass
;
2956 MonoGenericClass helper
;
2957 gboolean is_tb_open
= mono_metadata_is_type_builder_generic_type_definition (container_class
, inst
, is_dynamic
);
2961 memset (&helper
, 0, sizeof(helper
)); // act like g_new0
2962 helper
.container_class
= container_class
;
2963 helper
.context
.class_inst
= inst
;
2964 helper
.is_dynamic
= is_dynamic
; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
2965 helper
.is_tb_open
= is_tb_open
;
2967 collect_data_init (&data
);
2969 collect_gclass_images (&helper
, &data
);
2971 set
= get_image_set (data
.images
, data
.nimages
);
2973 collect_data_free (&data
);
2975 mono_image_set_lock (set
);
2977 gclass
= (MonoGenericClass
*)g_hash_table_lookup (set
->gclass_cache
, &helper
);
2979 /* A tripwire just to keep us honest */
2980 g_assert (!helper
.cached_class
);
2983 mono_image_set_unlock (set
);
2988 MonoDynamicGenericClass
*dgclass
= mono_image_set_new0 (set
, MonoDynamicGenericClass
, 1);
2989 gclass
= &dgclass
->generic_class
;
2990 gclass
->is_dynamic
= 1;
2992 gclass
= mono_image_set_new0 (set
, MonoGenericClass
, 1);
2995 gclass
->is_tb_open
= is_tb_open
;
2996 gclass
->container_class
= container_class
;
2997 gclass
->context
.class_inst
= inst
;
2998 gclass
->context
.method_inst
= NULL
;
2999 gclass
->owner
= set
;
3000 if (inst
== container_class
->generic_container
->context
.class_inst
&& !is_tb_open
)
3001 gclass
->cached_class
= container_class
;
3003 g_hash_table_insert (set
->gclass_cache
, gclass
, gclass
);
3005 mono_image_set_unlock (set
);
3011 * mono_metadata_inflate_generic_inst:
3013 * Instantiate the generic instance @ginst with the context @context.
3014 * Check @error for success.
3018 mono_metadata_inflate_generic_inst (MonoGenericInst
*ginst
, MonoGenericContext
*context
, MonoError
*error
)
3020 MonoType
**type_argv
;
3021 MonoGenericInst
*nginst
= NULL
;
3024 mono_error_init (error
);
3026 if (!ginst
->is_open
)
3029 type_argv
= g_new0 (MonoType
*, ginst
->type_argc
);
3031 for (i
= 0; i
< ginst
->type_argc
; i
++) {
3032 type_argv
[i
] = mono_class_inflate_generic_type_checked (ginst
->type_argv
[i
], context
, error
);
3033 if (!mono_error_ok (error
))
3038 nginst
= mono_metadata_get_generic_inst (ginst
->type_argc
, type_argv
);
3041 for (i
= 0; i
< count
; i
++)
3042 mono_metadata_free_type (type_argv
[i
]);
3049 mono_metadata_parse_generic_inst (MonoImage
*m
, MonoGenericContainer
*container
,
3050 int count
, const char *ptr
, const char **rptr
, MonoError
*error
)
3052 MonoType
**type_argv
;
3053 MonoGenericInst
*ginst
;
3056 mono_error_init (error
);
3057 type_argv
= g_new0 (MonoType
*, count
);
3059 for (i
= 0; i
< count
; i
++) {
3060 MonoType
*t
= mono_metadata_parse_type_checked (m
, container
, 0, FALSE
, ptr
, &ptr
, error
);
3071 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
3079 do_mono_metadata_parse_generic_class (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
3080 const char *ptr
, const char **rptr
, MonoError
*error
)
3082 MonoGenericInst
*inst
;
3087 mono_error_init (error
);
3089 // XXX how about transient?
3090 gtype
= mono_metadata_parse_type_checked (m
, NULL
, 0, FALSE
, ptr
, &ptr
, error
);
3094 gklass
= mono_class_from_mono_type (gtype
);
3095 if (!gklass
->generic_container
) {
3096 mono_error_set_bad_image (error
, m
, "Generic instance with non-generic definition");
3100 count
= mono_metadata_decode_value (ptr
, &ptr
);
3101 inst
= mono_metadata_parse_generic_inst (m
, container
, count
, ptr
, &ptr
, error
);
3108 type
->data
.generic_class
= mono_metadata_lookup_generic_class (gklass
, inst
, FALSE
);
3114 * @gc: The generic container to normalize
3115 * @type: The kind of generic parameters the resulting generic-container should contain
3118 static MonoGenericContainer
*
3119 select_container (MonoGenericContainer
*gc
, MonoTypeEnum type
)
3121 gboolean is_var
= (type
== MONO_TYPE_VAR
);
3125 g_assert (is_var
|| type
== MONO_TYPE_MVAR
);
3128 if (gc
->is_method
|| gc
->parent
)
3130 * The current MonoGenericContainer is a generic method -> its `parent'
3131 * points to the containing class'es container.
3139 MonoGenericContainer
*
3140 get_anonymous_container_for_image (MonoImage
*image
, gboolean is_mvar
)
3142 MonoGenericContainer
**container_pointer
;
3144 container_pointer
= &image
->anonymous_generic_method_container
;
3146 container_pointer
= &image
->anonymous_generic_class_container
;
3147 MonoGenericContainer
*result
= *container_pointer
;
3149 // This container has never been created; make it now.
3152 // Note this is never deallocated anywhere-- it exists for the lifetime of the image it's allocated from
3153 result
= (MonoGenericContainer
*)mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
3154 result
->owner
.image
= image
;
3155 result
->is_anonymous
= TRUE
;
3156 result
->is_small_param
= TRUE
;
3157 result
->is_method
= is_mvar
;
3159 // If another thread already made a container, use that and leak this new one.
3160 // (Technically it would currently be safe to just assign instead of CASing.)
3161 MonoGenericContainer
*exchange
= (MonoGenericContainer
*)InterlockedCompareExchangePointer ((volatile gpointer
*)container_pointer
, result
, NULL
);
3169 * mono_metadata_parse_generic_param:
3170 * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3171 * see mono_metadata_parse_type_checked() for details.
3172 * Internal routine to parse a generic type parameter.
3173 * LOCKING: Acquires the loader lock
3175 static MonoGenericParam
*
3176 mono_metadata_parse_generic_param (MonoImage
*m
, MonoGenericContainer
*generic_container
,
3177 MonoTypeEnum type
, const char *ptr
, const char **rptr
, MonoError
*error
)
3179 int index
= mono_metadata_decode_value (ptr
, &ptr
);
3183 mono_error_init (error
);
3185 generic_container
= select_container (generic_container
, type
);
3186 if (!generic_container
) {
3187 gboolean is_mvar
= FALSE
;
3192 case MONO_TYPE_MVAR
:
3196 g_error ("Cerating generic param object with invalid MonoType"); // This is not a generic param
3199 /* Create dummy MonoGenericParam */
3200 MonoGenericParam
*param
;
3202 param
= (MonoGenericParam
*)mono_image_alloc0 (m
, sizeof (MonoGenericParam
));
3204 param
->owner
= get_anonymous_container_for_image (m
, is_mvar
);
3209 if (index
>= generic_container
->type_argc
) {
3210 mono_error_set_bad_image (error
, m
, "Invalid generic %s parameter index %d, max index is %d",
3211 generic_container
->is_method
? "method" : "type",
3212 index
, generic_container
->type_argc
);
3216 //This can't return NULL
3217 return mono_generic_container_get_param (generic_container
, index
);
3221 * mono_metadata_get_shared_type:
3223 * Return a shared instance of TYPE, if available, NULL otherwise.
3224 * Shared MonoType instances help save memory. Their contents should not be modified
3225 * by the caller. They do not need to be freed as their lifetime is bound by either
3226 * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3227 * instance they are embedded in. If they are freed, they should be freed using
3228 * mono_metadata_free_type () instead of g_free ().
3231 mono_metadata_get_shared_type (MonoType
*type
)
3235 /* No need to use locking since nobody is modifying the hash table */
3236 if ((cached
= (MonoType
*)g_hash_table_lookup (type_cache
, type
)))
3239 switch (type
->type
){
3240 case MONO_TYPE_CLASS
:
3241 case MONO_TYPE_VALUETYPE
:
3242 if (type
== &type
->data
.klass
->byval_arg
)
3244 if (type
== &type
->data
.klass
->this_arg
)
3255 compare_type_literals (MonoImage
*image
, int class_type
, int type_type
, MonoError
*error
)
3257 mono_error_init (error
);
3259 /* byval_arg.type can be zero if we're decoding a type that references a class been loading.
3260 * See mcs/test/gtest-440. and #650936.
3261 * FIXME This better be moved to the metadata verifier as it can catch more cases.
3265 /* NET 1.1 assemblies might encode string and object in a denormalized way.
3268 if (class_type
== type_type
)
3271 if (type_type
== MONO_TYPE_CLASS
) {
3272 if (class_type
== MONO_TYPE_STRING
|| class_type
== MONO_TYPE_OBJECT
)
3274 //XXX stringify this argument
3275 mono_error_set_bad_image (error
, image
, "Expected reference type but got type kind %d", class_type
);
3279 g_assert (type_type
== MONO_TYPE_VALUETYPE
);
3280 switch (class_type
) {
3281 case MONO_TYPE_BOOLEAN
:
3282 case MONO_TYPE_CHAR
:
3295 case MONO_TYPE_CLASS
:
3298 //XXX stringify this argument
3299 mono_error_set_bad_image (error
, image
, "Expected value type but got type kind %d", class_type
);
3305 verify_var_type_and_container (MonoImage
*image
, int var_type
, MonoGenericContainer
*container
, MonoError
*error
)
3307 mono_error_init (error
);
3308 if (var_type
== MONO_TYPE_MVAR
) {
3309 if (!container
->is_method
) { //MVAR and a method container
3310 mono_error_set_bad_image (error
, image
, "MVAR parsed in a context without a method container");
3314 if (!(!container
->is_method
|| //VAR and class container
3315 (container
->is_method
&& container
->parent
))) { //VAR and method container with parent
3316 mono_error_set_bad_image (error
, image
, "VAR parsed in a context without a class container");
3324 * do_mono_metadata_parse_type:
3325 * @type: MonoType to be filled in with the return value
3327 * @generic_context: generics_context
3328 * @transient: whenever to allocate data from the heap
3329 * @ptr: pointer to the encoded type
3330 * @rptr: pointer where the end of the encoded type is saved
3332 * Internal routine used to "fill" the contents of @type from an
3333 * allocated pointer. This is done this way to avoid doing too
3334 * many mini-allocations (particularly for the MonoFieldType which
3335 * most of the time is just a MonoType, but sometimes might be augmented).
3337 * This routine is used by mono_metadata_parse_type and
3338 * mono_metadata_parse_field_type
3340 * This extracts a Type as specified in Partition II (22.2.12)
3342 * Returns: FALSE if the type could not be loaded
3345 do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
3346 gboolean transient
, const char *ptr
, const char **rptr
, MonoError
*error
)
3348 mono_error_init (error
);
3350 type
->type
= (MonoTypeEnum
)mono_metadata_decode_value (ptr
, &ptr
);
3352 switch (type
->type
){
3353 case MONO_TYPE_VOID
:
3354 case MONO_TYPE_BOOLEAN
:
3355 case MONO_TYPE_CHAR
:
3368 case MONO_TYPE_STRING
:
3369 case MONO_TYPE_OBJECT
:
3370 case MONO_TYPE_TYPEDBYREF
:
3372 case MONO_TYPE_VALUETYPE
:
3373 case MONO_TYPE_CLASS
: {
3376 token
= mono_metadata_parse_typedef_or_ref (m
, ptr
, &ptr
);
3377 klass
= mono_class_get_checked (m
, token
, error
);
3378 type
->data
.klass
= klass
;
3382 if (!compare_type_literals (m
, klass
->byval_arg
.type
, type
->type
, error
))
3387 case MONO_TYPE_SZARRAY
: {
3388 MonoType
*etype
= mono_metadata_parse_type_checked (m
, container
, 0, transient
, ptr
, &ptr
, error
);
3392 type
->data
.klass
= mono_class_from_mono_type (etype
);
3395 mono_metadata_free_type (etype
);
3397 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.
3400 case MONO_TYPE_PTR
: {
3401 type
->data
.type
= mono_metadata_parse_type_checked (m
, container
, 0, transient
, ptr
, &ptr
, error
);
3402 if (!type
->data
.type
)
3406 case MONO_TYPE_FNPTR
: {
3407 type
->data
.method
= mono_metadata_parse_method_signature_full (m
, container
, 0, ptr
, &ptr
, error
);
3408 if (!type
->data
.method
)
3412 case MONO_TYPE_ARRAY
: {
3413 type
->data
.array
= mono_metadata_parse_array_internal (m
, container
, transient
, ptr
, &ptr
, error
);
3414 if (!type
->data
.array
)
3418 case MONO_TYPE_MVAR
:
3419 case MONO_TYPE_VAR
: {
3420 if (container
&& !verify_var_type_and_container (m
, type
->type
, container
, error
))
3423 type
->data
.generic_param
= mono_metadata_parse_generic_param (m
, container
, type
->type
, ptr
, &ptr
, error
);
3424 if (!type
->data
.generic_param
)
3429 case MONO_TYPE_GENERICINST
: {
3430 if (!do_mono_metadata_parse_generic_class (type
, m
, container
, ptr
, &ptr
, error
))
3435 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
);
3445 * mono_metadata_free_type:
3446 * @type: type to free
3448 * Free the memory allocated for type @type which is allocated on the heap.
3451 mono_metadata_free_type (MonoType
*type
)
3453 if (type
>= builtin_types
&& type
< builtin_types
+ NBUILTIN_TYPES ())
3456 switch (type
->type
){
3457 case MONO_TYPE_OBJECT
:
3458 case MONO_TYPE_STRING
:
3459 if (!type
->data
.klass
)
3462 case MONO_TYPE_CLASS
:
3463 case MONO_TYPE_VALUETYPE
:
3464 if (type
== &type
->data
.klass
->byval_arg
|| type
== &type
->data
.klass
->this_arg
)
3468 mono_metadata_free_type (type
->data
.type
);
3470 case MONO_TYPE_FNPTR
:
3471 mono_metadata_free_method_signature (type
->data
.method
);
3473 case MONO_TYPE_ARRAY
:
3474 mono_metadata_free_array (type
->data
.array
);
3485 hex_dump (const char *buffer
, int base
, int count
)
3487 int show_header
= 1;
3495 for (i
= 0; i
< count
; i
++){
3498 printf ("\n0x%08x: ", (unsigned char) base
+ i
);
3500 printf ("%02x ", (unsigned char) (buffer
[i
]));
3507 * @ptr: Points to the beginning of the Section Data (25.3)
3509 static MonoExceptionClause
*
3510 parse_section_data (MonoImage
*m
, int *num_clauses
, const unsigned char *ptr
, MonoError
*error
)
3512 unsigned char sect_data_flags
;
3514 guint32 sect_data_len
;
3515 MonoExceptionClause
* clauses
= NULL
;
3517 mono_error_init (error
);
3520 /* align on 32-bit boundary */
3521 ptr
= dword_align (ptr
);
3522 sect_data_flags
= *ptr
;
3525 is_fat
= sect_data_flags
& METHOD_HEADER_SECTION_FAT_FORMAT
;
3527 sect_data_len
= (ptr
[2] << 16) | (ptr
[1] << 8) | ptr
[0];
3530 sect_data_len
= ptr
[0];
3534 if (sect_data_flags
& METHOD_HEADER_SECTION_EHTABLE
) {
3535 const unsigned char *p
= dword_align (ptr
);
3537 *num_clauses
= is_fat
? sect_data_len
/ 24: sect_data_len
/ 12;
3538 /* we could just store a pointer if we don't need to byteswap */
3539 clauses
= (MonoExceptionClause
*)g_malloc0 (sizeof (MonoExceptionClause
) * (*num_clauses
));
3540 for (i
= 0; i
< *num_clauses
; ++i
) {
3541 MonoExceptionClause
*ec
= &clauses
[i
];
3544 ec
->flags
= read32 (p
);
3545 ec
->try_offset
= read32 (p
+ 4);
3546 ec
->try_len
= read32 (p
+ 8);
3547 ec
->handler_offset
= read32 (p
+ 12);
3548 ec
->handler_len
= read32 (p
+ 16);
3549 tof_value
= read32 (p
+ 20);
3552 ec
->flags
= read16 (p
);
3553 ec
->try_offset
= read16 (p
+ 2);
3554 ec
->try_len
= *(p
+ 4);
3555 ec
->handler_offset
= read16 (p
+ 5);
3556 ec
->handler_len
= *(p
+ 7);
3557 tof_value
= read32 (p
+ 8);
3560 if (ec
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
) {
3561 ec
->data
.filter_offset
= tof_value
;
3562 } else if (ec
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) {
3563 ec
->data
.catch_class
= NULL
;
3565 ec
->data
.catch_class
= mono_class_get_checked (m
, tof_value
, error
);
3566 if (!is_ok (error
)) {
3572 ec
->data
.catch_class
= NULL
;
3574 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
3578 if (sect_data_flags
& METHOD_HEADER_SECTION_MORE_SECTS
)
3579 ptr
+= sect_data_len
- 4; /* LAMESPEC: it seems the size includes the header */
3586 * mono_method_get_header_summary:
3587 * @method: The method to get the header.
3588 * @summary: Where to store the header
3591 * Returns: TRUE if the header was properly decoded.
3594 mono_method_get_header_summary (MonoMethod
*method
, MonoMethodHeaderSummary
*summary
)
3600 unsigned char flags
, format
;
3603 /*Only the GMD has a pointer to the metadata.*/
3604 while (method
->is_inflated
)
3605 method
= ((MonoMethodInflated
*)method
)->declaring
;
3607 summary
->code_size
= 0;
3608 summary
->has_clauses
= FALSE
;
3610 /*FIXME extract this into a MACRO and share it with mono_method_get_header*/
3611 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
))
3614 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| method
->sre_method
) {
3615 MonoMethodHeader
*header
= ((MonoMethodWrapper
*)method
)->header
;
3618 summary
->code_size
= header
->code_size
;
3619 summary
->has_clauses
= header
->num_clauses
> 0;
3624 idx
= mono_metadata_token_index (method
->token
);
3625 img
= method
->klass
->image
;
3626 rva
= mono_metadata_decode_row_col (&img
->tables
[MONO_TABLE_METHOD
], idx
- 1, MONO_METHOD_RVA
);
3628 /*We must run the verifier since we'll be decoding it.*/
3629 if (!mono_verifier_verify_method_header (img
, rva
, NULL
))
3632 ptr
= mono_image_rva_map (img
, rva
);
3636 flags
= *(const unsigned char *)ptr
;
3637 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
3640 case METHOD_HEADER_TINY_FORMAT
:
3642 summary
->code_size
= flags
>> 2;
3644 case METHOD_HEADER_FAT_FORMAT
:
3645 fat_flags
= read16 (ptr
);
3647 summary
->code_size
= read32 (ptr
);
3648 if (fat_flags
& METHOD_HEADER_MORE_SECTS
)
3649 summary
->has_clauses
= TRUE
;
3658 * mono_metadata_parse_mh_full:
3659 * @m: metadata context
3660 * @generic_context: generics context
3661 * @ptr: pointer to the method header.
3663 * Decode the method header at @ptr, including pointer to the IL code,
3664 * info about local variables and optional exception tables.
3665 * This is a Mono runtime internal function.
3667 * LOCKING: Acquires the loader lock.
3669 * Returns: a transient MonoMethodHeader allocated from the heap.
3672 mono_metadata_parse_mh_full (MonoImage
*m
, MonoGenericContainer
*container
, const char *ptr
, MonoError
*error
)
3674 MonoMethodHeader
*mh
= NULL
;
3675 unsigned char flags
= *(const unsigned char *) ptr
;
3676 unsigned char format
= flags
& METHOD_HEADER_FORMAT_MASK
;
3678 guint32 local_var_sig_tok
, max_stack
, code_size
, init_locals
;
3679 const unsigned char *code
;
3680 MonoExceptionClause
* clauses
= NULL
;
3681 int num_clauses
= 0;
3682 MonoTableInfo
*t
= &m
->tables
[MONO_TABLE_STANDALONESIG
];
3683 guint32 cols
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
3685 mono_error_init (error
);
3688 mono_error_set_bad_image (error
, m
, "Method header with null pointer");
3693 case METHOD_HEADER_TINY_FORMAT
:
3694 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
);
3697 mh
->is_transient
= TRUE
;
3698 local_var_sig_tok
= 0;
3699 mh
->code_size
= flags
>> 2;
3700 mh
->code
= (unsigned char*)ptr
;
3702 case METHOD_HEADER_FAT_FORMAT
:
3703 fat_flags
= read16 (ptr
);
3705 max_stack
= read16 (ptr
);
3707 code_size
= read32 (ptr
);
3709 local_var_sig_tok
= read32 (ptr
);
3712 if (fat_flags
& METHOD_HEADER_INIT_LOCALS
)
3717 code
= (unsigned char*)ptr
;
3719 if (!(fat_flags
& METHOD_HEADER_MORE_SECTS
))
3723 * There are more sections
3725 ptr
= (char*)code
+ code_size
;
3728 mono_error_set_bad_image (error
, m
, "Invalid method header format %d", format
);
3732 if (local_var_sig_tok
) {
3733 int idx
= (local_var_sig_tok
& 0xffffff)-1;
3734 if (idx
>= t
->rows
|| idx
< 0) {
3735 mono_error_set_bad_image (error
, m
, "Invalid method header local vars signature token 0x%8x", idx
);
3738 mono_metadata_decode_row (t
, idx
, cols
, 1);
3740 if (!mono_verifier_verify_standalone_signature (m
, cols
[MONO_STAND_ALONE_SIGNATURE
], NULL
)) {
3741 mono_error_set_bad_image (error
, m
, "Method header locals signature 0x%8x verification failed", idx
);
3745 if (fat_flags
& METHOD_HEADER_MORE_SECTS
) {
3746 clauses
= parse_section_data (m
, &num_clauses
, (const unsigned char*)ptr
, error
);
3750 if (local_var_sig_tok
) {
3751 const char *locals_ptr
;
3754 locals_ptr
= mono_metadata_blob_heap (m
, cols
[MONO_STAND_ALONE_SIGNATURE
]);
3755 mono_metadata_decode_blob_size (locals_ptr
, &locals_ptr
);
3756 if (*locals_ptr
!= 0x07)
3757 g_warning ("wrong signature for locals blob");
3759 len
= mono_metadata_decode_value (locals_ptr
, &locals_ptr
);
3760 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ len
* sizeof (MonoType
*) + num_clauses
* sizeof (MonoExceptionClause
));
3761 mh
->num_locals
= len
;
3762 for (i
= 0; i
< len
; ++i
) {
3763 mh
->locals
[i
] = mono_metadata_parse_type_internal (m
, container
, 0, TRUE
, locals_ptr
, &locals_ptr
, error
);
3768 mh
= (MonoMethodHeader
*)g_malloc0 (MONO_SIZEOF_METHOD_HEADER
+ num_clauses
* sizeof (MonoExceptionClause
));
3771 mh
->code_size
= code_size
;
3772 mh
->max_stack
= max_stack
;
3773 mh
->is_transient
= TRUE
;
3774 mh
->init_locals
= init_locals
;
3776 MonoExceptionClause
* clausesp
= (MonoExceptionClause
*)&mh
->locals
[mh
->num_locals
];
3777 memcpy (clausesp
, clauses
, num_clauses
* sizeof (MonoExceptionClause
));
3779 mh
->clauses
= clausesp
;
3780 mh
->num_clauses
= num_clauses
;
3791 * mono_metadata_parse_mh:
3792 * @generic_context: generics context
3793 * @ptr: pointer to the method header.
3795 * Decode the method header at @ptr, including pointer to the IL code,
3796 * info about local variables and optional exception tables.
3798 * Returns: a transient MonoMethodHeader allocated from the heap.
3801 mono_metadata_parse_mh (MonoImage
*m
, const char *ptr
)
3804 MonoMethodHeader
*header
= mono_metadata_parse_mh_full (m
, NULL
, ptr
, &error
);
3805 mono_error_cleanup (&error
);
3810 * mono_metadata_free_mh:
3811 * @mh: a method header
3813 * Free the memory allocated for the method header.
3816 mono_metadata_free_mh (MonoMethodHeader
*mh
)
3820 /* If it is not transient it means it's part of a wrapper method,
3821 * or a SRE-generated method, so the lifetime in that case is
3822 * dictated by the method's own lifetime
3824 if (mh
->is_transient
) {
3825 for (i
= 0; i
< mh
->num_locals
; ++i
)
3826 mono_metadata_free_type (mh
->locals
[i
]);
3832 * mono_method_header_get_code:
3833 * @header: a MonoMethodHeader pointer
3834 * @code_size: memory location for returning the code size
3835 * @max_stack: memory location for returning the max stack
3837 * Method header accessor to retreive info about the IL code properties:
3838 * a pointer to the IL code itself, the size of the code and the max number
3839 * of stack slots used by the code.
3841 * Returns: pointer to the IL code represented by the method header.
3843 const unsigned char*
3844 mono_method_header_get_code (MonoMethodHeader
*header
, guint32
* code_size
, guint32
* max_stack
)
3847 *code_size
= header
->code_size
;
3849 *max_stack
= header
->max_stack
;
3850 return header
->code
;
3854 * mono_method_header_get_locals:
3855 * @header: a MonoMethodHeader pointer
3856 * @num_locals: memory location for returning the number of local variables
3857 * @init_locals: memory location for returning the init_locals flag
3859 * Method header accessor to retreive info about the local variables:
3860 * an array of local types, the number of locals and whether the locals
3861 * are supposed to be initialized to 0 on method entry
3863 * Returns: pointer to an array of types of the local variables
3866 mono_method_header_get_locals (MonoMethodHeader
*header
, guint32
* num_locals
, gboolean
*init_locals
)
3869 *num_locals
= header
->num_locals
;
3871 *init_locals
= header
->init_locals
;
3872 return header
->locals
;
3876 * mono_method_header_get_num_clauses:
3877 * @header: a MonoMethodHeader pointer
3879 * Method header accessor to retreive the number of exception clauses.
3881 * Returns: the number of exception clauses present
3884 mono_method_header_get_num_clauses (MonoMethodHeader
*header
)
3886 return header
->num_clauses
;
3890 * mono_method_header_get_clauses:
3891 * @header: a MonoMethodHeader pointer
3892 * @method: MonoMethod the header belongs to
3893 * @iter: pointer to a iterator
3894 * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
3896 * Get the info about the exception clauses in the method. Set *iter to NULL to
3897 * initiate the iteration, then call the method repeatedly until it returns FALSE.
3898 * At each iteration, the structure pointed to by clause if filled with the
3899 * exception clause information.
3901 * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
3905 mono_method_header_get_clauses (MonoMethodHeader
*header
, MonoMethod
*method
, gpointer
*iter
, MonoExceptionClause
*clause
)
3907 MonoExceptionClause
*sc
;
3908 /* later we'll be able to use this interface to parse the clause info on demand,
3909 * without allocating anything.
3911 if (!iter
|| !header
->num_clauses
)
3914 *iter
= sc
= header
->clauses
;
3918 sc
= (MonoExceptionClause
*)*iter
;
3920 if (sc
< header
->clauses
+ header
->num_clauses
) {
3929 * mono_metadata_parse_field_type:
3930 * @m: metadata context to extract information from
3931 * @ptr: pointer to the field signature
3932 * @rptr: pointer updated to match the end of the decoded stream
3934 * Parses the field signature, and returns the type information for it.
3936 * Returns: The MonoType that was extracted from @ptr.
3939 mono_metadata_parse_field_type (MonoImage
*m
, short field_flags
, const char *ptr
, const char **rptr
)
3942 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, field_flags
, FALSE
, ptr
, rptr
, &error
);
3943 mono_error_cleanup (&error
);
3948 * mono_metadata_parse_param:
3949 * @m: metadata context to extract information from
3950 * @ptr: pointer to the param signature
3951 * @rptr: pointer updated to match the end of the decoded stream
3953 * Parses the param signature, and returns the type information for it.
3955 * Returns: The MonoType that was extracted from @ptr.
3958 mono_metadata_parse_param (MonoImage
*m
, const char *ptr
, const char **rptr
)
3961 MonoType
* type
= mono_metadata_parse_type_internal (m
, NULL
, 0, FALSE
, ptr
, rptr
, &error
);
3962 mono_error_cleanup (&error
);
3967 * mono_metadata_token_from_dor:
3968 * @dor_token: A TypeDefOrRef coded index
3970 * dor_token is a TypeDefOrRef coded index: it contains either
3971 * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
3972 * bits contain an index into the table.
3974 * Returns: an expanded token
3977 mono_metadata_token_from_dor (guint32 dor_index
)
3981 table
= dor_index
& 0x03;
3982 idx
= dor_index
>> 2;
3985 case 0: /* TypeDef */
3986 return MONO_TOKEN_TYPE_DEF
| idx
;
3987 case 1: /* TypeRef */
3988 return MONO_TOKEN_TYPE_REF
| idx
;
3989 case 2: /* TypeSpec */
3990 return MONO_TOKEN_TYPE_SPEC
| idx
;
3992 g_assert_not_reached ();
3999 * We use this to pass context information to the row locator
4002 int idx
; /* The index that we are trying to locate */
4003 int col_idx
; /* The index in the row where idx may be stored */
4004 MonoTableInfo
*t
; /* pointer to the table */
4009 * How the row locator works.
4014 * ___|___------> _______
4017 * A column in the rows of table A references an index in table B.
4018 * For example A may be the TYPEDEF table and B the METHODDEF table.
4020 * Given an index in table B we want to get the row in table A
4021 * where the column n references our index in B.
4023 * In the locator_t structure:
4025 * col_idx is the column number
4026 * index is the index in table B
4027 * result will be the index in table A
4030 * Table A Table B column (in table A)
4031 * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
4032 * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
4033 * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
4034 * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
4035 * METHODSEM PROPERTY ASSOCIATION (encoded index)
4037 * Note that we still don't support encoded indexes.
4041 typedef_locator (const void *a
, const void *b
)
4043 locator_t
*loc
= (locator_t
*) a
;
4044 const char *bb
= (const char *) b
;
4045 int typedef_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4046 guint32 col
, col_next
;
4048 col
= mono_metadata_decode_row_col (loc
->t
, typedef_index
, loc
->col_idx
);
4054 * Need to check that the next row is valid.
4056 if (typedef_index
+ 1 < loc
->t
->rows
) {
4057 col_next
= mono_metadata_decode_row_col (loc
->t
, typedef_index
+ 1, loc
->col_idx
);
4058 if (loc
->idx
>= col_next
)
4061 if (col
== col_next
)
4065 loc
->result
= typedef_index
;
4071 table_locator (const void *a
, const void *b
)
4073 locator_t
*loc
= (locator_t
*) a
;
4074 const char *bb
= (const char *) b
;
4075 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4078 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
4080 if (loc
->idx
== col
) {
4081 loc
->result
= table_index
;
4091 declsec_locator (const void *a
, const void *b
)
4093 locator_t
*loc
= (locator_t
*) a
;
4094 const char *bb
= (const char *) b
;
4095 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
4098 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
4100 if (loc
->idx
== col
) {
4101 loc
->result
= table_index
;
4113 * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
4114 * which contains IDX.
4117 search_ptr_table (MonoImage
*image
, int table
, int idx
)
4119 MonoTableInfo
*ptrdef
= &image
->tables
[table
];
4122 /* Use a linear search to find our index in the table */
4123 for (i
= 0; i
< ptrdef
->rows
; i
++)
4124 /* All the Ptr tables have the same structure */
4125 if (mono_metadata_decode_row_col (ptrdef
, i
, 0) == idx
)
4128 if (i
< ptrdef
->rows
)
4135 * mono_metadata_typedef_from_field:
4136 * @meta: metadata context
4137 * @index: FieldDef token
4139 * Returns: the 1-based index into the TypeDef table of the type that
4140 * declared the field described by @index, or 0 if not found.
4143 mono_metadata_typedef_from_field (MonoImage
*meta
, guint32 index
)
4145 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
4151 loc
.idx
= mono_metadata_token_index (index
);
4152 loc
.col_idx
= MONO_TYPEDEF_FIELD_LIST
;
4155 if (meta
->uncompressed_metadata
)
4156 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
4158 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
4161 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4162 return loc
.result
+ 1;
4166 * mono_metadata_typedef_from_method:
4167 * @meta: metadata context
4168 * @index: MethodDef token
4170 * Returns: the 1-based index into the TypeDef table of the type that
4171 * declared the method described by @index. 0 if not found.
4174 mono_metadata_typedef_from_method (MonoImage
*meta
, guint32 index
)
4176 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
4182 loc
.idx
= mono_metadata_token_index (index
);
4183 loc
.col_idx
= MONO_TYPEDEF_METHOD_LIST
;
4186 if (meta
->uncompressed_metadata
)
4187 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_METHOD_POINTER
, loc
.idx
);
4189 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
4192 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4193 return loc
.result
+ 1;
4197 * mono_metadata_interfaces_from_typedef_full:
4198 * @meta: metadata context
4199 * @index: typedef token
4200 * @interfaces: Out parameter used to store the interface array
4201 * @count: Out parameter used to store the number of interfaces
4202 * @heap_alloc_result: if TRUE the result array will be g_malloc'd
4203 * @context: The generic context
4205 * The array of interfaces that the @index typedef token implements is returned in
4206 * @interfaces. The number of elements in the array is returned in @count.
4209 * Returns: TRUE on success, FALSE on failure.
4212 mono_metadata_interfaces_from_typedef_full (MonoImage
*meta
, guint32 index
, MonoClass
***interfaces
, guint
*count
, gboolean heap_alloc_result
, MonoGenericContext
*context
, MonoError
*error
)
4214 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_INTERFACEIMPL
];
4217 guint32 cols
[MONO_INTERFACEIMPL_SIZE
];
4223 mono_error_init (error
);
4228 loc
.idx
= mono_metadata_token_index (index
);
4229 loc
.col_idx
= MONO_INTERFACEIMPL_CLASS
;
4232 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4237 * We may end up in the middle of the rows...
4240 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_INTERFACEIMPL_CLASS
))
4246 while (pos
< tdef
->rows
) {
4247 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
4248 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
4253 if (heap_alloc_result
)
4254 result
= g_new0 (MonoClass
*, pos
- start
);
4256 result
= (MonoClass
**)mono_image_alloc0 (meta
, sizeof (MonoClass
*) * (pos
- start
));
4259 while (pos
< tdef
->rows
) {
4262 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
4263 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
4265 iface
= mono_class_get_and_inflate_typespec_checked (
4266 meta
, mono_metadata_token_from_dor (cols
[MONO_INTERFACEIMPL_INTERFACE
]), context
, error
);
4269 result
[pos
- start
] = iface
;
4272 *count
= pos
- start
;
4273 *interfaces
= result
;
4278 * @meta: metadata context
4279 * @index: typedef token
4280 * @count: Out parameter used to store the number of interfaces
4282 * The array of interfaces that the @index typedef token implements is returned in
4283 * @interfaces. The number of elements in the array is returned in @count. The returned
4284 * array is g_malloc'd and the caller must free it.
4286 * LOCKING: Acquires the loader lock .
4288 * Returns: the interface array on success, NULL on failure.
4292 mono_metadata_interfaces_from_typedef (MonoImage
*meta
, guint32 index
, guint
*count
)
4295 MonoClass
**interfaces
= NULL
;
4298 rv
= mono_metadata_interfaces_from_typedef_full (meta
, index
, &interfaces
, count
, TRUE
, NULL
, &error
);
4299 g_assert (mono_error_ok (&error
)); /* FIXME dont swallow the error */
4307 * mono_metadata_nested_in_typedef:
4308 * @meta: metadata context
4309 * @index: typedef token
4311 * Returns: the 1-based index into the TypeDef table of the type
4312 * where the type described by @index is nested.
4313 * Returns 0 if @index describes a non-nested type.
4316 mono_metadata_nested_in_typedef (MonoImage
*meta
, guint32 index
)
4318 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4324 loc
.idx
= mono_metadata_token_index (index
);
4325 loc
.col_idx
= MONO_NESTED_CLASS_NESTED
;
4328 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4331 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4332 return mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_NESTED_CLASS_ENCLOSING
) | MONO_TOKEN_TYPE_DEF
;
4336 * mono_metadata_nesting_typedef:
4337 * @meta: metadata context
4338 * @index: typedef token
4340 * Returns: the 1-based index into the TypeDef table of the first type
4341 * that is nested inside the type described by @index. The search starts at
4342 * @start_index. returns 0 if no such type is found.
4345 mono_metadata_nesting_typedef (MonoImage
*meta
, guint32 index
, guint32 start_index
)
4347 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
4349 guint32 class_index
= mono_metadata_token_index (index
);
4354 start
= start_index
;
4356 while (start
<= tdef
->rows
) {
4357 if (class_index
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_NESTED_CLASS_ENCLOSING
))
4363 if (start
> tdef
->rows
)
4370 * mono_metadata_packing_from_typedef:
4371 * @meta: metadata context
4372 * @index: token representing a type
4374 * Returns: the info stored in the ClassLAyout table for the given typedef token
4375 * into the @packing and @size pointers.
4376 * Returns 0 if the info is not found.
4379 mono_metadata_packing_from_typedef (MonoImage
*meta
, guint32 index
, guint32
*packing
, guint32
*size
)
4381 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CLASSLAYOUT
];
4383 guint32 cols
[MONO_CLASS_LAYOUT_SIZE
];
4388 loc
.idx
= mono_metadata_token_index (index
);
4389 loc
.col_idx
= MONO_CLASS_LAYOUT_PARENT
;
4392 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4395 mono_metadata_decode_row (tdef
, loc
.result
, cols
, MONO_CLASS_LAYOUT_SIZE
);
4397 *packing
= cols
[MONO_CLASS_LAYOUT_PACKING_SIZE
];
4399 *size
= cols
[MONO_CLASS_LAYOUT_CLASS_SIZE
];
4401 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4402 return loc
.result
+ 1;
4406 * mono_metadata_custom_attrs_from_index:
4407 * @meta: metadata context
4408 * @index: token representing the parent
4410 * Returns: the 1-based index into the CustomAttribute table of the first
4411 * attribute which belongs to the metadata object described by @index.
4412 * Returns 0 if no such attribute is found.
4415 mono_metadata_custom_attrs_from_index (MonoImage
*meta
, guint32 index
)
4417 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4424 loc
.col_idx
= MONO_CUSTOM_ATTR_PARENT
;
4427 /* FIXME: Index translation */
4429 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4432 /* Find the first entry by searching backwards */
4433 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_CUSTOM_ATTR_PARENT
) == index
))
4436 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4437 return loc
.result
+ 1;
4441 * mono_metadata_declsec_from_index:
4442 * @meta: metadata context
4443 * @index: token representing the parent
4445 * Returns: the 0-based index into the DeclarativeSecurity table of the first
4446 * attribute which belongs to the metadata object described by @index.
4447 * Returns -1 if no such attribute is found.
4450 mono_metadata_declsec_from_index (MonoImage
*meta
, guint32 index
)
4452 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_DECLSECURITY
];
4459 loc
.col_idx
= MONO_DECL_SECURITY_PARENT
;
4462 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, declsec_locator
))
4465 /* Find the first entry by searching backwards */
4466 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_DECL_SECURITY_PARENT
) == index
))
4473 * mono_metadata_localscope_from_methoddef:
4474 * @meta: metadata context
4475 * @index: methoddef index
4477 * Returns: the 1-based index into the LocalScope table of the first
4478 * scope which belongs to the method described by @index.
4479 * Returns 0 if no such row is found.
4482 mono_metadata_localscope_from_methoddef (MonoImage
*meta
, guint32 index
)
4484 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_LOCALSCOPE
];
4491 loc
.col_idx
= MONO_LOCALSCOPE_METHOD
;
4494 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4497 /* Find the first entry by searching backwards */
4498 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_LOCALSCOPE_METHOD
) == index
))
4501 return loc
.result
+ 1;
4506 mono_backtrace (int limit
)
4511 backtrace (array
, limit
);
4512 names
= backtrace_symbols (array
, limit
);
4513 for (i
=0; i
< limit
; ++i
) {
4514 g_print ("\t%s\n", names
[i
]);
4520 static int i8_align
;
4523 * mono_type_set_alignment:
4525 * Set the alignment used by runtime to layout fields etc. of type TYPE to ALIGN.
4526 * This should only be used in AOT mode since the resulting layout will not match the
4530 mono_type_set_alignment (MonoTypeEnum type
, int align
)
4532 /* Support only a few types whose alignment is abi dependent */
4538 g_assert_not_reached ();
4545 * @t: the type to return the size of
4547 * Returns: the number of bytes required to hold an instance of this
4551 mono_type_size (MonoType
*t
, int *align
)
4553 MonoTypeEnum simple_type
;
4560 *align
= MONO_ABI_ALIGNOF (gpointer
);
4561 return MONO_ABI_SIZEOF (gpointer
);
4564 simple_type
= t
->type
;
4566 switch (simple_type
) {
4567 case MONO_TYPE_VOID
:
4570 case MONO_TYPE_BOOLEAN
:
4571 *align
= MONO_ABI_ALIGNOF (gint8
);
4575 *align
= MONO_ABI_ALIGNOF (gint8
);
4577 case MONO_TYPE_CHAR
:
4580 *align
= MONO_ABI_ALIGNOF (gint16
);
4584 *align
= MONO_ABI_ALIGNOF (gint32
);
4587 *align
= MONO_ABI_ALIGNOF (float);
4591 *align
= MONO_ABI_ALIGNOF (gint64
);
4594 *align
= MONO_ABI_ALIGNOF (double);
4598 *align
= MONO_ABI_ALIGNOF (gpointer
);
4599 return MONO_ABI_SIZEOF (gpointer
);
4600 case MONO_TYPE_VALUETYPE
: {
4601 if (t
->data
.klass
->enumtype
)
4602 return mono_type_size (mono_class_enum_basetype (t
->data
.klass
), align
);
4604 return mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
4606 case MONO_TYPE_STRING
:
4607 case MONO_TYPE_OBJECT
:
4608 case MONO_TYPE_CLASS
:
4609 case MONO_TYPE_SZARRAY
:
4611 case MONO_TYPE_FNPTR
:
4612 case MONO_TYPE_ARRAY
:
4613 *align
= MONO_ABI_ALIGNOF (gpointer
);
4614 return MONO_ABI_SIZEOF (gpointer
);
4615 case MONO_TYPE_TYPEDBYREF
:
4616 return mono_class_value_size (mono_defaults
.typed_reference_class
, (guint32
*)align
);
4617 case MONO_TYPE_GENERICINST
: {
4618 MonoGenericClass
*gclass
= t
->data
.generic_class
;
4619 MonoClass
*container_class
= gclass
->container_class
;
4621 // g_assert (!gclass->inst->is_open);
4623 if (container_class
->valuetype
) {
4624 if (container_class
->enumtype
)
4625 return mono_type_size (mono_class_enum_basetype (container_class
), align
);
4627 return mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
4629 *align
= MONO_ABI_ALIGNOF (gpointer
);
4630 return MONO_ABI_SIZEOF (gpointer
);
4634 case MONO_TYPE_MVAR
:
4635 if (!t
->data
.generic_param
->gshared_constraint
|| t
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_VALUETYPE
) {
4636 *align
= MONO_ABI_ALIGNOF (gpointer
);
4637 return MONO_ABI_SIZEOF (gpointer
);
4639 /* The gparam can only match types given by gshared_constraint */
4640 return mono_type_size (t
->data
.generic_param
->gshared_constraint
, align
);
4644 g_error ("mono_type_size: type 0x%02x unknown", t
->type
);
4650 * mono_type_stack_size:
4651 * @t: the type to return the size it uses on the stack
4653 * Returns: the number of bytes required to hold an instance of this
4654 * type on the runtime stack
4657 mono_type_stack_size (MonoType
*t
, int *align
)
4659 return mono_type_stack_size_internal (t
, align
, FALSE
);
4663 mono_type_stack_size_internal (MonoType
*t
, int *align
, gboolean allow_open
)
4666 MonoTypeEnum simple_type
;
4667 #if SIZEOF_VOID_P == SIZEOF_REGISTER
4668 int stack_slot_size
= MONO_ABI_SIZEOF (gpointer
);
4669 int stack_slot_align
= MONO_ABI_ALIGNOF (gpointer
);
4670 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
4671 int stack_slot_size
= SIZEOF_REGISTER
;
4672 int stack_slot_align
= SIZEOF_REGISTER
;
4675 g_assert (t
!= NULL
);
4681 *align
= stack_slot_align
;
4682 return stack_slot_size
;
4685 simple_type
= t
->type
;
4686 switch (simple_type
) {
4687 case MONO_TYPE_BOOLEAN
:
4688 case MONO_TYPE_CHAR
:
4697 case MONO_TYPE_STRING
:
4698 case MONO_TYPE_OBJECT
:
4699 case MONO_TYPE_CLASS
:
4700 case MONO_TYPE_SZARRAY
:
4702 case MONO_TYPE_FNPTR
:
4703 case MONO_TYPE_ARRAY
:
4704 *align
= stack_slot_align
;
4705 return stack_slot_size
;
4707 case MONO_TYPE_MVAR
:
4708 g_assert (allow_open
);
4709 if (!t
->data
.generic_param
->gshared_constraint
|| t
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_VALUETYPE
) {
4710 *align
= stack_slot_align
;
4711 return stack_slot_size
;
4713 /* The gparam can only match types given by gshared_constraint */
4714 return mono_type_stack_size_internal (t
->data
.generic_param
->gshared_constraint
, align
, allow_open
);
4716 case MONO_TYPE_TYPEDBYREF
:
4717 *align
= stack_slot_align
;
4718 return stack_slot_size
* 3;
4720 *align
= MONO_ABI_ALIGNOF (float);
4721 return sizeof (float);
4724 *align
= MONO_ABI_ALIGNOF (gint64
);
4725 return sizeof (gint64
);
4727 *align
= MONO_ABI_ALIGNOF (double);
4728 return sizeof (double);
4729 case MONO_TYPE_VALUETYPE
: {
4732 if (t
->data
.klass
->enumtype
)
4733 return mono_type_stack_size_internal (mono_class_enum_basetype (t
->data
.klass
), align
, allow_open
);
4735 size
= mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
4737 *align
= *align
+ stack_slot_align
- 1;
4738 *align
&= ~(stack_slot_align
- 1);
4740 size
+= stack_slot_size
- 1;
4741 size
&= ~(stack_slot_size
- 1);
4746 case MONO_TYPE_GENERICINST
: {
4747 MonoGenericClass
*gclass
= t
->data
.generic_class
;
4748 MonoClass
*container_class
= gclass
->container_class
;
4751 g_assert (!gclass
->context
.class_inst
->is_open
);
4753 if (container_class
->valuetype
) {
4754 if (container_class
->enumtype
)
4755 return mono_type_stack_size_internal (mono_class_enum_basetype (container_class
), align
, allow_open
);
4757 guint32 size
= mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
4759 *align
= *align
+ stack_slot_align
- 1;
4760 *align
&= ~(stack_slot_align
- 1);
4762 size
+= stack_slot_size
- 1;
4763 size
&= ~(stack_slot_size
- 1);
4768 *align
= stack_slot_align
;
4769 return stack_slot_size
;
4773 g_error ("type 0x%02x unknown", t
->type
);
4779 mono_type_generic_inst_is_valuetype (MonoType
*type
)
4781 g_assert (type
->type
== MONO_TYPE_GENERICINST
);
4782 return type
->data
.generic_class
->container_class
->valuetype
;
4786 mono_metadata_generic_class_is_valuetype (MonoGenericClass
*gclass
)
4788 return gclass
->container_class
->valuetype
;
4792 _mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
, gboolean signature_only
)
4794 MonoGenericInst
*i1
= g1
->context
.class_inst
;
4795 MonoGenericInst
*i2
= g2
->context
.class_inst
;
4797 if (g1
->is_dynamic
!= g2
->is_dynamic
)
4799 if (!mono_metadata_class_equal (g1
->container_class
, g2
->container_class
, signature_only
))
4801 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
4803 return g1
->is_tb_open
== g2
->is_tb_open
;
4807 _mono_metadata_generic_class_container_equal (const MonoGenericClass
*g1
, MonoClass
*c2
, gboolean signature_only
)
4809 MonoGenericInst
*i1
= g1
->context
.class_inst
;
4810 MonoGenericInst
*i2
= c2
->generic_container
->context
.class_inst
;
4812 if (!mono_metadata_class_equal (g1
->container_class
, c2
, signature_only
))
4814 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
4816 return !g1
->is_tb_open
;
4820 mono_metadata_generic_context_hash (const MonoGenericContext
*context
)
4822 /* FIXME: check if this seed is good enough */
4823 guint hash
= 0xc01dfee7;
4824 if (context
->class_inst
)
4825 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->class_inst
);
4826 if (context
->method_inst
)
4827 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->method_inst
);
4832 mono_metadata_generic_context_equal (const MonoGenericContext
*g1
, const MonoGenericContext
*g2
)
4834 return g1
->class_inst
== g2
->class_inst
&& g1
->method_inst
== g2
->method_inst
;
4838 * mono_metadata_str_hash:
4840 * This should be used instead of g_str_hash for computing hash codes visible
4841 * outside this module, since g_str_hash () is not guaranteed to be stable
4842 * (its not the same in eglib for example).
4845 mono_metadata_str_hash (gconstpointer v1
)
4847 /* Same as g_str_hash () in glib */
4848 char *p
= (char *) v1
;
4853 hash
= (hash
<< 5) - hash
+ *p
;
4860 * mono_metadata_type_hash:
4863 * Computes an hash value for @t1 to be used in GHashTable.
4864 * The returned hash is guaranteed to be the same across executions.
4867 mono_metadata_type_hash (MonoType
*t1
)
4869 guint hash
= t1
->type
;
4871 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
4873 case MONO_TYPE_VALUETYPE
:
4874 case MONO_TYPE_CLASS
:
4875 case MONO_TYPE_SZARRAY
: {
4876 MonoClass
*klass
= t1
->data
.klass
;
4878 * Dynamic classes must not be hashed on their type since it can change
4879 * during runtime. For example, if we hash a reference type that is
4880 * later made into a valuetype.
4882 * This is specially problematic with generic instances since they are
4883 * inserted in a bunch of hash tables before been finished.
4885 if (image_is_dynamic (klass
->image
))
4886 return (t1
->byref
<< 6) | mono_metadata_str_hash (klass
->name
);
4887 return ((hash
<< 5) - hash
) ^ mono_metadata_str_hash (klass
->name
);
4890 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (t1
->data
.type
);
4891 case MONO_TYPE_ARRAY
:
4892 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (&t1
->data
.array
->eklass
->byval_arg
);
4893 case MONO_TYPE_GENERICINST
:
4894 return ((hash
<< 5) - hash
) ^ mono_generic_class_hash (t1
->data
.generic_class
);
4896 case MONO_TYPE_MVAR
:
4897 return ((hash
<< 5) - hash
) ^ mono_metadata_generic_param_hash (t1
->data
.generic_param
);
4904 mono_metadata_generic_param_hash (MonoGenericParam
*p
)
4907 MonoGenericParamInfo
*info
;
4909 hash
= (mono_generic_param_num (p
) << 2);
4910 if (p
->gshared_constraint
)
4911 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (p
->gshared_constraint
);
4912 info
= mono_generic_param_info (p
);
4913 /* Can't hash on the owner klass/method, since those might not be set when this is called */
4915 hash
= ((hash
<< 5) - hash
) ^ info
->token
;
4920 mono_metadata_generic_param_equal_internal (MonoGenericParam
*p1
, MonoGenericParam
*p2
, gboolean signature_only
)
4924 if (mono_generic_param_num (p1
) != mono_generic_param_num (p2
))
4926 if (p1
->gshared_constraint
&& p2
->gshared_constraint
) {
4927 if (!mono_metadata_type_equal (p1
->gshared_constraint
, p2
->gshared_constraint
))
4930 if (p1
->gshared_constraint
!= p2
->gshared_constraint
)
4935 * We have to compare the image as well because if we didn't,
4936 * the generic_inst_cache lookup wouldn't care about the image
4937 * of generic params, so what could happen is that a generic
4938 * inst with params from image A is put into the cache, then
4939 * image B gets that generic inst from the cache, image A is
4940 * unloaded, so the inst is deleted, but image B still retains
4943 if (mono_generic_param_owner (p1
) == mono_generic_param_owner (p2
))
4947 * If `signature_only' is true, we're comparing two (method) signatures.
4948 * In this case, the owner of two type parameters doesn't need to match.
4951 return signature_only
;
4955 mono_metadata_generic_param_equal (MonoGenericParam
*p1
, MonoGenericParam
*p2
)
4957 return mono_metadata_generic_param_equal_internal (p1
, p2
, TRUE
);
4961 mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
)
4965 if (c1
->generic_class
&& c2
->generic_class
)
4966 return _mono_metadata_generic_class_equal (c1
->generic_class
, c2
->generic_class
, signature_only
);
4967 if (c1
->generic_class
&& c2
->generic_container
)
4968 return _mono_metadata_generic_class_container_equal (c1
->generic_class
, c2
, signature_only
);
4969 if (c1
->generic_container
&& c2
->generic_class
)
4970 return _mono_metadata_generic_class_container_equal (c2
->generic_class
, c1
, signature_only
);
4971 if ((c1
->byval_arg
.type
== MONO_TYPE_VAR
) && (c2
->byval_arg
.type
== MONO_TYPE_VAR
))
4972 return mono_metadata_generic_param_equal_internal (
4973 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
4974 if ((c1
->byval_arg
.type
== MONO_TYPE_MVAR
) && (c2
->byval_arg
.type
== MONO_TYPE_MVAR
))
4975 return mono_metadata_generic_param_equal_internal (
4976 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
4977 if (signature_only
&&
4978 (c1
->byval_arg
.type
== MONO_TYPE_SZARRAY
) && (c2
->byval_arg
.type
== MONO_TYPE_SZARRAY
))
4979 return mono_metadata_class_equal (c1
->byval_arg
.data
.klass
, c2
->byval_arg
.data
.klass
, signature_only
);
4980 if (signature_only
&&
4981 (c1
->byval_arg
.type
== MONO_TYPE_ARRAY
) && (c2
->byval_arg
.type
== MONO_TYPE_ARRAY
))
4982 return do_mono_metadata_type_equal (&c1
->byval_arg
, &c2
->byval_arg
, signature_only
);
4987 mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
)
4989 gpointer iter1
= 0, iter2
= 0;
4993 if (s1
->call_convention
!= s2
->call_convention
)
4995 if (s1
->sentinelpos
!= s2
->sentinelpos
)
4997 if (s1
->hasthis
!= s2
->hasthis
)
4999 if (s1
->explicit_this
!= s2
->explicit_this
)
5001 if (! do_mono_metadata_type_equal (s1
->ret
, s2
->ret
, signature_only
))
5003 if (s1
->param_count
!= s2
->param_count
)
5007 MonoType
*t1
= mono_signature_get_params (s1
, &iter1
);
5008 MonoType
*t2
= mono_signature_get_params (s2
, &iter2
);
5010 if (t1
== NULL
|| t2
== NULL
)
5012 if (! do_mono_metadata_type_equal (t1
, t2
, signature_only
))
5018 * mono_metadata_type_equal:
5021 * @signature_only: If true, treat ginsts as equal which are instantiated separately but have equal positional value
5023 * Determine if @t1 and @t2 represent the same type.
5024 * Returns: #TRUE if @t1 and @t2 are equal.
5027 do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
5029 if (t1
->type
!= t2
->type
|| t1
->byref
!= t2
->byref
)
5033 case MONO_TYPE_VOID
:
5034 case MONO_TYPE_BOOLEAN
:
5035 case MONO_TYPE_CHAR
:
5046 case MONO_TYPE_STRING
:
5049 case MONO_TYPE_OBJECT
:
5050 case MONO_TYPE_TYPEDBYREF
:
5052 case MONO_TYPE_VALUETYPE
:
5053 case MONO_TYPE_CLASS
:
5054 case MONO_TYPE_SZARRAY
:
5055 return mono_metadata_class_equal (t1
->data
.klass
, t2
->data
.klass
, signature_only
);
5057 return do_mono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
, signature_only
);
5058 case MONO_TYPE_ARRAY
:
5059 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
5061 return mono_metadata_class_equal (t1
->data
.array
->eklass
, t2
->data
.array
->eklass
, signature_only
);
5062 case MONO_TYPE_GENERICINST
:
5063 return _mono_metadata_generic_class_equal (
5064 t1
->data
.generic_class
, t2
->data
.generic_class
, signature_only
);
5066 return mono_metadata_generic_param_equal_internal (
5067 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
5068 case MONO_TYPE_MVAR
:
5069 return mono_metadata_generic_param_equal_internal (
5070 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
5071 case MONO_TYPE_FNPTR
:
5072 return mono_metadata_fnptr_equal (t1
->data
.method
, t2
->data
.method
, signature_only
);
5074 g_error ("implement type compare for %0x!", t1
->type
);
5082 mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
5084 return do_mono_metadata_type_equal (t1
, t2
, FALSE
);
5088 * mono_metadata_type_equal_full:
5091 * @signature_only: if signature only comparison should be made
5093 * Determine if @t1 and @t2 are signature compatible if @signature_only is #TRUE, otherwise
5094 * behaves the same way as mono_metadata_type_equal.
5095 * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
5096 * Returns: #TRUE if @t1 and @t2 are equal taking @signature_only into account.
5099 mono_metadata_type_equal_full (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
5101 return do_mono_metadata_type_equal (t1
, t2
, signature_only
);
5105 * mono_metadata_signature_equal:
5106 * @sig1: a signature
5107 * @sig2: another signature
5109 * Determine if @sig1 and @sig2 represent the same signature, with the
5110 * same number of arguments and the same types.
5111 * Returns: #TRUE if @sig1 and @sig2 are equal.
5114 mono_metadata_signature_equal (MonoMethodSignature
*sig1
, MonoMethodSignature
*sig2
)
5118 if (sig1
->hasthis
!= sig2
->hasthis
|| sig1
->param_count
!= sig2
->param_count
)
5121 if (sig1
->generic_param_count
!= sig2
->generic_param_count
)
5125 * We're just comparing the signatures of two methods here:
5127 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
5128 * U and V are equal here.
5130 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
5133 for (i
= 0; i
< sig1
->param_count
; i
++) {
5134 MonoType
*p1
= sig1
->params
[i
];
5135 MonoType
*p2
= sig2
->params
[i
];
5137 /* if (p1->attrs != p2->attrs)
5140 if (!do_mono_metadata_type_equal (p1
, p2
, TRUE
))
5144 if (!do_mono_metadata_type_equal (sig1
->ret
, sig2
->ret
, TRUE
))
5150 * mono_metadata_type_dup:
5151 * @image: image to alloc memory from
5152 * @original: type to duplicate
5154 * Returns: copy of type allocated from the image's mempool (or from the heap, if @image is null).
5157 mono_metadata_type_dup (MonoImage
*image
, const MonoType
*o
)
5160 int sizeof_o
= MONO_SIZEOF_TYPE
;
5162 sizeof_o
+= o
->num_mods
* sizeof (MonoCustomMod
);
5164 r
= image
? (MonoType
*)mono_image_alloc0 (image
, sizeof_o
) : (MonoType
*)g_malloc (sizeof_o
);
5166 memcpy (r
, o
, sizeof_o
);
5168 if (o
->type
== MONO_TYPE_PTR
) {
5169 r
->data
.type
= mono_metadata_type_dup (image
, o
->data
.type
);
5170 } else if (o
->type
== MONO_TYPE_ARRAY
) {
5171 r
->data
.array
= mono_dup_array_type (image
, o
->data
.array
);
5172 } else if (o
->type
== MONO_TYPE_FNPTR
) {
5173 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
5174 r
->data
.method
= mono_metadata_signature_deep_dup (image
, o
->data
.method
);
5180 mono_signature_hash (MonoMethodSignature
*sig
)
5182 guint i
, res
= sig
->ret
->type
;
5184 for (i
= 0; i
< sig
->param_count
; i
++)
5185 res
= (res
<< 5) - res
+ mono_type_hash (sig
->params
[i
]);
5191 * mono_metadata_encode_value:
5192 * @value: value to encode
5193 * @buf: buffer where to write the compressed representation
5194 * @endbuf: pointer updated to point at the end of the encoded output
5196 * Encodes the value @value in the compressed representation used
5197 * in metadata and stores the result in @buf. @buf needs to be big
5198 * enough to hold the data (4 bytes).
5201 mono_metadata_encode_value (guint32 value
, char *buf
, char **endbuf
)
5207 else if (value
< 0x4000) {
5208 p
[0] = 0x80 | (value
>> 8);
5209 p
[1] = value
& 0xff;
5212 p
[0] = (value
>> 24) | 0xc0;
5213 p
[1] = (value
>> 16) & 0xff;
5214 p
[2] = (value
>> 8) & 0xff;
5215 p
[3] = value
& 0xff;
5223 * mono_metadata_field_info:
5224 * @meta: the Image the field is defined in
5225 * @index: the index in the field table representing the field
5226 * @offset: a pointer to an integer where to store the offset that
5227 * may have been specified for the field in a FieldLayout table
5228 * @rva: a pointer to the RVA of the field data in the image that
5229 * may have been defined in a FieldRVA table
5230 * @marshal_spec: a pointer to the marshal spec that may have been
5231 * defined for the field in a FieldMarshal table.
5233 * Gather info for field @index that may have been defined in the FieldLayout,
5234 * FieldRVA and FieldMarshal tables.
5235 * Either of offset, rva and marshal_spec can be NULL if you're not interested
5239 mono_metadata_field_info (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5240 MonoMarshalSpec
**marshal_spec
)
5242 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, FALSE
);
5246 mono_metadata_field_info_with_mempool (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5247 MonoMarshalSpec
**marshal_spec
)
5249 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, TRUE
);
5253 mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
5254 MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
)
5256 MonoTableInfo
*tdef
;
5259 loc
.idx
= index
+ 1;
5260 if (meta
->uncompressed_metadata
)
5261 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
5264 tdef
= &meta
->tables
[MONO_TABLE_FIELDLAYOUT
];
5266 loc
.col_idx
= MONO_FIELD_LAYOUT_FIELD
;
5269 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5270 *offset
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_LAYOUT_OFFSET
);
5272 *offset
= (guint32
)-1;
5276 tdef
= &meta
->tables
[MONO_TABLE_FIELDRVA
];
5278 loc
.col_idx
= MONO_FIELD_RVA_FIELD
;
5281 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5283 * LAMESPEC: There is no signature, no nothing, just the raw data.
5285 *rva
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_RVA_RVA
);
5293 if ((p
= mono_metadata_get_marshal_info (meta
, index
, TRUE
))) {
5294 *marshal_spec
= mono_metadata_parse_marshal_spec_full (alloc_from_image
? meta
: NULL
, meta
, p
);
5301 * mono_metadata_get_constant_index:
5302 * @meta: the Image the field is defined in
5303 * @index: the token that may have a row defined in the constants table
5304 * @hint: possible position for the row
5306 * @token must be a FieldDef, ParamDef or PropertyDef token.
5308 * Returns: the index into the Constants table or 0 if not found.
5311 mono_metadata_get_constant_index (MonoImage
*meta
, guint32 token
, guint32 hint
)
5313 MonoTableInfo
*tdef
;
5315 guint32 index
= mono_metadata_token_index (token
);
5317 tdef
= &meta
->tables
[MONO_TABLE_CONSTANT
];
5318 index
<<= MONO_HASCONSTANT_BITS
;
5319 switch (mono_metadata_token_table (token
)) {
5320 case MONO_TABLE_FIELD
:
5321 index
|= MONO_HASCONSTANT_FIEDDEF
;
5323 case MONO_TABLE_PARAM
:
5324 index
|= MONO_HASCONSTANT_PARAM
;
5326 case MONO_TABLE_PROPERTY
:
5327 index
|= MONO_HASCONSTANT_PROPERTY
;
5330 g_warning ("Not a valid token for the constant table: 0x%08x", token
);
5334 loc
.col_idx
= MONO_CONSTANT_PARENT
;
5337 /* FIXME: Index translation */
5339 if ((hint
> 0) && (hint
< tdef
->rows
) && (mono_metadata_decode_row_col (tdef
, hint
- 1, MONO_CONSTANT_PARENT
) == index
))
5342 if (tdef
->base
&& mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
5343 return loc
.result
+ 1;
5349 * mono_metadata_events_from_typedef:
5350 * @meta: metadata context
5351 * @index: 0-based index (in the TypeDef table) describing a type
5353 * Returns: the 0-based index in the Event table for the events in the
5354 * type. The last event that belongs to the type (plus 1) is stored
5355 * in the @end_idx pointer.
5358 mono_metadata_events_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5362 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_EVENTMAP
];
5370 loc
.col_idx
= MONO_EVENT_MAP_PARENT
;
5371 loc
.idx
= index
+ 1;
5373 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5376 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_EVENT_MAP_EVENTLIST
);
5377 if (loc
.result
+ 1 < tdef
->rows
) {
5378 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_EVENT_MAP_EVENTLIST
) - 1;
5380 end
= meta
->tables
[MONO_TABLE_EVENT
].rows
;
5388 * mono_metadata_methods_from_event:
5389 * @meta: metadata context
5390 * @index: 0-based index (in the Event table) describing a event
5392 * Returns: the 0-based index in the MethodDef table for the methods in the
5393 * event. The last method that belongs to the event (plus 1) is stored
5394 * in the @end_idx pointer.
5397 mono_metadata_methods_from_event (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5401 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
5402 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
5408 if (meta
->uncompressed_metadata
)
5409 index
= search_ptr_table (meta
, MONO_TABLE_EVENT_POINTER
, index
+ 1) - 1;
5412 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
5413 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
; /* Method association coded index */
5415 if (!mono_binary_search (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
5420 * We may end up in the middle of the rows...
5423 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
5429 while (end
< msemt
->rows
) {
5430 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
5431 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
5440 * mono_metadata_properties_from_typedef:
5441 * @meta: metadata context
5442 * @index: 0-based index (in the TypeDef table) describing a type
5444 * Returns: the 0-based index in the Property table for the properties in the
5445 * type. The last property that belongs to the type (plus 1) is stored
5446 * in the @end_idx pointer.
5449 mono_metadata_properties_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5453 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_PROPERTYMAP
];
5461 loc
.col_idx
= MONO_PROPERTY_MAP_PARENT
;
5462 loc
.idx
= index
+ 1;
5464 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5467 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_PROPERTY_MAP_PROPERTY_LIST
);
5468 if (loc
.result
+ 1 < tdef
->rows
) {
5469 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_PROPERTY_MAP_PROPERTY_LIST
) - 1;
5471 end
= meta
->tables
[MONO_TABLE_PROPERTY
].rows
;
5479 * mono_metadata_methods_from_property:
5480 * @meta: metadata context
5481 * @index: 0-based index (in the PropertyDef table) describing a property
5483 * Returns: the 0-based index in the MethodDef table for the methods in the
5484 * property. The last method that belongs to the property (plus 1) is stored
5485 * in the @end_idx pointer.
5488 mono_metadata_methods_from_property (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
5492 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
5493 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
5499 if (meta
->uncompressed_metadata
)
5500 index
= search_ptr_table (meta
, MONO_TABLE_PROPERTY_POINTER
, index
+ 1) - 1;
5503 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
5504 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
; /* Method association coded index */
5506 if (!mono_binary_search (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
5511 * We may end up in the middle of the rows...
5514 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
5520 while (end
< msemt
->rows
) {
5521 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
5522 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
5531 mono_metadata_implmap_from_method (MonoImage
*meta
, guint32 method_idx
)
5534 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_IMPLMAP
];
5539 /* No index translation seems to be needed */
5542 loc
.col_idx
= MONO_IMPLMAP_MEMBER
;
5543 loc
.idx
= ((method_idx
+ 1) << MONO_MEMBERFORWD_BITS
) | MONO_MEMBERFORWD_METHODDEF
;
5545 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5548 return loc
.result
+ 1;
5552 * @image: context where the image is created
5553 * @type_spec: typespec token
5554 * @deprecated use mono_type_create_from_typespec_checked that has proper error handling
5556 * Creates a MonoType representing the TypeSpec indexed by the @type_spec
5560 mono_type_create_from_typespec (MonoImage
*image
, guint32 type_spec
)
5563 MonoType
*type
= mono_type_create_from_typespec_checked (image
, type_spec
, &error
);
5565 g_error ("Could not create typespec %x due to %s", type_spec
, mono_error_get_message (&error
));
5570 mono_type_create_from_typespec_checked (MonoImage
*image
, guint32 type_spec
, MonoError
*error
)
5573 guint32 idx
= mono_metadata_token_index (type_spec
);
5575 guint32 cols
[MONO_TYPESPEC_SIZE
];
5577 MonoType
*type
, *type2
;
5579 mono_error_init (error
);
5581 mono_image_lock (image
);
5582 type
= (MonoType
*)g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
5583 mono_image_unlock (image
);
5587 t
= &image
->tables
[MONO_TABLE_TYPESPEC
];
5589 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPESPEC_SIZE
);
5590 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_TYPESPEC_SIGNATURE
]);
5592 if (!mono_verifier_verify_typespec_signature (image
, cols
[MONO_TYPESPEC_SIGNATURE
], type_spec
, NULL
)) {
5593 mono_error_set_bad_image (error
, image
, "Could not verify type spec %08x.", type_spec
);
5597 mono_metadata_decode_value (ptr
, &ptr
);
5599 type
= mono_metadata_parse_type_checked (image
, NULL
, 0, TRUE
, ptr
, &ptr
, error
);
5603 type2
= mono_metadata_type_dup (image
, type
);
5604 mono_metadata_free_type (type
);
5606 mono_image_lock (image
);
5607 type
= (MonoType
*)g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
5608 /* We might leak some data in the image mempool if found */
5610 g_hash_table_insert (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
), type2
);
5613 mono_image_unlock (image
);
5620 mono_image_strndup (MonoImage
*image
, const char *data
, guint len
)
5624 return g_strndup (data
, len
);
5625 res
= (char *)mono_image_alloc (image
, len
+ 1);
5626 memcpy (res
, data
, len
);
5632 mono_metadata_parse_marshal_spec (MonoImage
*image
, const char *ptr
)
5634 return mono_metadata_parse_marshal_spec_full (NULL
, image
, ptr
);
5638 * If IMAGE is non-null, memory will be allocated from its mempool, otherwise it will be allocated using malloc.
5639 * PARENT_IMAGE is the image containing the marshal spec.
5642 mono_metadata_parse_marshal_spec_full (MonoImage
*image
, MonoImage
*parent_image
, const char *ptr
)
5644 MonoMarshalSpec
*res
;
5646 const char *start
= ptr
;
5648 /* fixme: this is incomplete, but I cant find more infos in the specs */
5651 res
= (MonoMarshalSpec
*)mono_image_alloc0 (image
, sizeof (MonoMarshalSpec
));
5653 res
= g_new0 (MonoMarshalSpec
, 1);
5655 len
= mono_metadata_decode_value (ptr
, &ptr
);
5656 res
->native
= (MonoMarshalNative
)*ptr
++;
5658 if (res
->native
== MONO_NATIVE_LPARRAY
) {
5659 res
->data
.array_data
.param_num
= -1;
5660 res
->data
.array_data
.num_elem
= -1;
5661 res
->data
.array_data
.elem_mult
= -1;
5663 if (ptr
- start
<= len
)
5664 res
->data
.array_data
.elem_type
= (MonoMarshalNative
)*ptr
++;
5665 if (ptr
- start
<= len
)
5666 res
->data
.array_data
.param_num
= mono_metadata_decode_value (ptr
, &ptr
);
5667 if (ptr
- start
<= len
)
5668 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5669 if (ptr
- start
<= len
) {
5671 * LAMESPEC: Older spec versions say this parameter comes before
5672 * num_elem. Never spec versions don't talk about elem_mult at
5673 * all, but csc still emits it, and it is used to distinguish
5674 * between param_num being 0, and param_num being omitted.
5675 * So if (param_num == 0) && (num_elem > 0), then
5676 * elem_mult == 0 -> the array size is num_elem
5677 * elem_mult == 1 -> the array size is @param_num + num_elem
5679 res
->data
.array_data
.elem_mult
= mono_metadata_decode_value (ptr
, &ptr
);
5683 if (res
->native
== MONO_NATIVE_BYVALTSTR
) {
5684 if (ptr
- start
<= len
)
5685 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5688 if (res
->native
== MONO_NATIVE_BYVALARRAY
) {
5689 if (ptr
- start
<= len
)
5690 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
5693 if (res
->native
== MONO_NATIVE_CUSTOM
) {
5694 /* skip unused type guid */
5695 len
= mono_metadata_decode_value (ptr
, &ptr
);
5697 /* skip unused native type name */
5698 len
= mono_metadata_decode_value (ptr
, &ptr
);
5700 /* read custom marshaler type name */
5701 len
= mono_metadata_decode_value (ptr
, &ptr
);
5702 res
->data
.custom_data
.custom_name
= mono_image_strndup (image
, ptr
, len
);
5704 /* read cookie string */
5705 len
= mono_metadata_decode_value (ptr
, &ptr
);
5706 res
->data
.custom_data
.cookie
= mono_image_strndup (image
, ptr
, len
);
5707 res
->data
.custom_data
.image
= parent_image
;
5710 if (res
->native
== MONO_NATIVE_SAFEARRAY
) {
5711 res
->data
.safearray_data
.elem_type
= (MonoMarshalVariant
)0;
5712 res
->data
.safearray_data
.num_elem
= 0;
5713 if (ptr
- start
<= len
)
5714 res
->data
.safearray_data
.elem_type
= (MonoMarshalVariant
)*ptr
++;
5715 if (ptr
- start
<= len
)
5716 res
->data
.safearray_data
.num_elem
= *ptr
++;
5722 mono_metadata_free_marshal_spec (MonoMarshalSpec
*spec
)
5724 if (spec
->native
== MONO_NATIVE_CUSTOM
) {
5725 g_free (spec
->data
.custom_data
.custom_name
);
5726 g_free (spec
->data
.custom_data
.cookie
);
5732 * mono_type_to_unmanaged:
5734 * Returns: A MonoMarshalNative enumeration value (MONO_NATIVE_) value
5735 * describing the underlying native reprensetation of the type.
5737 * In addition the value pointed by
5738 * "conv" will contain the kind of marshalling required for this
5739 * particular type one of the MONO_MARSHAL_CONV_ enumeration values.
5742 mono_type_to_unmanaged (MonoType
*type
, MonoMarshalSpec
*mspec
, gboolean as_field
,
5743 gboolean unicode
, MonoMarshalConv
*conv
)
5745 MonoMarshalConv dummy_conv
;
5751 *conv
= MONO_MARSHAL_CONV_NONE
;
5754 return MONO_NATIVE_UINT
;
5758 case MONO_TYPE_BOOLEAN
:
5760 switch (mspec
->native
) {
5761 case MONO_NATIVE_VARIANTBOOL
:
5762 *conv
= MONO_MARSHAL_CONV_BOOL_VARIANTBOOL
;
5763 return MONO_NATIVE_VARIANTBOOL
;
5764 case MONO_NATIVE_BOOLEAN
:
5765 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
5766 return MONO_NATIVE_BOOLEAN
;
5767 case MONO_NATIVE_I1
:
5768 case MONO_NATIVE_U1
:
5769 return mspec
->native
;
5771 g_error ("cant marshal bool to native type %02x", mspec
->native
);
5774 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
5775 return MONO_NATIVE_BOOLEAN
;
5776 case MONO_TYPE_CHAR
:
5778 switch (mspec
->native
) {
5779 case MONO_NATIVE_U2
:
5780 case MONO_NATIVE_U1
:
5781 return mspec
->native
;
5783 g_error ("cant marshal char to native type %02x", mspec
->native
);
5786 return unicode
? MONO_NATIVE_U2
: MONO_NATIVE_U1
;
5787 case MONO_TYPE_I1
: return MONO_NATIVE_I1
;
5788 case MONO_TYPE_U1
: return MONO_NATIVE_U1
;
5789 case MONO_TYPE_I2
: return MONO_NATIVE_I2
;
5790 case MONO_TYPE_U2
: return MONO_NATIVE_U2
;
5791 case MONO_TYPE_I4
: return MONO_NATIVE_I4
;
5792 case MONO_TYPE_U4
: return MONO_NATIVE_U4
;
5793 case MONO_TYPE_I8
: return MONO_NATIVE_I8
;
5794 case MONO_TYPE_U8
: return MONO_NATIVE_U8
;
5795 case MONO_TYPE_R4
: return MONO_NATIVE_R4
;
5796 case MONO_TYPE_R8
: return MONO_NATIVE_R8
;
5797 case MONO_TYPE_STRING
:
5799 switch (mspec
->native
) {
5800 case MONO_NATIVE_BSTR
:
5801 *conv
= MONO_MARSHAL_CONV_STR_BSTR
;
5802 return MONO_NATIVE_BSTR
;
5803 case MONO_NATIVE_LPSTR
:
5804 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
5805 return MONO_NATIVE_LPSTR
;
5806 case MONO_NATIVE_LPWSTR
:
5807 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
5808 return MONO_NATIVE_LPWSTR
;
5809 case MONO_NATIVE_LPTSTR
:
5810 *conv
= MONO_MARSHAL_CONV_STR_LPTSTR
;
5811 return MONO_NATIVE_LPTSTR
;
5812 case MONO_NATIVE_ANSIBSTR
:
5813 *conv
= MONO_MARSHAL_CONV_STR_ANSIBSTR
;
5814 return MONO_NATIVE_ANSIBSTR
;
5815 case MONO_NATIVE_TBSTR
:
5816 *conv
= MONO_MARSHAL_CONV_STR_TBSTR
;
5817 return MONO_NATIVE_TBSTR
;
5818 case MONO_NATIVE_BYVALTSTR
:
5820 *conv
= MONO_MARSHAL_CONV_STR_BYVALWSTR
;
5822 *conv
= MONO_MARSHAL_CONV_STR_BYVALSTR
;
5823 return MONO_NATIVE_BYVALTSTR
;
5825 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
);
5829 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
5830 return MONO_NATIVE_LPWSTR
;
5833 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
5834 return MONO_NATIVE_LPSTR
;
5836 case MONO_TYPE_PTR
: return MONO_NATIVE_UINT
;
5837 case MONO_TYPE_VALUETYPE
: /*FIXME*/
5838 if (type
->data
.klass
->enumtype
) {
5839 t
= mono_class_enum_basetype (type
->data
.klass
)->type
;
5842 if (type
->data
.klass
== mono_defaults
.handleref_class
){
5843 *conv
= MONO_MARSHAL_CONV_HANDLEREF
;
5844 return MONO_NATIVE_INT
;
5846 return MONO_NATIVE_STRUCT
;
5847 case MONO_TYPE_SZARRAY
:
5848 case MONO_TYPE_ARRAY
:
5850 switch (mspec
->native
) {
5851 case MONO_NATIVE_BYVALARRAY
:
5852 if ((type
->data
.klass
->element_class
== mono_defaults
.char_class
) && !unicode
)
5853 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY
;
5855 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALARRAY
;
5856 return MONO_NATIVE_BYVALARRAY
;
5857 case MONO_NATIVE_SAFEARRAY
:
5858 *conv
= MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
;
5859 return MONO_NATIVE_SAFEARRAY
;
5860 case MONO_NATIVE_LPARRAY
:
5861 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
5862 return MONO_NATIVE_LPARRAY
;
5864 g_error ("cant marshal array as native type %02x", mspec
->native
);
5868 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
5869 return MONO_NATIVE_LPARRAY
;
5870 case MONO_TYPE_I
: return MONO_NATIVE_INT
;
5871 case MONO_TYPE_U
: return MONO_NATIVE_UINT
;
5872 case MONO_TYPE_CLASS
:
5873 case MONO_TYPE_OBJECT
: {
5874 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
5876 switch (mspec
->native
) {
5877 case MONO_NATIVE_STRUCT
:
5878 return MONO_NATIVE_STRUCT
;
5879 case MONO_NATIVE_CUSTOM
:
5880 return MONO_NATIVE_CUSTOM
;
5881 case MONO_NATIVE_INTERFACE
:
5882 *conv
= MONO_MARSHAL_CONV_OBJECT_INTERFACE
;
5883 return MONO_NATIVE_INTERFACE
;
5884 case MONO_NATIVE_IDISPATCH
:
5885 *conv
= MONO_MARSHAL_CONV_OBJECT_IDISPATCH
;
5886 return MONO_NATIVE_IDISPATCH
;
5887 case MONO_NATIVE_IUNKNOWN
:
5888 *conv
= MONO_MARSHAL_CONV_OBJECT_IUNKNOWN
;
5889 return MONO_NATIVE_IUNKNOWN
;
5890 case MONO_NATIVE_FUNC
:
5891 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
5892 type
->data
.klass
== mono_defaults
.delegate_class
||
5893 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
5894 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
5895 return MONO_NATIVE_FUNC
;
5899 g_error ("cant marshal object as native type %02x", mspec
->native
);
5902 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
5903 type
->data
.klass
== mono_defaults
.delegate_class
||
5904 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
5905 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
5906 return MONO_NATIVE_FUNC
;
5908 if (mono_class_try_get_safehandle_class () && type
->data
.klass
== mono_class_try_get_safehandle_class ()){
5909 *conv
= MONO_MARSHAL_CONV_SAFEHANDLE
;
5910 return MONO_NATIVE_INT
;
5912 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
5913 return MONO_NATIVE_STRUCT
;
5915 case MONO_TYPE_FNPTR
: return MONO_NATIVE_FUNC
;
5916 case MONO_TYPE_GENERICINST
:
5917 type
= &type
->data
.generic_class
->container_class
->byval_arg
;
5920 case MONO_TYPE_TYPEDBYREF
:
5922 g_error ("type 0x%02x not handled in marshal", t
);
5924 return MONO_NATIVE_MAX
;
5928 mono_metadata_get_marshal_info (MonoImage
*meta
, guint32 idx
, gboolean is_field
)
5931 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_FIELDMARSHAL
];
5937 loc
.col_idx
= MONO_FIELD_MARSHAL_PARENT
;
5938 loc
.idx
= ((idx
+ 1) << MONO_HAS_FIELD_MARSHAL_BITS
) | (is_field
? MONO_HAS_FIELD_MARSHAL_FIELDSREF
: MONO_HAS_FIELD_MARSHAL_PARAMDEF
);
5940 /* FIXME: Index translation */
5942 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5945 return mono_metadata_blob_heap (meta
, mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_MARSHAL_NATIVE_TYPE
));
5949 method_from_method_def_or_ref (MonoImage
*m
, guint32 tok
, MonoGenericContext
*context
, MonoError
*error
)
5951 MonoMethod
*result
= NULL
;
5952 guint32 idx
= tok
>> MONO_METHODDEFORREF_BITS
;
5954 mono_error_init (error
);
5956 switch (tok
& MONO_METHODDEFORREF_MASK
) {
5957 case MONO_METHODDEFORREF_METHODDEF
:
5958 result
= mono_get_method_checked (m
, MONO_TOKEN_METHOD_DEF
| idx
, NULL
, context
, error
);
5960 case MONO_METHODDEFORREF_METHODREF
:
5961 result
= mono_get_method_checked (m
, MONO_TOKEN_MEMBER_REF
| idx
, NULL
, context
, error
);
5964 mono_error_set_bad_image (error
, m
, "Invalid MethodDefOfRef token %x", tok
);
5971 * mono_class_get_overrides_full:
5973 * Return the method overrides belonging to class @type_token in @overrides, and
5974 * the number of overrides in @num_overrides.
5976 * Returns: TRUE on success, FALSE on failure.
5979 mono_class_get_overrides_full (MonoImage
*image
, guint32 type_token
, MonoMethod
***overrides
, gint32
*num_overrides
,
5980 MonoGenericContext
*generic_context
)
5984 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_METHODIMPL
];
5987 guint32 cols
[MONO_METHODIMPL_SIZE
];
5988 MonoMethod
**result
;
5999 loc
.col_idx
= MONO_METHODIMPL_CLASS
;
6000 loc
.idx
= mono_metadata_token_index (type_token
);
6002 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6008 * We may end up in the middle of the rows...
6011 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_METHODIMPL_CLASS
))
6016 while (end
< tdef
->rows
) {
6017 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, end
, MONO_METHODIMPL_CLASS
))
6023 result
= g_new (MonoMethod
*, num
* 2);
6024 for (i
= 0; i
< num
; ++i
) {
6027 if (!mono_verifier_verify_methodimpl_row (image
, start
+ i
, &error
)) {
6028 mono_error_cleanup (&error
); /* FIXME don't swallow the error */
6033 mono_metadata_decode_row (tdef
, start
+ i
, cols
, MONO_METHODIMPL_SIZE
);
6034 method
= method_from_method_def_or_ref (
6035 image
, cols
[MONO_METHODIMPL_DECLARATION
], generic_context
, &error
);
6036 if (method
== NULL
) {
6037 mono_error_cleanup (&error
); /* FIXME don't swallow the error */
6040 result
[i
* 2] = method
;
6041 method
= method_from_method_def_or_ref (
6042 image
, cols
[MONO_METHODIMPL_BODY
], generic_context
, &error
);
6043 if (method
== NULL
) {
6044 mono_error_cleanup (&error
); /* FIXME don't swallow the error */
6047 result
[i
* 2 + 1] = method
;
6050 *overrides
= result
;
6052 *num_overrides
= num
;
6057 * mono_guid_to_string:
6059 * Converts a 16 byte Microsoft GUID to the standard string representation.
6062 mono_guid_to_string (const guint8
*guid
)
6064 return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
6065 guid
[3], guid
[2], guid
[1], guid
[0],
6069 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
6073 * mono_guid_to_string_minimal:
6075 * Converts a 16 byte Microsoft GUID to lower case no '-' representation..
6078 mono_guid_to_string_minimal (const guint8
*guid
)
6080 return g_strdup_printf ("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
6081 guid
[3], guid
[2], guid
[1], guid
[0],
6085 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
6088 get_constraints (MonoImage
*image
, int owner
, MonoClass
***constraints
, MonoGenericContainer
*container
, MonoError
*error
)
6090 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
6091 guint32 cols
[MONO_GENPARCONSTRAINT_SIZE
];
6092 guint32 i
, token
, found
;
6093 MonoClass
*klass
, **res
;
6094 GSList
*cons
= NULL
, *tmp
;
6095 MonoGenericContext
*context
= &container
->context
;
6097 mono_error_init (error
);
6099 *constraints
= NULL
;
6101 for (i
= 0; i
< tdef
->rows
; ++i
) {
6102 mono_metadata_decode_row (tdef
, i
, cols
, MONO_GENPARCONSTRAINT_SIZE
);
6103 if (cols
[MONO_GENPARCONSTRAINT_GENERICPAR
] == owner
) {
6104 token
= mono_metadata_token_from_dor (cols
[MONO_GENPARCONSTRAINT_CONSTRAINT
]);
6105 klass
= mono_class_get_and_inflate_typespec_checked (image
, token
, context
, error
);
6107 g_slist_free (cons
);
6110 cons
= g_slist_append (cons
, klass
);
6113 /* contiguous list finished */
6120 res
= (MonoClass
**)mono_image_alloc0 (image
, sizeof (MonoClass
*) * (found
+ 1));
6121 for (i
= 0, tmp
= cons
; i
< found
; ++i
, tmp
= tmp
->next
) {
6122 res
[i
] = (MonoClass
*)tmp
->data
;
6124 g_slist_free (cons
);
6130 * mono_metadata_get_generic_param_row:
6133 * @token: TypeOrMethodDef token, owner for GenericParam
6134 * @owner: coded token, set on return
6136 * Returns: 1-based row-id in the GenericParam table whose
6137 * owner is @token. 0 if not found.
6140 mono_metadata_get_generic_param_row (MonoImage
*image
, guint32 token
, guint32
*owner
)
6142 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
6149 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPEDEF
)
6150 *owner
= MONO_TYPEORMETHOD_TYPE
;
6151 else if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
6152 *owner
= MONO_TYPEORMETHOD_METHOD
;
6154 g_error ("wrong token %x to get_generic_param_row", token
);
6157 *owner
|= mono_metadata_token_index (token
) << MONO_TYPEORMETHOD_BITS
;
6160 loc
.col_idx
= MONO_GENERICPARAM_OWNER
;
6163 if (!mono_binary_search (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
6166 /* Find the first entry by searching backwards */
6167 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_GENERICPARAM_OWNER
) == loc
.idx
))
6170 return loc
.result
+ 1;
6174 mono_metadata_has_generic_params (MonoImage
*image
, guint32 token
)
6177 return mono_metadata_get_generic_param_row (image
, token
, &owner
);
6181 * Memory is allocated from IMAGE's mempool.
6184 mono_metadata_load_generic_param_constraints_checked (MonoImage
*image
, guint32 token
,
6185 MonoGenericContainer
*container
, MonoError
*error
)
6188 guint32 start_row
, i
, owner
;
6189 mono_error_init (error
);
6191 if (! (start_row
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
6193 for (i
= 0; i
< container
->type_argc
; i
++) {
6194 if (!get_constraints (image
, start_row
+ i
, &mono_generic_container_get_param_info (container
, i
)->constraints
, container
, error
)) {
6202 * mono_metadata_load_generic_params:
6204 * Load the type parameters from the type or method definition @token.
6206 * Use this method after parsing a type or method definition to figure out whether it's a generic
6207 * type / method. When parsing a method definition, @parent_container points to the generic container
6208 * of the current class, if any.
6210 * Note: This method does not load the constraints: for typedefs, this has to be done after fully
6211 * creating the type.
6213 * Returns: NULL if @token is not a generic type or method definition or the new generic container.
6215 * LOCKING: Acquires the loader lock
6218 MonoGenericContainer
*
6219 mono_metadata_load_generic_params (MonoImage
*image
, guint32 token
, MonoGenericContainer
*parent_container
)
6221 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
6222 guint32 cols
[MONO_GENERICPARAM_SIZE
];
6223 guint32 i
, owner
= 0, n
;
6224 MonoGenericContainer
*container
;
6225 MonoGenericParamFull
*params
;
6226 MonoGenericContext
*context
;
6228 if (!(i
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
6230 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
6233 container
= (MonoGenericContainer
*)mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
6234 container
->owner
.image
= image
; // Temporarily mark as anonymous, but this will be overriden by caller
6235 container
->is_anonymous
= TRUE
;
6238 params
= (MonoGenericParamFull
*)g_realloc (params
, sizeof (MonoGenericParamFull
) * n
);
6239 memset (¶ms
[n
- 1], 0, sizeof (MonoGenericParamFull
));
6240 params
[n
- 1].param
.owner
= container
;
6241 params
[n
- 1].param
.num
= cols
[MONO_GENERICPARAM_NUMBER
];
6242 params
[n
- 1].info
.token
= i
| MONO_TOKEN_GENERIC_PARAM
;
6243 params
[n
- 1].info
.flags
= cols
[MONO_GENERICPARAM_FLAGS
];
6244 params
[n
- 1].info
.name
= mono_metadata_string_heap (image
, cols
[MONO_GENERICPARAM_NAME
]);
6245 if (params
[n
- 1].param
.num
!= n
- 1)
6246 g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i
);
6247 if (++i
> tdef
->rows
)
6249 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
6250 } while (cols
[MONO_GENERICPARAM_OWNER
] == owner
);
6252 container
->type_argc
= n
;
6253 container
->type_params
= (MonoGenericParamFull
*)mono_image_alloc0 (image
, sizeof (MonoGenericParamFull
) * n
);
6254 memcpy (container
->type_params
, params
, sizeof (MonoGenericParamFull
) * n
);
6256 container
->parent
= parent_container
;
6258 if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
6259 container
->is_method
= 1;
6261 g_assert (container
->parent
== NULL
|| container
->is_method
);
6263 context
= &container
->context
;
6264 if (container
->is_method
) {
6265 context
->class_inst
= container
->parent
? container
->parent
->context
.class_inst
: NULL
;
6266 context
->method_inst
= mono_get_shared_generic_inst (container
);
6268 context
->class_inst
= mono_get_shared_generic_inst (container
);
6275 mono_get_shared_generic_inst (MonoGenericContainer
*container
)
6277 MonoType
**type_argv
;
6279 MonoGenericInst
*nginst
;
6282 type_argv
= g_new0 (MonoType
*, container
->type_argc
);
6283 helper
= g_new0 (MonoType
, container
->type_argc
);
6285 for (i
= 0; i
< container
->type_argc
; i
++) {
6286 MonoType
*t
= &helper
[i
];
6288 t
->type
= container
->is_method
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
6289 t
->data
.generic_param
= mono_generic_container_get_param (container
, i
);
6294 nginst
= mono_metadata_get_generic_inst (container
->type_argc
, type_argv
);
6303 * mono_type_is_byref:
6304 * @type: the MonoType operated on
6306 * Returns: #TRUE if @type represents a type passed by reference,
6310 mono_type_is_byref (MonoType
*type
)
6316 * mono_type_get_type:
6317 * @type: the MonoType operated on
6319 * Returns: the IL type value for @type. This is one of the MonoTypeEnum
6320 * enum members like MONO_TYPE_I4 or MONO_TYPE_STRING.
6323 mono_type_get_type (MonoType
*type
)
6329 * mono_type_get_signature:
6330 * @type: the MonoType operated on
6332 * It is only valid to call this function if @type is a MONO_TYPE_FNPTR.
6334 * Returns: the MonoMethodSignature pointer that describes the signature
6335 * of the function pointer @type represents.
6337 MonoMethodSignature
*
6338 mono_type_get_signature (MonoType
*type
)
6340 g_assert (type
->type
== MONO_TYPE_FNPTR
);
6341 return type
->data
.method
;
6345 * mono_type_get_class:
6346 * @type: the MonoType operated on
6348 * It is only valid to call this function if @type is a MONO_TYPE_CLASS or a
6349 * MONO_TYPE_VALUETYPE. For more general functionality, use mono_class_from_mono_type (),
6352 * Returns: the MonoClass pointer that describes the class that @type represents.
6355 mono_type_get_class (MonoType
*type
)
6357 /* FIXME: review the runtime users before adding the assert here */
6358 return type
->data
.klass
;
6362 * mono_type_get_array_type:
6363 * @type: the MonoType operated on
6365 * It is only valid to call this function if @type is a MONO_TYPE_ARRAY.
6367 * Returns: a MonoArrayType struct describing the array type that @type
6368 * represents. The info includes details such as rank, array element type
6369 * and the sizes and bounds of multidimensional arrays.
6372 mono_type_get_array_type (MonoType
*type
)
6374 return type
->data
.array
;
6378 * mono_type_get_ptr_type:
6379 * @type: the MonoType operated on
6381 * It is only valid to call this function if @type is a MONO_TYPE_PTR.
6384 * Returns: the MonoType pointer that describes the type that @type
6385 * represents a pointer to.
6388 mono_type_get_ptr_type (MonoType
*type
)
6390 g_assert (type
->type
== MONO_TYPE_PTR
);
6391 return type
->data
.type
;
6395 mono_type_get_modifiers (MonoType
*type
, gboolean
*is_required
, gpointer
*iter
)
6397 /* FIXME: implement */
6402 * mono_type_is_struct:
6403 * @type: the MonoType operated on
6405 * Returns: #TRUE is @type is a struct, that is a ValueType but not en enum
6406 * or a basic type like System.Int32. #FALSE otherwise.
6409 mono_type_is_struct (MonoType
*type
)
6411 return (!type
->byref
&& ((type
->type
== MONO_TYPE_VALUETYPE
&&
6412 !type
->data
.klass
->enumtype
) || (type
->type
== MONO_TYPE_TYPEDBYREF
) ||
6413 ((type
->type
== MONO_TYPE_GENERICINST
) &&
6414 mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
) &&
6415 !type
->data
.generic_class
->container_class
->enumtype
)));
6419 * mono_type_is_void:
6420 * @type: the MonoType operated on
6422 * Returns: #TRUE is @type is System.Void. #FALSE otherwise.
6425 mono_type_is_void (MonoType
*type
)
6427 return (type
&& (type
->type
== MONO_TYPE_VOID
) && !type
->byref
);
6431 * mono_type_is_pointer:
6432 * @type: the MonoType operated on
6434 * Returns: #TRUE is @type is a managed or unmanaged pointer type. #FALSE otherwise.
6437 mono_type_is_pointer (MonoType
*type
)
6439 return (type
&& ((type
->byref
|| (type
->type
== MONO_TYPE_I
) || type
->type
== MONO_TYPE_STRING
)
6440 || (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
6441 (type
->type
== MONO_TYPE_U
) || (type
->type
== MONO_TYPE_OBJECT
) ||
6442 (type
->type
== MONO_TYPE_ARRAY
) || (type
->type
== MONO_TYPE_PTR
) ||
6443 (type
->type
== MONO_TYPE_FNPTR
)));
6447 * mono_type_is_reference:
6448 * @type: the MonoType operated on
6450 * Returns: #TRUE is @type represents an object reference . #FALSE otherwise.
6453 mono_type_is_reference (MonoType
*type
)
6455 return (type
&& (((type
->type
== MONO_TYPE_STRING
) ||
6456 (type
->type
== MONO_TYPE_SZARRAY
) || (type
->type
== MONO_TYPE_CLASS
) ||
6457 (type
->type
== MONO_TYPE_OBJECT
) || (type
->type
== MONO_TYPE_ARRAY
)) ||
6458 ((type
->type
== MONO_TYPE_GENERICINST
) &&
6459 !mono_metadata_generic_class_is_valuetype (type
->data
.generic_class
))));
6463 mono_type_is_generic_parameter (MonoType
*type
)
6465 return !type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
);
6469 * mono_signature_get_return_type:
6470 * @sig: the method signature inspected
6472 * Returns: the return type of the method signature @sig
6475 mono_signature_get_return_type (MonoMethodSignature
*sig
)
6481 * mono_signature_get_params:
6482 * @sig: the method signature inspected
6483 * #iter: pointer to an iterator
6485 * Iterates over the parameters for the method signature @sig.
6486 * A void* pointer must be initualized to #NULL to start the iteration
6487 * and it's address is passed to this function repeteadly until it returns
6490 * Returns: the next parameter type of the method signature @sig,
6491 * #NULL when finished.
6494 mono_signature_get_params (MonoMethodSignature
*sig
, gpointer
*iter
)
6500 /* start from the first */
6501 if (sig
->param_count
) {
6502 *iter
= &sig
->params
[0];
6503 return sig
->params
[0];
6509 type
= (MonoType
**)*iter
;
6511 if (type
< &sig
->params
[sig
->param_count
]) {
6519 * mono_signature_get_param_count:
6520 * @sig: the method signature inspected
6522 * Returns: the number of parameters in the method signature @sig.
6525 mono_signature_get_param_count (MonoMethodSignature
*sig
)
6527 return sig
->param_count
;
6531 * mono_signature_get_call_conv:
6532 * @sig: the method signature inspected
6534 * Returns: the call convention of the method signature @sig.
6537 mono_signature_get_call_conv (MonoMethodSignature
*sig
)
6539 return sig
->call_convention
;
6543 * mono_signature_vararg_start:
6544 * @sig: the method signature inspected
6546 * Returns: the number of the first vararg parameter in the
6547 * method signature @sig. -1 if this is not a vararg signature.
6550 mono_signature_vararg_start (MonoMethodSignature
*sig
)
6552 return sig
->sentinelpos
;
6556 * mono_signature_is_instance:
6557 * @sig: the method signature inspected
6559 * Returns: #TRUE if this the method signature @sig has an implicit
6560 * first instance argument. #FALSE otherwise.
6563 mono_signature_is_instance (MonoMethodSignature
*sig
)
6565 return sig
->hasthis
;
6569 * mono_signature_param_is_out
6570 * @sig: the method signature inspected
6571 * @param_num: the 0-based index of the inspected parameter
6573 * Returns: #TRUE if the parameter is an out parameter, #FALSE
6577 mono_signature_param_is_out (MonoMethodSignature
*sig
, int param_num
)
6579 g_assert (param_num
>= 0 && param_num
< sig
->param_count
);
6580 return (sig
->params
[param_num
]->attrs
& PARAM_ATTRIBUTE_OUT
) != 0;
6584 * mono_signature_explicit_this:
6585 * @sig: the method signature inspected
6587 * Returns: #TRUE if this the method signature @sig has an explicit
6588 * instance argument. #FALSE otherwise.
6591 mono_signature_explicit_this (MonoMethodSignature
*sig
)
6593 return sig
->explicit_this
;
6596 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
6598 mono_aligned_addr_hash (gconstpointer ptr
)
6600 return GPOINTER_TO_UINT (ptr
) >> 3;
6604 * If @field belongs to an inflated generic class, return the corresponding field of the
6605 * generic type definition class.
6608 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField
*field
)
6613 if (!field
->parent
->generic_class
)
6616 gtd
= field
->parent
->generic_class
->container_class
;
6617 offset
= field
- field
->parent
->fields
;
6618 return gtd
->fields
+ offset
;
6622 * If @event belongs to an inflated generic class, return the corresponding event of the
6623 * generic type definition class.
6626 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent
*event
)
6631 if (!event
->parent
->generic_class
)
6634 gtd
= event
->parent
->generic_class
->container_class
;
6635 offset
= event
- event
->parent
->ext
->events
;
6636 return gtd
->ext
->events
+ offset
;
6640 * If @property belongs to an inflated generic class, return the corresponding property of the
6641 * generic type definition class.
6644 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty
*property
)
6649 if (!property
->parent
->generic_class
)
6652 gtd
= property
->parent
->generic_class
->container_class
;
6653 offset
= property
- property
->parent
->ext
->properties
;
6654 return gtd
->ext
->properties
+ offset
;
6658 mono_method_get_wrapper_cache (MonoMethod
*method
)
6660 if (method
->is_inflated
) {
6661 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
6662 return &imethod
->owner
->wrapper_caches
;
6664 return &method
->klass
->image
->wrapper_caches
;
6668 // 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.
6671 * mono_find_image_set_owner:
6673 * Find the imageset, if any, which a given pointer is located in the memory of.
6676 mono_find_image_set_owner (void *ptr
)
6678 MonoImageSet
*owner
= NULL
;
6685 for (i
= 0; !owner
&& i
< image_sets
->len
; ++i
) {
6686 MonoImageSet
*set
= (MonoImageSet
*)g_ptr_array_index (image_sets
, i
);
6687 if (mono_mempool_contains_addr (set
->mempool
, ptr
))
6692 image_sets_unlock ();