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)
21 #include "tabledefs.h"
22 #include "mono-endian.h"
24 #include "tokentype.h"
25 #include "metadata-internals.h"
26 #include "class-internals.h"
27 #include "verify-internals.h"
30 #include "gc-internal.h"
31 #include <mono/utils/mono-error-internals.h>
34 static gboolean
do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
35 const char *ptr
, const char **rptr
);
37 static gboolean
do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
);
38 static gboolean
mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
);
39 static gboolean
mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
);
40 static gboolean
_mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
,
41 gboolean signature_only
);
42 static void free_generic_inst (MonoGenericInst
*ginst
);
43 static void free_generic_class (MonoGenericClass
*ginst
);
44 static void free_inflated_method (MonoMethodInflated
*method
);
45 static void mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
, MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
);
48 * This enumeration is used to describe the data types in the metadata
59 /* Index into Blob heap */
62 /* Index into String heap */
68 /* Pointer into a table */
71 /* HasConstant:Parent pointer (Param, Field or Property) */
74 /* HasCustomAttribute index. Indexes any table except CustomAttribute */
77 /* CustomAttributeType encoded index */
80 /* HasDeclSecurity index: TypeDef Method or Assembly */
83 /* Implementation coded index: File, Export AssemblyRef */
86 /* HasFieldMarshal coded index: Field or Param table */
89 /* MemberForwardedIndex: Field or Method */
92 /* TypeDefOrRef coded index: typedef, typeref, typespec */
95 /* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
98 /* MethodDefOrRef coded index: Method or Member Ref table */
101 /* HasSemantic coded index: Event or Property */
104 /* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
108 const static unsigned char TableSchemas
[] = {
109 #define ASSEMBLY_SCHEMA_OFFSET 0
110 MONO_MT_UINT32
, /* "HashId" }, */
111 MONO_MT_UINT16
, /* "Major" }, */
112 MONO_MT_UINT16
, /* "Minor" }, */
113 MONO_MT_UINT16
, /* "BuildNumber" }, */
114 MONO_MT_UINT16
, /* "RevisionNumber" }, */
115 MONO_MT_UINT32
, /* "Flags" }, */
116 MONO_MT_BLOB_IDX
, /* "PublicKey" }, */
117 MONO_MT_STRING_IDX
, /* "Name" }, */
118 MONO_MT_STRING_IDX
, /* "Culture" }, */
121 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
122 MONO_MT_UINT32
, /* "OSPlatformID" }, */
123 MONO_MT_UINT32
, /* "OSMajor" }, */
124 MONO_MT_UINT32
, /* "OSMinor" }, */
127 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
128 MONO_MT_UINT32
, /* "Processor" }, */
131 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
132 MONO_MT_UINT16
, /* "Major" }, */
133 MONO_MT_UINT16
, /* "Minor" }, */
134 MONO_MT_UINT16
, /* "Build" }, */
135 MONO_MT_UINT16
, /* "Revision" }, */
136 MONO_MT_UINT32
, /* "Flags" }, */
137 MONO_MT_BLOB_IDX
, /* "PublicKeyOrToken" }, */
138 MONO_MT_STRING_IDX
, /* "Name" }, */
139 MONO_MT_STRING_IDX
, /* "Culture" }, */
140 MONO_MT_BLOB_IDX
, /* "HashValue" }, */
143 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
144 MONO_MT_UINT32
, /* "OSPlatformID" }, */
145 MONO_MT_UINT32
, /* "OSMajorVersion" }, */
146 MONO_MT_UINT32
, /* "OSMinorVersion" }, */
147 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
150 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
151 MONO_MT_UINT32
, /* "Processor" }, */
152 MONO_MT_TABLE_IDX
, /* "AssemblyRef:AssemblyRef" }, */
155 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
156 MONO_MT_UINT16
, /* "PackingSize" }, */
157 MONO_MT_UINT32
, /* "ClassSize" }, */
158 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
161 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
162 MONO_MT_UINT8
, /* "Type" }, */
163 MONO_MT_UINT8
, /* "PaddingZero" }, */
164 MONO_MT_CONST_IDX
, /* "Parent" }, */
165 MONO_MT_BLOB_IDX
, /* "Value" }, */
168 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
169 MONO_MT_HASCAT_IDX
, /* "Parent" }, */
170 MONO_MT_CAT_IDX
, /* "Type" }, */
171 MONO_MT_BLOB_IDX
, /* "Value" }, */
174 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
175 MONO_MT_UINT16
, /* "Action" }, */
176 MONO_MT_HASDEC_IDX
, /* "Parent" }, */
177 MONO_MT_BLOB_IDX
, /* "PermissionSet" }, */
180 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
181 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
182 MONO_MT_TABLE_IDX
, /* "EventList:Event" }, */
185 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
186 MONO_MT_UINT16
, /* "EventFlags#EventAttribute" }, */
187 MONO_MT_STRING_IDX
, /* "Name" }, */
188 MONO_MT_TDOR_IDX
, /* "EventType" }, TypeDef or TypeRef or TypeSpec */
191 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
192 MONO_MT_TABLE_IDX
, /* "Event" }, */
195 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
196 MONO_MT_UINT32
, /* "Flags" }, */
197 MONO_MT_TABLE_IDX
, /* "TypeDefId" }, */
198 MONO_MT_STRING_IDX
, /* "TypeName" }, */
199 MONO_MT_STRING_IDX
, /* "TypeNameSpace" }, */
200 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
203 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
204 MONO_MT_UINT16
, /* "Flags" }, */
205 MONO_MT_STRING_IDX
, /* "Name" }, */
206 MONO_MT_BLOB_IDX
, /* "Signature" }, */
209 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
210 MONO_MT_UINT32
, /* "Offset" }, */
211 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
214 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
215 MONO_MT_HFM_IDX
, /* "Parent" }, */
216 MONO_MT_BLOB_IDX
, /* "NativeType" }, */
219 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
220 MONO_MT_UINT32
, /* "RVA" }, */
221 MONO_MT_TABLE_IDX
, /* "Field:Field" }, */
224 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
225 MONO_MT_TABLE_IDX
, /* "Field" }, */
228 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
229 MONO_MT_UINT32
, /* "Flags" }, */
230 MONO_MT_STRING_IDX
, /* "Name" }, */
231 MONO_MT_BLOB_IDX
, /* "Value" }, */
234 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
235 MONO_MT_UINT16
, /* "MappingFlag" }, */
236 MONO_MT_MF_IDX
, /* "MemberForwarded" }, */
237 MONO_MT_STRING_IDX
, /* "ImportName" }, */
238 MONO_MT_TABLE_IDX
, /* "ImportScope:ModuleRef" }, */
241 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
242 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
243 MONO_MT_TDOR_IDX
, /* "Interface=TypeDefOrRef" }, */
246 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
247 MONO_MT_UINT32
, /* "Offset" }, */
248 MONO_MT_UINT32
, /* "Flags" }, */
249 MONO_MT_STRING_IDX
, /* "Name" }, */
250 MONO_MT_IMPL_IDX
, /* "Implementation" }, */
253 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
254 MONO_MT_MRP_IDX
, /* "Class" }, */
255 MONO_MT_STRING_IDX
, /* "Name" }, */
256 MONO_MT_BLOB_IDX
, /* "Signature" }, */
259 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
260 MONO_MT_UINT32
, /* "RVA" }, */
261 MONO_MT_UINT16
, /* "ImplFlags#MethodImplAttributes" }, */
262 MONO_MT_UINT16
, /* "Flags#MethodAttribute" }, */
263 MONO_MT_STRING_IDX
, /* "Name" }, */
264 MONO_MT_BLOB_IDX
, /* "Signature" }, */
265 MONO_MT_TABLE_IDX
, /* "ParamList:Param" }, */
268 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
269 MONO_MT_TABLE_IDX
, /* "Class:TypeDef" }, */
270 MONO_MT_MDOR_IDX
, /* "MethodBody" }, */
271 MONO_MT_MDOR_IDX
, /* "MethodDeclaration" }, */
274 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
275 MONO_MT_UINT16
, /* "MethodSemantic" }, */
276 MONO_MT_TABLE_IDX
, /* "Method:Method" }, */
277 MONO_MT_HS_IDX
, /* "Association" }, */
280 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
281 MONO_MT_TABLE_IDX
, /* "Method" }, */
284 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
285 MONO_MT_UINT16
, /* "Generation" }, */
286 MONO_MT_STRING_IDX
, /* "Name" }, */
287 MONO_MT_GUID_IDX
, /* "MVID" }, */
288 MONO_MT_GUID_IDX
, /* "EncID" }, */
289 MONO_MT_GUID_IDX
, /* "EncBaseID" }, */
292 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
293 MONO_MT_STRING_IDX
, /* "Name" }, */
296 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
297 MONO_MT_TABLE_IDX
, /* "NestedClass:TypeDef" }, */
298 MONO_MT_TABLE_IDX
, /* "EnclosingClass:TypeDef" }, */
301 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
302 MONO_MT_UINT16
, /* "Flags" }, */
303 MONO_MT_UINT16
, /* "Sequence" }, */
304 MONO_MT_STRING_IDX
, /* "Name" }, */
307 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
308 MONO_MT_TABLE_IDX
, /* "Param" }, */
311 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
312 MONO_MT_UINT16
, /* "Flags" }, */
313 MONO_MT_STRING_IDX
, /* "Name" }, */
314 MONO_MT_BLOB_IDX
, /* "Type" }, */
317 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
318 MONO_MT_TABLE_IDX
, /* "Property" }, */
321 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
322 MONO_MT_TABLE_IDX
, /* "Parent:TypeDef" }, */
323 MONO_MT_TABLE_IDX
, /* "PropertyList:Property" }, */
326 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
327 MONO_MT_BLOB_IDX
, /* "Signature" }, */
330 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
331 MONO_MT_UINT32
, /* "Flags" }, */
332 MONO_MT_STRING_IDX
, /* "Name" }, */
333 MONO_MT_STRING_IDX
, /* "Namespace" }, */
334 MONO_MT_TDOR_IDX
, /* "Extends" }, */
335 MONO_MT_TABLE_IDX
, /* "FieldList:Field" }, */
336 MONO_MT_TABLE_IDX
, /* "MethodList:Method" }, */
339 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
340 MONO_MT_RS_IDX
, /* "ResolutionScope=ResolutionScope" }, */
341 MONO_MT_STRING_IDX
, /* "Name" }, */
342 MONO_MT_STRING_IDX
, /* "Namespace" }, */
345 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
346 MONO_MT_BLOB_IDX
, /* "Signature" }, */
349 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
350 MONO_MT_UINT16
, /* "Number" }, */
351 MONO_MT_UINT16
, /* "Flags" }, */
352 MONO_MT_TABLE_IDX
, /* "Owner" }, TypeDef or MethodDef */
353 MONO_MT_STRING_IDX
, /* "Name" }, */
356 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
357 MONO_MT_MDOR_IDX
, /* "Method" }, */
358 MONO_MT_BLOB_IDX
, /* "Signature" }, */
361 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
362 MONO_MT_TABLE_IDX
, /* "GenericParam" }, */
363 MONO_MT_TDOR_IDX
, /* "Constraint" }, */
366 #define NULL_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
370 /* Must be the same order as MONO_TABLE_* */
371 const static unsigned char
372 table_description
[] = {
373 MODULE_SCHEMA_OFFSET
,
374 TYPEREF_SCHEMA_OFFSET
,
375 TYPEDEF_SCHEMA_OFFSET
,
376 FIELD_POINTER_SCHEMA_OFFSET
,
378 METHOD_POINTER_SCHEMA_OFFSET
,
379 METHOD_SCHEMA_OFFSET
,
380 PARAM_POINTER_SCHEMA_OFFSET
,
382 IFACEMAP_SCHEMA_OFFSET
,
383 MEMBERREF_SCHEMA_OFFSET
, /* 0xa */
384 CONSTANT_SCHEMA_OFFSET
,
385 CUSTOM_ATTR_SCHEMA_OFFSET
,
386 FIELD_MARSHAL_SCHEMA_OFFSET
,
387 DECL_SEC_SCHEMA_OFFSET
,
388 CLASS_LAYOUT_SCHEMA_OFFSET
,
389 FIELD_LAYOUT_SCHEMA_OFFSET
, /* 0x10 */
390 STDALON_SIG_SCHEMA_OFFSET
,
391 EVENTMAP_SCHEMA_OFFSET
,
392 EVENT_POINTER_SCHEMA_OFFSET
,
394 PROPERTY_MAP_SCHEMA_OFFSET
,
395 PROPERTY_POINTER_SCHEMA_OFFSET
,
396 PROPERTY_SCHEMA_OFFSET
,
397 METHOD_SEMA_SCHEMA_OFFSET
,
398 METHOD_IMPL_SCHEMA_OFFSET
,
399 MODULEREF_SCHEMA_OFFSET
, /* 0x1a */
400 TYPESPEC_SCHEMA_OFFSET
,
401 IMPLMAP_SCHEMA_OFFSET
,
402 FIELD_RVA_SCHEMA_OFFSET
,
405 ASSEMBLY_SCHEMA_OFFSET
, /* 0x20 */
406 ASSEMBLYPROC_SCHEMA_OFFSET
,
407 ASSEMBLYOS_SCHEMA_OFFSET
,
408 ASSEMBLYREF_SCHEMA_OFFSET
,
409 ASSEMBLYREFPROC_SCHEMA_OFFSET
,
410 ASSEMBLYREFOS_SCHEMA_OFFSET
,
412 EXPORTED_TYPE_SCHEMA_OFFSET
,
413 MANIFEST_SCHEMA_OFFSET
,
414 NESTED_CLASS_SCHEMA_OFFSET
,
415 GENPARAM_SCHEMA_OFFSET
, /* 0x2a */
416 METHOD_SPEC_SCHEMA_OFFSET
,
417 GEN_CONSTRAINT_SCHEMA_OFFSET
420 #ifdef HAVE_ARRAY_ELEM_INIT
421 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
422 #define MSGSTRFIELD1(line) str##line
423 static const struct msgstr_t
{
424 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
425 #include "mono/cil/tables.def"
428 #define TABLEDEF(a,b) b,
429 #include "mono/cil/tables.def"
432 static const gint16 tableidx
[] = {
433 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
434 #include "mono/cil/tables.def"
439 #define TABLEDEF(a,b) b,
440 static const char* const
441 mono_tables_names
[] = {
442 #include "mono/cil/tables.def"
448 /* Auxiliary structure used for caching inflated signatures */
450 MonoMethodSignature
*sig
;
451 MonoGenericContext context
;
452 } MonoInflatedMethodSignature
;
455 * mono_meta_table_name:
456 * @table: table index
458 * Returns the name of the given ECMA metadata logical format table
459 * as described in ECMA 335, Partition II, Section 22.
461 * Returns: the name for the @table index
464 mono_meta_table_name (int table
)
466 if ((table
< 0) || (table
> MONO_TABLE_LAST
))
469 #ifdef HAVE_ARRAY_ELEM_INIT
470 return (const char*)&tablestr
+ tableidx
[table
];
472 return mono_tables_names
[table
];
476 /* The guy who wrote the spec for this should not be allowed near a
479 If e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
480 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
481 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
482 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
483 inverse of this mapping.
486 #define rtsize(s,b) (((s) < (1 << (b)) ? 2 : 4))
487 #define idx_size(tableidx) (meta->tables [(tableidx)].rows < 65536 ? 2 : 4)
489 /* Reference: Partition II - 23.2.6 */
491 * mono_metadata_compute_size:
492 * @meta: metadata context
493 * @tableindex: metadata table number
494 * @result_bitfield: pointer to guint32 where to store additional info
496 * mono_metadata_compute_size() computes the lenght in bytes of a single
497 * row in a metadata table. The size of each column is encoded in the
498 * @result_bitfield return value along with the number of columns in the table.
499 * the resulting bitfield should be handed to the mono_metadata_table_size()
500 * and mono_metadata_table_count() macros.
501 * This is a Mono runtime internal only function.
504 mono_metadata_compute_size (MonoImage
*meta
, int tableindex
, guint32
*result_bitfield
)
506 guint32 bitfield
= 0;
507 int size
= 0, field_size
= 0;
510 const unsigned char *description
= TableSchemas
+ table_description
[tableindex
];
512 for (i
= 0; (code
= description
[i
]) != MONO_MT_END
; i
++){
515 field_size
= 4; break;
518 field_size
= 2; break;
521 field_size
= 1; break;
523 case MONO_MT_BLOB_IDX
:
524 field_size
= meta
->idx_blob_wide
? 4 : 2; break;
526 case MONO_MT_STRING_IDX
:
527 field_size
= meta
->idx_string_wide
? 4 : 2; break;
529 case MONO_MT_GUID_IDX
:
530 field_size
= meta
->idx_guid_wide
? 4 : 2; break;
532 case MONO_MT_TABLE_IDX
:
533 /* Uhm, a table index can point to other tables besides the current one
534 * so, it's not correct to use the rowcount of the current table to
535 * get the size for this column - lupus
537 switch (tableindex
) {
538 case MONO_TABLE_ASSEMBLYREFOS
:
540 field_size
= idx_size (MONO_TABLE_ASSEMBLYREF
); break;
541 case MONO_TABLE_ASSEMBLYREFPROCESSOR
:
543 field_size
= idx_size (MONO_TABLE_ASSEMBLYREF
); break;
544 case MONO_TABLE_CLASSLAYOUT
:
546 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
547 case MONO_TABLE_EVENTMAP
:
548 g_assert (i
== 0 || i
== 1);
549 field_size
= i
? idx_size (MONO_TABLE_EVENT
):
550 idx_size(MONO_TABLE_TYPEDEF
);
552 case MONO_TABLE_EVENT_POINTER
:
554 field_size
= idx_size (MONO_TABLE_EVENT
); break;
555 case MONO_TABLE_EXPORTEDTYPE
:
557 /* the index is in another metadata file, so it must be 4 */
558 field_size
= 4; break;
559 case MONO_TABLE_FIELDLAYOUT
:
561 field_size
= idx_size (MONO_TABLE_FIELD
); break;
562 case MONO_TABLE_FIELDRVA
:
564 field_size
= idx_size (MONO_TABLE_FIELD
); break;
565 case MONO_TABLE_FIELD_POINTER
:
567 field_size
= idx_size (MONO_TABLE_FIELD
); break;
568 case MONO_TABLE_IMPLMAP
:
570 field_size
= idx_size (MONO_TABLE_MODULEREF
); break;
571 case MONO_TABLE_INTERFACEIMPL
:
573 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
574 case MONO_TABLE_METHOD
:
576 field_size
= idx_size (MONO_TABLE_PARAM
); break;
577 case MONO_TABLE_METHODIMPL
:
579 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
580 case MONO_TABLE_METHODSEMANTICS
:
582 field_size
= idx_size (MONO_TABLE_METHOD
); break;
583 case MONO_TABLE_METHOD_POINTER
:
585 field_size
= idx_size (MONO_TABLE_METHOD
); break;
586 case MONO_TABLE_NESTEDCLASS
:
587 g_assert (i
== 0 || i
== 1);
588 field_size
= idx_size (MONO_TABLE_TYPEDEF
); break;
589 case MONO_TABLE_PARAM_POINTER
:
591 field_size
= idx_size (MONO_TABLE_PARAM
); break;
592 case MONO_TABLE_PROPERTYMAP
:
593 g_assert (i
== 0 || i
== 1);
594 field_size
= i
? idx_size (MONO_TABLE_PROPERTY
):
595 idx_size(MONO_TABLE_TYPEDEF
);
597 case MONO_TABLE_PROPERTY_POINTER
:
599 field_size
= idx_size (MONO_TABLE_PROPERTY
); break;
600 case MONO_TABLE_TYPEDEF
:
601 g_assert (i
== 4 || i
== 5);
602 field_size
= i
== 4 ? idx_size (MONO_TABLE_FIELD
):
603 idx_size(MONO_TABLE_METHOD
);
605 case MONO_TABLE_GENERICPARAM
:
607 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
, meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
608 /*This is a coded token for 2 tables, so takes 1 bit */
609 field_size
= rtsize (n
, 16 - MONO_TYPEORMETHOD_BITS
);
611 case MONO_TABLE_GENERICPARAMCONSTRAINT
:
613 field_size
= idx_size (MONO_TABLE_GENERICPARAM
);
617 g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex
, i
);
622 * HasConstant: ParamDef, FieldDef, Property
624 case MONO_MT_CONST_IDX
:
625 n
= MAX (meta
->tables
[MONO_TABLE_PARAM
].rows
,
626 meta
->tables
[MONO_TABLE_FIELD
].rows
);
627 n
= MAX (n
, meta
->tables
[MONO_TABLE_PROPERTY
].rows
);
629 /* 2 bits to encode tag */
630 field_size
= rtsize (n
, 16-2);
634 * HasCustomAttribute: points to any table but
637 case MONO_MT_HASCAT_IDX
:
639 * We believe that since the signature and
640 * permission are indexing the Blob heap,
641 * we should consider the blob size first
643 /* I'm not a believer - lupus
644 if (meta->idx_blob_wide){
649 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
,
650 meta
->tables
[MONO_TABLE_FIELD
].rows
);
651 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
652 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
653 n
= MAX (n
, meta
->tables
[MONO_TABLE_PARAM
].rows
);
654 n
= MAX (n
, meta
->tables
[MONO_TABLE_INTERFACEIMPL
].rows
);
655 n
= MAX (n
, meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
656 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULE
].rows
);
657 n
= MAX (n
, meta
->tables
[MONO_TABLE_DECLSECURITY
].rows
);
658 n
= MAX (n
, meta
->tables
[MONO_TABLE_PROPERTY
].rows
);
659 n
= MAX (n
, meta
->tables
[MONO_TABLE_EVENT
].rows
);
660 n
= MAX (n
, meta
->tables
[MONO_TABLE_STANDALONESIG
].rows
);
661 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
662 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
663 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLY
].rows
);
664 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
665 n
= MAX (n
, meta
->tables
[MONO_TABLE_FILE
].rows
);
666 n
= MAX (n
, meta
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
);
667 n
= MAX (n
, meta
->tables
[MONO_TABLE_MANIFESTRESOURCE
].rows
);
669 /* 5 bits to encode */
670 field_size
= rtsize (n
, 16-5);
674 * CustomAttributeType: TypeDef, TypeRef, MethodDef,
675 * MemberRef and String.
677 case MONO_MT_CAT_IDX
:
678 /* String is a heap, if it is wide, we know the size */
680 if (meta->idx_string_wide){
685 n
= MAX (meta
->tables
[MONO_TABLE_TYPEREF
].rows
,
686 meta
->tables
[MONO_TABLE_TYPEDEF
].rows
);
687 n
= MAX (n
, meta
->tables
[MONO_TABLE_METHOD
].rows
);
688 n
= MAX (n
, meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
690 /* 3 bits to encode */
691 field_size
= rtsize (n
, 16-3);
695 * HasDeclSecurity: Typedef, MethodDef, Assembly
697 case MONO_MT_HASDEC_IDX
:
698 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
699 meta
->tables
[MONO_TABLE_METHOD
].rows
);
700 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLY
].rows
);
702 /* 2 bits to encode */
703 field_size
= rtsize (n
, 16-2);
707 * Implementation: File, AssemblyRef, ExportedType
709 case MONO_MT_IMPL_IDX
:
710 n
= MAX (meta
->tables
[MONO_TABLE_FILE
].rows
,
711 meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
712 n
= MAX (n
, meta
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
);
714 /* 2 bits to encode tag */
715 field_size
= rtsize (n
, 16-2);
719 * HasFieldMarshall: FieldDef, ParamDef
721 case MONO_MT_HFM_IDX
:
722 n
= MAX (meta
->tables
[MONO_TABLE_FIELD
].rows
,
723 meta
->tables
[MONO_TABLE_PARAM
].rows
);
725 /* 1 bit used to encode tag */
726 field_size
= rtsize (n
, 16-1);
730 * MemberForwarded: FieldDef, MethodDef
733 n
= MAX (meta
->tables
[MONO_TABLE_FIELD
].rows
,
734 meta
->tables
[MONO_TABLE_METHOD
].rows
);
736 /* 1 bit used to encode tag */
737 field_size
= rtsize (n
, 16-1);
741 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
743 * It is TypeDef, _TypeRef_, TypeSpec, instead.
745 case MONO_MT_TDOR_IDX
:
746 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
747 meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
748 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
750 /* 2 bits to encode */
751 field_size
= rtsize (n
, 16-2);
755 * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
757 case MONO_MT_MRP_IDX
:
758 n
= MAX (meta
->tables
[MONO_TABLE_TYPEDEF
].rows
,
759 meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
760 n
= MAX (n
, meta
->tables
[MONO_TABLE_METHOD
].rows
);
761 n
= MAX (n
, meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
762 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPESPEC
].rows
);
763 n
= MAX (n
, meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
765 /* 3 bits to encode */
766 field_size
= rtsize (n
, 16 - 3);
770 * MethodDefOrRef: MethodDef, MemberRef
772 case MONO_MT_MDOR_IDX
:
773 n
= MAX (meta
->tables
[MONO_TABLE_METHOD
].rows
,
774 meta
->tables
[MONO_TABLE_MEMBERREF
].rows
);
776 /* 1 bit used to encode tag */
777 field_size
= rtsize (n
, 16-1);
781 * HasSemantics: Property, Event
784 n
= MAX (meta
->tables
[MONO_TABLE_PROPERTY
].rows
,
785 meta
->tables
[MONO_TABLE_EVENT
].rows
);
787 /* 1 bit used to encode tag */
788 field_size
= rtsize (n
, 16-1);
792 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
795 n
= MAX (meta
->tables
[MONO_TABLE_MODULE
].rows
,
796 meta
->tables
[MONO_TABLE_MODULEREF
].rows
);
797 n
= MAX (n
, meta
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
);
798 n
= MAX (n
, meta
->tables
[MONO_TABLE_TYPEREF
].rows
);
800 /* 2 bits used to encode tag (ECMA spec claims 3) */
801 field_size
= rtsize (n
, 16 - 2);
806 * encode field size as follows (we just need to
813 bitfield
|= (field_size
-1) << shift
;
816 /*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
819 *result_bitfield
= (i
<< 24) | bitfield
;
824 * mono_metadata_compute_table_bases:
825 * @meta: metadata context to compute table values
827 * Computes the table bases for the metadata structure.
828 * This is an internal function used by the image loader code.
831 mono_metadata_compute_table_bases (MonoImage
*meta
)
834 const char *base
= meta
->tables_base
;
836 for (i
= 0; i
< MONO_TABLE_NUM
; i
++) {
837 MonoTableInfo
*table
= &meta
->tables
[i
];
838 if (table
->rows
== 0)
841 table
->row_size
= mono_metadata_compute_size (meta
, i
, &table
->size_bitfield
);
843 base
+= table
->rows
* table
->row_size
;
848 * mono_metadata_locate:
849 * @meta: metadata context
850 * @table: table code.
851 * @idx: index of element to retrieve from @table.
853 * Returns: a pointer to the @idx element in the metadata table
854 * whose code is @table.
857 mono_metadata_locate (MonoImage
*meta
, int table
, int idx
)
859 /* idx == 0 refers always to NULL */
860 g_return_val_if_fail (idx
> 0 && idx
<= meta
->tables
[table
].rows
, ""); /*FIXME shouldn't we return NULL here?*/
862 return meta
->tables
[table
].base
+ (meta
->tables
[table
].row_size
* (idx
- 1));
866 * mono_metadata_locate_token:
867 * @meta: metadata context
868 * @token: metadata token
870 * Returns: a pointer to the data in the metadata represented by the
874 mono_metadata_locate_token (MonoImage
*meta
, guint32 token
)
876 return mono_metadata_locate (meta
, token
>> 24, token
& 0xffffff);
880 * mono_metadata_string_heap:
881 * @meta: metadata context
882 * @index: index into the string heap.
884 * Returns: an in-memory pointer to the @index in the string heap.
887 mono_metadata_string_heap (MonoImage
*meta
, guint32 index
)
889 g_return_val_if_fail (index
< meta
->heap_strings
.size
, "");
890 return meta
->heap_strings
.data
+ index
;
894 * mono_metadata_user_string:
895 * @meta: metadata context
896 * @index: index into the user string heap.
898 * Returns: an in-memory pointer to the @index in the user string heap ("#US").
901 mono_metadata_user_string (MonoImage
*meta
, guint32 index
)
903 g_return_val_if_fail (index
< meta
->heap_us
.size
, "");
904 return meta
->heap_us
.data
+ index
;
908 * mono_metadata_blob_heap:
909 * @meta: metadata context
910 * @index: index into the blob.
912 * Returns: an in-memory pointer to the @index in the Blob heap.
915 mono_metadata_blob_heap (MonoImage
*meta
, guint32 index
)
917 g_return_val_if_fail (index
< meta
->heap_blob
.size
, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
918 return meta
->heap_blob
.data
+ index
;
922 * mono_metadata_guid_heap:
923 * @meta: metadata context
924 * @index: index into the guid heap.
926 * Returns: an in-memory pointer to the @index in the guid heap.
929 mono_metadata_guid_heap (MonoImage
*meta
, guint32 index
)
932 index
*= 16; /* adjust for guid size and 1-based index */
933 g_return_val_if_fail (index
< meta
->heap_guid
.size
, "");
934 return meta
->heap_guid
.data
+ index
;
937 static const unsigned char *
938 dword_align (const unsigned char *ptr
)
940 #if SIZEOF_VOID_P == 8
941 return (const unsigned char *) (((guint64
) (ptr
+ 3)) & ~3);
943 return (const unsigned char *) (((guint32
) (ptr
+ 3)) & ~3);
948 * mono_metadata_decode_row:
949 * @t: table to extract information from.
950 * @idx: index in table.
951 * @res: array of @res_size cols to store the results in
953 * This decompresses the metadata element @idx in table @t
954 * into the guint32 @res array that has res_size elements
957 mono_metadata_decode_row (const MonoTableInfo
*t
, int idx
, guint32
*res
, int res_size
)
959 guint32 bitfield
= t
->size_bitfield
;
960 int i
, count
= mono_metadata_table_count (bitfield
);
963 g_assert (idx
< t
->rows
);
964 data
= t
->base
+ idx
* t
->row_size
;
966 g_assert (res_size
== count
);
968 for (i
= 0; i
< count
; i
++) {
969 int n
= mono_metadata_table_size (bitfield
, i
);
973 res
[i
] = *data
; break;
975 res
[i
] = read16 (data
); break;
977 res
[i
] = read32 (data
); break;
979 g_assert_not_reached ();
986 * mono_metadata_decode_row_col:
987 * @t: table to extract information from.
988 * @idx: index for row in table.
989 * @col: column in the row.
991 * This function returns the value of column @col from the @idx
992 * row in the table @t.
995 mono_metadata_decode_row_col (const MonoTableInfo
*t
, int idx
, guint col
)
997 guint32 bitfield
= t
->size_bitfield
;
999 register const char *data
;
1002 g_assert (idx
< t
->rows
);
1003 g_assert (col
< mono_metadata_table_count (bitfield
));
1004 data
= t
->base
+ idx
* t
->row_size
;
1006 n
= mono_metadata_table_size (bitfield
, 0);
1007 for (i
= 0; i
< col
; ++i
) {
1009 n
= mono_metadata_table_size (bitfield
, i
+ 1);
1015 return read16 (data
);
1017 return read32 (data
);
1019 g_assert_not_reached ();
1025 * mono_metadata_decode_blob_size:
1026 * @ptr: pointer to a blob object
1027 * @rptr: the new position of the pointer
1029 * This decodes a compressed size as described by 23.1.4 (a blob or user string object)
1031 * Returns: the size of the blob object
1034 mono_metadata_decode_blob_size (const char *xptr
, const char **rptr
)
1036 const unsigned char *ptr
= (const unsigned char *)xptr
;
1039 if ((*ptr
& 0x80) == 0){
1040 size
= ptr
[0] & 0x7f;
1042 } else if ((*ptr
& 0x40) == 0){
1043 size
= ((ptr
[0] & 0x3f) << 8) + ptr
[1];
1046 size
= ((ptr
[0] & 0x1f) << 24) +
1058 * mono_metadata_decode_value:
1059 * @ptr: pointer to decode from
1060 * @rptr: the new position of the pointer
1062 * This routine decompresses 32-bit values as specified in the "Blob and
1063 * Signature" section (22.2)
1065 * Returns: the decoded value
1068 mono_metadata_decode_value (const char *_ptr
, const char **rptr
)
1070 const unsigned char *ptr
= (const unsigned char *) _ptr
;
1071 unsigned char b
= *ptr
;
1074 if ((b
& 0x80) == 0){
1077 } else if ((b
& 0x40) == 0){
1078 len
= ((b
& 0x3f) << 8 | ptr
[1]);
1081 len
= ((b
& 0x1f) << 24) |
1094 * mono_metadata_decode_signed_value:
1095 * @ptr: pointer to decode from
1096 * @rptr: the new position of the pointer
1098 * This routine decompresses 32-bit signed values
1099 * (not specified in the spec)
1101 * Returns: the decoded value
1104 mono_metadata_decode_signed_value (const char *ptr
, const char **rptr
)
1106 guint32 uval
= mono_metadata_decode_value (ptr
, rptr
);
1107 gint32 ival
= uval
>> 1;
1110 /* ival is a truncated 2's complement negative number. */
1112 /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1115 /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1116 return ival
- 0x2000;
1117 if (ival
< 0x10000000)
1118 /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1119 return ival
- 0x10000000;
1120 g_assert (ival
< 0x20000000);
1121 g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival
, uval
);
1122 return ival
- 0x20000000;
1126 * Translates the given 1-based index into the Method, Field, Event, or Param tables
1127 * using the *Ptr tables in uncompressed metadata, if they are available.
1129 * FIXME: The caller is not forced to call this function, which is error-prone, since
1130 * forgetting to call it would only show up as a bug on uncompressed metadata.
1133 mono_metadata_translate_token_index (MonoImage
*image
, int table
, guint32 idx
)
1135 if (!image
->uncompressed_metadata
)
1139 case MONO_TABLE_METHOD
:
1140 if (image
->tables
[MONO_TABLE_METHOD_POINTER
].rows
)
1141 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_METHOD_POINTER
], idx
- 1, MONO_METHOD_POINTER_METHOD
);
1144 case MONO_TABLE_FIELD
:
1145 if (image
->tables
[MONO_TABLE_FIELD_POINTER
].rows
)
1146 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_FIELD_POINTER
], idx
- 1, MONO_FIELD_POINTER_FIELD
);
1149 case MONO_TABLE_EVENT
:
1150 if (image
->tables
[MONO_TABLE_EVENT_POINTER
].rows
)
1151 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_EVENT_POINTER
], idx
- 1, MONO_EVENT_POINTER_EVENT
);
1154 case MONO_TABLE_PROPERTY
:
1155 if (image
->tables
[MONO_TABLE_PROPERTY_POINTER
].rows
)
1156 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PROPERTY_POINTER
], idx
- 1, MONO_PROPERTY_POINTER_PROPERTY
);
1159 case MONO_TABLE_PARAM
:
1160 if (image
->tables
[MONO_TABLE_PARAM_POINTER
].rows
)
1161 return mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_PARAM_POINTER
], idx
- 1, MONO_PARAM_POINTER_PARAM
);
1170 * mono_metadata_decode_table_row:
1172 * Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
1173 * uncompressed metadata into account, so it should be used to access the
1174 * Method, Field, Param and Event tables when the access is made from metadata, i.e.
1175 * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
1178 mono_metadata_decode_table_row (MonoImage
*image
, int table
, int idx
, guint32
*res
, int res_size
)
1180 if (image
->uncompressed_metadata
)
1181 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1183 mono_metadata_decode_row (&image
->tables
[table
], idx
, res
, res_size
);
1187 * mono_metadata_decode_table_row_col:
1189 * Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
1190 * uncompressed metadata into account, so it should be used to access the
1191 * Method, Field, Param and Event tables.
1193 guint32
mono_metadata_decode_table_row_col (MonoImage
*image
, int table
, int idx
, guint col
)
1195 if (image
->uncompressed_metadata
)
1196 idx
= mono_metadata_translate_token_index (image
, table
, idx
+ 1) - 1;
1198 return mono_metadata_decode_row_col (&image
->tables
[table
], idx
, col
);
1202 * mono_metadata_parse_typedef_or_ref:
1203 * @m: a metadata context.
1204 * @ptr: a pointer to an encoded TypedefOrRef in @m
1205 * @rptr: pointer updated to match the end of the decoded stream
1207 * Returns: a token valid in the @m metadata decoded from
1208 * the compressed representation.
1211 mono_metadata_parse_typedef_or_ref (MonoImage
*m
, const char *ptr
, const char **rptr
)
1214 token
= mono_metadata_decode_value (ptr
, &ptr
);
1217 return mono_metadata_token_from_dor (token
);
1221 * mono_metadata_parse_custom_mod:
1222 * @m: a metadata context.
1223 * @dest: storage where the info about the custom modifier is stored (may be NULL)
1224 * @ptr: a pointer to (possibly) the start of a custom modifier list
1225 * @rptr: pointer updated to match the end of the decoded stream
1227 * Checks if @ptr points to a type custom modifier compressed representation.
1229 * Returns: #TRUE if a custom modifier was found, #FALSE if not.
1232 mono_metadata_parse_custom_mod (MonoImage
*m
, MonoCustomMod
*dest
, const char *ptr
, const char **rptr
)
1234 MonoCustomMod local
;
1235 if ((*ptr
== MONO_TYPE_CMOD_OPT
) || (*ptr
== MONO_TYPE_CMOD_REQD
)) {
1238 dest
->required
= *ptr
== MONO_TYPE_CMOD_REQD
? 1 : 0;
1239 dest
->token
= mono_metadata_parse_typedef_or_ref (m
, ptr
+ 1, rptr
);
1246 * mono_metadata_parse_array_full:
1247 * @m: a metadata context.
1248 * @ptr: a pointer to an encoded array description.
1249 * @rptr: pointer updated to match the end of the decoded stream
1251 * Decodes the compressed array description found in the metadata @m at @ptr.
1253 * Returns: a #MonoArrayType structure describing the array type
1254 * and dimensions. Memory is allocated from the image mempool.
1256 * LOCKING: Acquires the loader lock
1259 mono_metadata_parse_array_full (MonoImage
*m
, MonoGenericContainer
*container
,
1260 const char *ptr
, const char **rptr
)
1263 MonoArrayType
*array
;
1266 array
= mono_image_alloc0 (m
, sizeof (MonoArrayType
));
1267 etype
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
1270 array
->eklass
= mono_class_from_mono_type (etype
);
1271 array
->rank
= mono_metadata_decode_value (ptr
, &ptr
);
1273 array
->numsizes
= mono_metadata_decode_value (ptr
, &ptr
);
1274 if (array
->numsizes
)
1275 array
->sizes
= mono_image_alloc0 (m
, sizeof (int) * array
->numsizes
);
1276 for (i
= 0; i
< array
->numsizes
; ++i
)
1277 array
->sizes
[i
] = mono_metadata_decode_value (ptr
, &ptr
);
1279 array
->numlobounds
= mono_metadata_decode_value (ptr
, &ptr
);
1280 if (array
->numlobounds
)
1281 array
->lobounds
= mono_image_alloc0 (m
, sizeof (int) * array
->numlobounds
);
1282 for (i
= 0; i
< array
->numlobounds
; ++i
)
1283 array
->lobounds
[i
] = mono_metadata_decode_signed_value (ptr
, &ptr
);
1291 mono_metadata_parse_array (MonoImage
*m
, const char *ptr
, const char **rptr
)
1293 return mono_metadata_parse_array_full (m
, NULL
, ptr
, rptr
);
1297 * mono_metadata_free_array:
1298 * @array: array description
1300 * Frees the array description returned from mono_metadata_parse_array().
1303 mono_metadata_free_array (MonoArrayType
*array
)
1305 g_free (array
->sizes
);
1306 g_free (array
->lobounds
);
1311 * need to add common field and param attributes combinations:
1314 * public static literal
1317 * private static literal
1319 static const MonoType
1321 /* data, attrs, type, nmods, byref, pinned */
1322 {{NULL
}, 0, MONO_TYPE_VOID
, 0, 0, 0},
1323 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 0, 0},
1324 {{NULL
}, 0, MONO_TYPE_BOOLEAN
, 0, 1, 0},
1325 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 0, 0},
1326 {{NULL
}, 0, MONO_TYPE_CHAR
, 0, 1, 0},
1327 {{NULL
}, 0, MONO_TYPE_I1
, 0, 0, 0},
1328 {{NULL
}, 0, MONO_TYPE_I1
, 0, 1, 0},
1329 {{NULL
}, 0, MONO_TYPE_U1
, 0, 0, 0},
1330 {{NULL
}, 0, MONO_TYPE_U1
, 0, 1, 0},
1331 {{NULL
}, 0, MONO_TYPE_I2
, 0, 0, 0},
1332 {{NULL
}, 0, MONO_TYPE_I2
, 0, 1, 0},
1333 {{NULL
}, 0, MONO_TYPE_U2
, 0, 0, 0},
1334 {{NULL
}, 0, MONO_TYPE_U2
, 0, 1, 0},
1335 {{NULL
}, 0, MONO_TYPE_I4
, 0, 0, 0},
1336 {{NULL
}, 0, MONO_TYPE_I4
, 0, 1, 0},
1337 {{NULL
}, 0, MONO_TYPE_U4
, 0, 0, 0},
1338 {{NULL
}, 0, MONO_TYPE_U4
, 0, 1, 0},
1339 {{NULL
}, 0, MONO_TYPE_I8
, 0, 0, 0},
1340 {{NULL
}, 0, MONO_TYPE_I8
, 0, 1, 0},
1341 {{NULL
}, 0, MONO_TYPE_U8
, 0, 0, 0},
1342 {{NULL
}, 0, MONO_TYPE_U8
, 0, 1, 0},
1343 {{NULL
}, 0, MONO_TYPE_R4
, 0, 0, 0},
1344 {{NULL
}, 0, MONO_TYPE_R4
, 0, 1, 0},
1345 {{NULL
}, 0, MONO_TYPE_R8
, 0, 0, 0},
1346 {{NULL
}, 0, MONO_TYPE_R8
, 0, 1, 0},
1347 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 0, 0},
1348 {{NULL
}, 0, MONO_TYPE_STRING
, 0, 1, 0},
1349 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 0, 0},
1350 {{NULL
}, 0, MONO_TYPE_OBJECT
, 0, 1, 0},
1351 {{NULL
}, 0, MONO_TYPE_TYPEDBYREF
, 0, 0, 0},
1352 {{NULL
}, 0, MONO_TYPE_I
, 0, 0, 0},
1353 {{NULL
}, 0, MONO_TYPE_I
, 0, 1, 0},
1354 {{NULL
}, 0, MONO_TYPE_U
, 0, 0, 0},
1355 {{NULL
}, 0, MONO_TYPE_U
, 0, 1, 0},
1358 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1360 static GHashTable
*type_cache
= NULL
;
1361 static GHashTable
*generic_inst_cache
= NULL
;
1362 static GHashTable
*generic_class_cache
= NULL
;
1363 static int next_generic_inst_id
= 0;
1366 * Protected by the loader lock.
1367 * It has a MonoMethodInflated* as key and value.
1368 * The key lookup will just access the declaring and context fields
1370 static GHashTable
*generic_method_cache
= NULL
;
1373 * Protected by the loader lock.
1374 * It has a MonoInflatedMethodSignature* as key and value.
1376 static GHashTable
*generic_signature_cache
= NULL
;
1378 static guint
mono_generic_class_hash (gconstpointer data
);
1381 * MonoTypes with modifies are never cached, so we never check or use that field.
1384 mono_type_hash (gconstpointer data
)
1386 const MonoType
*type
= (const MonoType
*) data
;
1387 if (type
->type
== MONO_TYPE_GENERICINST
)
1388 return mono_generic_class_hash (type
->data
.generic_class
);
1390 return type
->type
| (type
->byref
<< 8) | (type
->attrs
<< 9);
1394 mono_type_equal (gconstpointer ka
, gconstpointer kb
)
1396 const MonoType
*a
= (const MonoType
*) ka
;
1397 const MonoType
*b
= (const MonoType
*) kb
;
1399 if (a
->type
!= b
->type
|| a
->byref
!= b
->byref
|| a
->attrs
!= b
->attrs
|| a
->pinned
!= b
->pinned
)
1401 /* need other checks */
1406 mono_metadata_generic_inst_hash (gconstpointer data
)
1408 const MonoGenericInst
*ginst
= (const MonoGenericInst
*) data
;
1412 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
1414 hash
+= mono_metadata_type_hash (ginst
->type_argv
[i
]);
1417 return hash
^ (ginst
->is_open
<< 8);
1421 mono_generic_inst_equal_full (const MonoGenericInst
*a
, const MonoGenericInst
*b
, gboolean signature_only
)
1425 if (a
->id
&& b
->id
) {
1428 if (!signature_only
)
1432 if (a
->is_open
!= b
->is_open
|| a
->type_argc
!= b
->type_argc
)
1434 for (i
= 0; i
< a
->type_argc
; ++i
) {
1435 if (!do_mono_metadata_type_equal (a
->type_argv
[i
], b
->type_argv
[i
], signature_only
))
1442 mono_metadata_generic_inst_equal (gconstpointer ka
, gconstpointer kb
)
1444 const MonoGenericInst
*a
= (const MonoGenericInst
*) ka
;
1445 const MonoGenericInst
*b
= (const MonoGenericInst
*) kb
;
1447 return mono_generic_inst_equal_full (a
, b
, FALSE
);
1451 mono_generic_class_hash (gconstpointer data
)
1453 const MonoGenericClass
*gclass
= (const MonoGenericClass
*) data
;
1454 guint hash
= mono_metadata_type_hash (&gclass
->container_class
->byval_arg
);
1457 hash
+= gclass
->is_tb_open
;
1458 hash
+= mono_metadata_generic_context_hash (&gclass
->context
);
1464 mono_generic_class_equal (gconstpointer ka
, gconstpointer kb
)
1466 const MonoGenericClass
*a
= (const MonoGenericClass
*) ka
;
1467 const MonoGenericClass
*b
= (const MonoGenericClass
*) kb
;
1469 return _mono_metadata_generic_class_equal (a
, b
, FALSE
);
1473 * mono_metadata_init:
1475 * Initialize the global variables of this module.
1476 * This is a Mono runtime internal function.
1479 mono_metadata_init (void)
1483 type_cache
= g_hash_table_new (mono_type_hash
, mono_type_equal
);
1484 generic_inst_cache
= g_hash_table_new_full (mono_metadata_generic_inst_hash
, mono_metadata_generic_inst_equal
, NULL
, (GDestroyNotify
)free_generic_inst
);
1485 generic_class_cache
= g_hash_table_new_full (mono_generic_class_hash
, mono_generic_class_equal
, NULL
, (GDestroyNotify
)free_generic_class
);
1487 for (i
= 0; i
< NBUILTIN_TYPES (); ++i
)
1488 g_hash_table_insert (type_cache
, (gpointer
) &builtin_types
[i
], (gpointer
) &builtin_types
[i
]);
1492 * mono_metadata_cleanup:
1494 * Free all resources used by this module.
1495 * This is a Mono runtime internal function.
1498 mono_metadata_cleanup (void)
1500 /* Has to free this first, as it could reference data in the other caches */
1501 if (generic_method_cache
)
1502 g_hash_table_destroy (generic_method_cache
);
1503 g_hash_table_destroy (type_cache
);
1504 g_hash_table_destroy (generic_inst_cache
);
1505 g_hash_table_destroy (generic_class_cache
);
1506 if (generic_signature_cache
)
1507 g_hash_table_destroy (generic_signature_cache
);
1509 generic_inst_cache
= NULL
;
1510 generic_class_cache
= NULL
;
1511 generic_method_cache
= NULL
;
1512 generic_signature_cache
= NULL
;
1516 * mono_metadata_parse_type:
1517 * @m: metadata context
1518 * @mode: king of type that may be found at @ptr
1519 * @opt_attrs: optional attributes to store in the returned type
1520 * @ptr: pointer to the type representation
1521 * @rptr: pointer updated to match the end of the decoded stream
1523 * Decode a compressed type description found at @ptr in @m.
1524 * @mode can be one of MONO_PARSE_MOD_TYPE, MONO_PARSE_PARAM, MONO_PARSE_RET,
1525 * MONO_PARSE_FIELD, MONO_PARSE_LOCAL, MONO_PARSE_TYPE.
1526 * This function can be used to decode type descriptions in method signatures,
1527 * field signatures, locals signatures etc.
1529 * To parse a generic type, `generic_container' points to the current class'es
1530 * (the `generic_container' field in the MonoClass) or the current generic method's
1531 * (the `generic_container' field in the MonoMethodNormal) generic container.
1532 * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
1533 * this MonoGenericContainer.
1534 * This is a Mono runtime internal function.
1536 * LOCKING: Acquires the loader lock.
1538 * Returns: a #MonoType structure representing the decoded type.
1541 mono_metadata_parse_type_full (MonoImage
*m
, MonoGenericContainer
*container
, MonoParseTypeMode mode
,
1542 short opt_attrs
, const char *ptr
, const char **rptr
)
1544 MonoType
*type
, *cached
;
1546 gboolean byref
= FALSE
;
1547 gboolean pinned
= FALSE
;
1548 const char *tmp_ptr
;
1553 * According to the spec, custom modifiers should come before the byref
1554 * flag, but the IL produced by ilasm from the following signature:
1555 * object modopt(...) &
1556 * starts with a byref flag, followed by the modifiers. (bug #49802)
1557 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1558 * it would be better to treat byref as real type constructor instead of
1560 * Also, pinned should come before anything else, but some MSV++ produced
1561 * assemblies violate this (#bug 61990).
1564 /* Count the modifiers first */
1569 case MONO_TYPE_PINNED
:
1570 case MONO_TYPE_BYREF
:
1573 case MONO_TYPE_CMOD_REQD
:
1574 case MONO_TYPE_CMOD_OPT
:
1576 mono_metadata_parse_custom_mod (m
, NULL
, tmp_ptr
, &tmp_ptr
);
1584 type
= mono_image_alloc0 (m
, MONO_SIZEOF_TYPE
+ ((gint32
)count
) * sizeof (MonoCustomMod
));
1585 type
->num_mods
= count
;
1587 g_warning ("got more than 64 modifiers in type");
1590 memset (type
, 0, MONO_SIZEOF_TYPE
);
1593 /* Parse pinned, byref and custom modifiers */
1598 case MONO_TYPE_PINNED
:
1602 case MONO_TYPE_BYREF
:
1606 case MONO_TYPE_CMOD_REQD
:
1607 case MONO_TYPE_CMOD_OPT
:
1608 mono_metadata_parse_custom_mod (m
, &(type
->modifiers
[count
]), ptr
, &ptr
);
1616 type
->attrs
= opt_attrs
;
1617 type
->byref
= byref
;
1618 type
->pinned
= pinned
? 1 : 0;
1620 if (!do_mono_metadata_parse_type (type
, m
, container
, ptr
, &ptr
)) {
1627 if (!type
->num_mods
) {
1628 /* no need to free type here, because it is on the stack */
1629 if ((type
->type
== MONO_TYPE_CLASS
|| type
->type
== MONO_TYPE_VALUETYPE
) && !type
->pinned
&& !type
->attrs
) {
1630 MonoType
*ret
= type
->byref
? &type
->data
.klass
->this_arg
: &type
->data
.klass
->byval_arg
;
1632 /* Consider the case:
1634 class Foo<T> { class Bar {} }
1635 class Test : Foo<Test>.Bar {}
1637 When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
1638 a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1640 We ensure that the MonoClass is in a state that we can canonicalize to:
1642 klass->byval_arg.data.klass == klass
1643 klass->this_arg.data.klass == klass
1645 If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1647 LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1648 of a MonoClass which currently holds the loader lock. 'type' is local.
1650 if (ret
->data
.klass
== type
->data
.klass
) {
1654 /* No need to use locking since nobody is modifying the hash table */
1655 if ((cached
= g_hash_table_lookup (type_cache
, type
))) {
1660 /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1662 if (type
== &stype
) {
1663 type
= mono_image_alloc (m
, MONO_SIZEOF_TYPE
);
1664 memcpy (type
, &stype
, MONO_SIZEOF_TYPE
);
1670 * LOCKING: Acquires the loader lock.
1673 mono_metadata_parse_type (MonoImage
*m
, MonoParseTypeMode mode
, short opt_attrs
,
1674 const char *ptr
, const char **rptr
)
1676 return mono_metadata_parse_type_full (m
, NULL
, mode
, opt_attrs
, ptr
, rptr
);
1680 mono_metadata_method_has_param_attrs (MonoImage
*m
, int def
)
1682 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1683 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1684 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1686 if (def
< methodt
->rows
)
1687 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1689 lastp
= m
->tables
[MONO_TABLE_PARAM
].rows
+ 1;
1691 for (i
= param_index
; i
< lastp
; ++i
) {
1692 guint32 flags
= mono_metadata_decode_row_col (paramt
, i
- 1, MONO_PARAM_FLAGS
);
1701 * mono_metadata_get_param_attrs:
1703 * @m The image to loader parameter attributes from
1704 * @def method def token (one based)
1705 * @param_count number of params to decode including the return value
1707 * Return the parameter attributes for the method whose MethodDef index is DEF. The
1708 * returned memory needs to be freed by the caller. If all the param attributes are
1709 * 0, then NULL is returned.
1712 mono_metadata_get_param_attrs (MonoImage
*m
, int def
, int param_count
)
1714 MonoTableInfo
*paramt
= &m
->tables
[MONO_TABLE_PARAM
];
1715 MonoTableInfo
*methodt
= &m
->tables
[MONO_TABLE_METHOD
];
1716 guint32 cols
[MONO_PARAM_SIZE
];
1717 guint lastp
, i
, param_index
= mono_metadata_decode_row_col (methodt
, def
- 1, MONO_METHOD_PARAMLIST
);
1720 if (def
< methodt
->rows
)
1721 lastp
= mono_metadata_decode_row_col (methodt
, def
, MONO_METHOD_PARAMLIST
);
1723 lastp
= paramt
->rows
+ 1;
1725 for (i
= param_index
; i
< lastp
; ++i
) {
1726 mono_metadata_decode_row (paramt
, i
- 1, cols
, MONO_PARAM_SIZE
);
1727 if (cols
[MONO_PARAM_FLAGS
]) {
1729 pattrs
= g_new0 (int, param_count
);
1730 /* at runtime we just ignore this kind of malformed file:
1731 * the verifier can signal the error to the user
1733 if (cols
[MONO_PARAM_SEQUENCE
] >= param_count
)
1735 pattrs
[cols
[MONO_PARAM_SEQUENCE
]] = cols
[MONO_PARAM_FLAGS
];
1743 * mono_metadata_parse_signature_full:
1744 * @image: metadata context
1745 * @generic_container: generic container
1746 * @toke: metadata token
1748 * Decode a method signature stored in the STANDALONESIG table
1750 * LOCKING: Assumes the loader lock is held.
1752 * Returns: a MonoMethodSignature describing the signature.
1754 MonoMethodSignature
*
1755 mono_metadata_parse_signature_full (MonoImage
*image
, MonoGenericContainer
*generic_container
, guint32 token
)
1757 MonoTableInfo
*tables
= image
->tables
;
1758 guint32 idx
= mono_metadata_token_index (token
);
1763 return mono_lookup_dynamic_token (image
, token
, NULL
);
1765 g_assert (mono_metadata_token_table(token
) == MONO_TABLE_STANDALONESIG
);
1767 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
1769 ptr
= mono_metadata_blob_heap (image
, sig
);
1770 mono_metadata_decode_blob_size (ptr
, &ptr
);
1772 return mono_metadata_parse_method_signature_full (image
, generic_container
, 0, ptr
, NULL
);
1776 * mono_metadata_parse_signature:
1777 * @image: metadata context
1778 * @toke: metadata token
1780 * Decode a method signature stored in the STANDALONESIG table
1782 * Returns: a MonoMethodSignature describing the signature.
1784 MonoMethodSignature
*
1785 mono_metadata_parse_signature (MonoImage
*image
, guint32 token
)
1787 return mono_metadata_parse_signature_full (image
, NULL
, token
);
1791 * mono_metadata_signature_alloc:
1792 * @image: metadata context
1793 * @nparmas: number of parameters in the signature
1795 * Allocate a MonoMethodSignature structure with the specified number of params.
1796 * The return type and the params types need to be filled later.
1797 * This is a Mono runtime internal function.
1799 * LOCKING: Assumes the loader lock is held.
1801 * Returns: the new MonoMethodSignature structure.
1803 MonoMethodSignature
*
1804 mono_metadata_signature_alloc (MonoImage
*m
, guint32 nparams
)
1806 MonoMethodSignature
*sig
;
1808 sig
= mono_image_alloc0 (m
, MONO_SIZEOF_METHOD_SIGNATURE
+ ((gint32
)nparams
) * sizeof (MonoType
*));
1809 sig
->param_count
= nparams
;
1810 sig
->sentinelpos
= -1;
1815 static MonoMethodSignature
*
1816 mono_metadata_signature_dup_internal (MonoImage
*image
, MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1819 MonoMethodSignature
*ret
;
1820 sigsize
= MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*);
1823 ret
= mono_image_alloc (image
, sigsize
);
1825 ret
= mono_mempool_alloc (mp
, sigsize
);
1827 ret
= g_malloc (sigsize
);
1829 memcpy (ret
, sig
, sigsize
);
1833 MonoMethodSignature
*
1834 mono_metadata_signature_dup_full (MonoImage
*image
, MonoMethodSignature
*sig
)
1836 return mono_metadata_signature_dup_internal (image
, NULL
, sig
);
1839 /*The mempool is accessed without synchronization*/
1840 MonoMethodSignature
*
1841 mono_metadata_signature_dup_mempool (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1843 return mono_metadata_signature_dup_internal (NULL
, mp
, sig
);
1847 * mono_metadata_signature_dup:
1848 * @sig: method signature
1850 * Duplicate an existing MonoMethodSignature so it can be modified.
1851 * This is a Mono runtime internal function.
1853 * Returns: the new MonoMethodSignature structure.
1855 MonoMethodSignature
*
1856 mono_metadata_signature_dup (MonoMethodSignature
*sig
)
1858 return mono_metadata_signature_dup_full (NULL
, sig
);
1862 * mono_metadata_signature_size:
1864 * Return the amount of memory allocated to SIG.
1867 mono_metadata_signature_size (MonoMethodSignature
*sig
)
1869 return MONO_SIZEOF_METHOD_SIGNATURE
+ sig
->param_count
* sizeof (MonoType
*);
1873 * mono_metadata_parse_method_signature:
1874 * @m: metadata context
1875 * @generic_container: generics container
1876 * @def: the MethodDef index or 0 for Ref signatures.
1877 * @ptr: pointer to the signature metadata representation
1878 * @rptr: pointer updated to match the end of the decoded stream
1880 * Decode a method signature stored at @ptr.
1881 * This is a Mono runtime internal function.
1883 * LOCKING: Assumes the loader lock is held.
1885 * Returns: a MonoMethodSignature describing the signature.
1887 MonoMethodSignature
*
1888 mono_metadata_parse_method_signature_full (MonoImage
*m
, MonoGenericContainer
*container
,
1889 int def
, const char *ptr
, const char **rptr
)
1891 MonoMethodSignature
*method
;
1892 int i
, *pattrs
= NULL
;
1893 guint32 hasthis
= 0, explicit_this
= 0, call_convention
, param_count
;
1894 guint32 gen_param_count
= 0;
1895 gboolean is_open
= FALSE
;
1898 gen_param_count
= 1;
1903 call_convention
= *ptr
& 0x0F;
1905 if (gen_param_count
)
1906 gen_param_count
= mono_metadata_decode_value (ptr
, &ptr
);
1907 param_count
= mono_metadata_decode_value (ptr
, &ptr
);
1910 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 */
1912 method
= mono_metadata_signature_alloc (m
, param_count
);
1913 method
->hasthis
= hasthis
;
1914 method
->explicit_this
= explicit_this
;
1915 method
->call_convention
= call_convention
;
1916 method
->generic_param_count
= gen_param_count
;
1918 if (call_convention
!= 0xa) {
1919 method
->ret
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_RET
, pattrs
? pattrs
[0] : 0, ptr
, &ptr
);
1921 mono_metadata_free_method_signature (method
);
1925 is_open
= mono_class_is_open_constructed_type (method
->ret
);
1928 for (i
= 0; i
< method
->param_count
; ++i
) {
1929 if (*ptr
== MONO_TYPE_SENTINEL
) {
1930 if (method
->call_convention
!= MONO_CALL_VARARG
|| def
) {
1931 g_warning ("found sentinel for methoddef or no vararg method 0x%08x on image %s", def
, m
->name
);
1935 if (method
->sentinelpos
>= 0) {
1936 g_warning ("found sentinel twice in the same signature for method 0x%08x on image %s", def
, m
->name
);
1940 method
->sentinelpos
= i
;
1943 method
->params
[i
] = mono_metadata_parse_type_full (m
, container
, MONO_PARSE_PARAM
, pattrs
? pattrs
[i
+1] : 0, ptr
, &ptr
);
1944 if (!method
->params
[i
]) {
1945 mono_metadata_free_method_signature (method
);
1950 is_open
= mono_class_is_open_constructed_type (method
->params
[i
]);
1953 /* The sentinel could be missing if the caller does not pass any additional arguments */
1954 if (!def
&& method
->call_convention
== MONO_CALL_VARARG
&& method
->sentinelpos
< 0)
1955 method
->sentinelpos
= method
->param_count
;
1957 method
->has_type_parameters
= is_open
;
1959 if (def
&& (method
->call_convention
== MONO_CALL_VARARG
))
1960 method
->sentinelpos
= method
->param_count
;
1967 * Add signature to a cache and increase ref count...
1974 * mono_metadata_parse_method_signature:
1975 * @m: metadata context
1976 * @def: the MethodDef index or 0 for Ref signatures.
1977 * @ptr: pointer to the signature metadata representation
1978 * @rptr: pointer updated to match the end of the decoded stream
1980 * Decode a method signature stored at @ptr.
1981 * This is a Mono runtime internal function.
1983 * LOCKING: Assumes the loader lock is held.
1985 * Returns: a MonoMethodSignature describing the signature.
1987 MonoMethodSignature
*
1988 mono_metadata_parse_method_signature (MonoImage
*m
, int def
, const char *ptr
, const char **rptr
)
1990 return mono_metadata_parse_method_signature_full (m
, NULL
, def
, ptr
, rptr
);
1994 * mono_metadata_free_method_signature:
1995 * @sig: signature to destroy
1997 * Free the memory allocated in the signature @sig.
1998 * This method needs to be robust and work also on partially-built
1999 * signatures, so it does extra checks.
2002 mono_metadata_free_method_signature (MonoMethodSignature
*sig
)
2004 /* Everything is allocated from mempools */
2008 mono_metadata_free_type (sig->ret);
2009 for (i = 0; i < sig->param_count; ++i) {
2010 if (sig->params [i])
2011 mono_metadata_free_type (sig->params [i]);
2017 mono_metadata_free_inflated_signature (MonoMethodSignature
*sig
)
2021 /* Allocated in inflate_generic_signature () */
2023 mono_metadata_free_type (sig
->ret
);
2024 for (i
= 0; i
< sig
->param_count
; ++i
) {
2025 if (sig
->params
[i
])
2026 mono_metadata_free_type (sig
->params
[i
]);
2032 inflated_method_equal (gconstpointer a
, gconstpointer b
)
2034 const MonoMethodInflated
*ma
= a
;
2035 const MonoMethodInflated
*mb
= b
;
2036 if (ma
->declaring
!= mb
->declaring
)
2038 if (ma
->method
.method
.is_mb_open
!= mb
->method
.method
.is_mb_open
)
2040 return mono_metadata_generic_context_equal (&ma
->context
, &mb
->context
);
2044 inflated_method_hash (gconstpointer a
)
2046 const MonoMethodInflated
*ma
= a
;
2047 return (mono_metadata_generic_context_hash (&ma
->context
) ^ mono_aligned_addr_hash (ma
->declaring
)) + ma
->method
.method
.is_mb_open
;
2051 inflated_signature_equal (gconstpointer a
, gconstpointer b
)
2053 const MonoInflatedMethodSignature
*sig1
= a
;
2054 const MonoInflatedMethodSignature
*sig2
= b
;
2056 /* sig->sig is assumed to be canonized */
2057 if (sig1
->sig
!= sig2
->sig
)
2059 /* The generic instances are canonized */
2060 return mono_metadata_generic_context_equal (&sig1
->context
, &sig2
->context
);
2064 inflated_signature_hash (gconstpointer a
)
2066 const MonoInflatedMethodSignature
*sig
= a
;
2068 /* sig->sig is assumed to be canonized */
2069 return mono_metadata_generic_context_hash (&sig
->context
) ^ mono_aligned_addr_hash (sig
->sig
);
2073 dump_ginst (MonoGenericInst *ginst)
2078 g_print ("Ginst: <");
2079 for (i = 0; i < ginst->type_argc; ++i) {
2082 name = mono_type_get_name (ginst->type_argv [i]);
2083 g_print ("%s", name);
2089 static gboolean
type_in_image (MonoType
*type
, MonoImage
*image
);
2092 signature_in_image (MonoMethodSignature
*sig
, MonoImage
*image
)
2094 gpointer iter
= NULL
;
2097 while ((p
= mono_signature_get_params (sig
, &iter
)) != NULL
)
2098 if (type_in_image (p
, image
))
2101 return type_in_image (mono_signature_get_return_type (sig
), image
);
2105 ginst_in_image (MonoGenericInst
*ginst
, MonoImage
*image
)
2109 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
2110 if (type_in_image (ginst
->type_argv
[i
], image
))
2118 gclass_in_image (MonoGenericClass
*gclass
, MonoImage
*image
)
2120 return gclass
->container_class
->image
== image
||
2121 ginst_in_image (gclass
->context
.class_inst
, image
);
2125 type_in_image (MonoType
*type
, MonoImage
*image
)
2128 switch (type
->type
) {
2129 case MONO_TYPE_GENERICINST
:
2130 return gclass_in_image (type
->data
.generic_class
, image
);
2132 type
= type
->data
.type
;
2134 case MONO_TYPE_SZARRAY
:
2135 type
= &type
->data
.klass
->byval_arg
;
2137 case MONO_TYPE_ARRAY
:
2138 type
= &type
->data
.array
->eklass
->byval_arg
;
2140 case MONO_TYPE_FNPTR
:
2141 return signature_in_image (type
->data
.method
, image
);
2142 case MONO_TYPE_VAR
: {
2143 MonoGenericContainer
*container
= mono_type_get_generic_param_owner (type
);
2145 g_assert (!container
->is_method
);
2147 * FIXME: The following check is here solely
2148 * for monodis, which uses the internal
2150 * mono_metadata_load_generic_params(). The
2151 * caller of that function needs to fill in
2152 * owner->klass or owner->method of the
2153 * returned struct, but monodis doesn't do
2154 * that. The image unloading depends on that,
2155 * however, so a crash results without this
2158 if (!container
->owner
.klass
)
2159 return container
->image
== image
;
2160 return container
->owner
.klass
->image
== image
;
2162 return type
->data
.generic_param
->image
== image
;
2165 case MONO_TYPE_MVAR
: {
2166 MonoGenericContainer
*container
= mono_type_get_generic_param_owner (type
);
2167 if (type
->data
.generic_param
->image
== image
)
2170 g_assert (container
->is_method
);
2171 if (!container
->owner
.method
)
2172 /* RefEmit created generic param whose method is not finished */
2173 return container
->image
== image
;
2174 return container
->owner
.method
->klass
->image
== image
;
2176 return type
->data
.generic_param
->image
== image
;
2180 /* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2181 return image
== mono_class_from_mono_type (type
)->image
;
2188 } CleanForImageUserData
;
2191 steal_gclass_in_image (gpointer key
, gpointer value
, gpointer data
)
2193 MonoGenericClass
*gclass
= key
;
2194 CleanForImageUserData
*user_data
= data
;
2196 if (!gclass_in_image (gclass
, user_data
->image
))
2199 user_data
->list
= g_slist_prepend (user_data
->list
, gclass
);
2204 steal_ginst_in_image (gpointer key
, gpointer value
, gpointer data
)
2206 MonoGenericInst
*ginst
= key
;
2207 CleanForImageUserData
*user_data
= data
;
2209 if (!ginst_in_image (ginst
, user_data
->image
))
2212 user_data
->list
= g_slist_prepend (user_data
->list
, ginst
);
2217 inflated_method_in_image (gpointer key
, gpointer value
, gpointer data
)
2219 MonoImage
*image
= data
;
2220 MonoMethodInflated
*method
= key
;
2223 // https://bugzilla.novell.com/show_bug.cgi?id=458168
2224 return method
->declaring
->klass
->image
== image
||
2225 (method
->context
.class_inst
&& ginst_in_image (method
->context
.class_inst
, image
)) ||
2226 (method
->context
.method_inst
&& ginst_in_image (method
->context
.method_inst
, image
)) || (((MonoMethod
*)method
)->signature
&& signature_in_image (mono_method_signature ((MonoMethod
*)method
), image
));
2230 inflated_signature_in_image (gpointer key
, gpointer value
, gpointer data
)
2232 MonoImage
*image
= data
;
2233 MonoInflatedMethodSignature
*sig
= key
;
2235 return signature_in_image (sig
->sig
, image
) ||
2236 (sig
->context
.class_inst
&& ginst_in_image (sig
->context
.class_inst
, image
)) ||
2237 (sig
->context
.method_inst
&& ginst_in_image (sig
->context
.method_inst
, image
));
2241 mono_metadata_clean_for_image (MonoImage
*image
)
2243 CleanForImageUserData ginst_data
, gclass_data
;
2246 /* The data structures could reference each other so we delete them in two phases */
2247 ginst_data
.image
= gclass_data
.image
= image
;
2248 ginst_data
.list
= gclass_data
.list
= NULL
;
2250 mono_loader_lock ();
2251 /* Collect the items to delete and remove them from the hash table */
2252 g_hash_table_foreach_steal (generic_inst_cache
, steal_ginst_in_image
, &ginst_data
);
2253 g_hash_table_foreach_steal (generic_class_cache
, steal_gclass_in_image
, &gclass_data
);
2254 if (generic_method_cache
)
2255 g_hash_table_foreach_remove (generic_method_cache
, inflated_method_in_image
, image
);
2256 if (generic_signature_cache
)
2257 g_hash_table_foreach_remove (generic_signature_cache
, inflated_signature_in_image
, image
);
2258 /* Delete the removed items */
2259 for (l
= ginst_data
.list
; l
; l
= l
->next
)
2260 free_generic_inst (l
->data
);
2261 for (l
= gclass_data
.list
; l
; l
= l
->next
)
2262 free_generic_class (l
->data
);
2263 g_slist_free (ginst_data
.list
);
2264 g_slist_free (gclass_data
.list
);
2265 mono_class_unregister_image_generic_subclasses (image
);
2266 mono_loader_unlock ();
2270 free_inflated_method (MonoMethodInflated
*imethod
)
2273 MonoMethod
*method
= (MonoMethod
*)imethod
;
2275 mono_marshal_free_inflated_wrappers (method
);
2277 if (method
->signature
)
2278 mono_metadata_free_inflated_signature (method
->signature
);
2280 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
))) {
2281 MonoMethodNormal
* mn
= (MonoMethodNormal
*) method
;
2282 MonoMethodHeader
*header
= mn
->header
;
2285 /* Allocated in inflate_generic_header () */
2286 for (i
= 0; i
< header
->num_locals
; ++i
)
2287 mono_metadata_free_type (header
->locals
[i
]);
2288 g_free (header
->clauses
);
2297 free_generic_inst (MonoGenericInst
*ginst
)
2301 for (i
= 0; i
< ginst
->type_argc
; ++i
)
2302 mono_metadata_free_type (ginst
->type_argv
[i
]);
2308 free_generic_class (MonoGenericClass
*gclass
)
2312 /* FIXME: The dynamic case */
2313 if (gclass
->cached_class
&& !gclass
->cached_class
->image
->dynamic
&& !mono_generic_class_is_generic_type_definition (gclass
)) {
2314 MonoClass
*class = gclass
->cached_class
;
2316 /* Allocated in mono_class_init () */
2317 g_free (class->methods
);
2319 g_free (class->ext
->properties
);
2320 /* Allocated in mono_generic_class_get_class () */
2321 g_free (class->interfaces
);
2323 } else if (gclass
->is_dynamic
) {
2324 MonoDynamicGenericClass
*dgclass
= (MonoDynamicGenericClass
*)gclass
;
2326 for (i
= 0; i
< dgclass
->count_fields
; ++i
) {
2327 MonoClassField
*field
= dgclass
->fields
+ i
;
2328 mono_metadata_free_type (field
->type
);
2329 g_free ((char*)field
->name
);
2331 MONO_GC_UNREGISTER_ROOT (dgclass
->field_objects
[i
]);
2334 for (i
= 0; i
< dgclass
->count_properties
; ++i
) {
2335 MonoProperty
*property
= dgclass
->properties
+ i
;
2336 g_free ((char*)property
->name
);
2338 for (i
= 0; i
< dgclass
->count_events
; ++i
) {
2339 MonoEvent
*event
= dgclass
->events
+ i
;
2340 g_free ((char*)event
->name
);
2343 g_free (dgclass
->methods
);
2344 g_free (dgclass
->ctors
);
2345 g_free (dgclass
->fields
);
2346 g_free (dgclass
->properties
);
2347 g_free (dgclass
->events
);
2348 g_free (dgclass
->field_objects
);
2349 g_free (dgclass
->field_generic_types
);
2350 if (!mono_generic_class_is_generic_type_definition (gclass
))
2351 g_free (gclass
->cached_class
);
2357 free_inflated_signature (MonoInflatedMethodSignature
*sig
)
2359 mono_metadata_free_inflated_signature (sig
->sig
);
2364 * LOCKING: assumes the loader lock is held.
2367 mono_method_inflated_lookup (MonoMethodInflated
* method
, gboolean cache
)
2370 if (!generic_method_cache
)
2371 generic_method_cache
= g_hash_table_new_full (inflated_method_hash
, inflated_method_equal
, NULL
, (GDestroyNotify
)free_inflated_method
);
2372 g_hash_table_insert (generic_method_cache
, method
, method
);
2375 if (generic_method_cache
)
2376 return g_hash_table_lookup (generic_method_cache
, method
);
2382 * mono_metadata_get_inflated_signature:
2384 * Given an inflated signature and a generic context, return a canonical copy of the
2385 * signature. The returned signature might be equal to SIG or it might be a cached copy.
2387 MonoMethodSignature
*
2388 mono_metadata_get_inflated_signature (MonoMethodSignature
*sig
, MonoGenericContext
*context
)
2390 MonoInflatedMethodSignature helper
;
2391 MonoInflatedMethodSignature
*res
;
2393 mono_loader_lock ();
2394 if (!generic_signature_cache
)
2395 generic_signature_cache
= g_hash_table_new_full (inflated_signature_hash
, inflated_signature_equal
, NULL
, (GDestroyNotify
)free_inflated_signature
);
2398 helper
.context
.class_inst
= context
->class_inst
;
2399 helper
.context
.method_inst
= context
->method_inst
;
2400 res
= g_hash_table_lookup (generic_signature_cache
, &helper
);
2402 res
= g_new0 (MonoInflatedMethodSignature
, 1);
2404 res
->context
.class_inst
= context
->class_inst
;
2405 res
->context
.method_inst
= context
->method_inst
;
2406 g_hash_table_insert (generic_signature_cache
, res
, res
);
2409 mono_loader_unlock ();
2414 * mono_metadata_get_generic_inst:
2416 * Given a list of types, return a MonoGenericInst that represents that list.
2417 * The returned MonoGenericInst has its own copy of the list of types. The list
2418 * passed in the argument can be freed, modified or disposed of.
2422 mono_metadata_get_generic_inst (int type_argc
, MonoType
**type_argv
)
2424 MonoGenericInst
*ginst
;
2427 int size
= MONO_SIZEOF_GENERIC_INST
+ type_argc
* sizeof (MonoType
*);
2429 for (i
= 0; i
< type_argc
; ++i
)
2430 if (mono_class_is_open_constructed_type (type_argv
[i
]))
2432 is_open
= (i
< type_argc
);
2434 ginst
= alloca (size
);
2436 ginst
->is_open
= is_open
;
2437 ginst
->type_argc
= type_argc
;
2438 memcpy (ginst
->type_argv
, type_argv
, type_argc
* sizeof (MonoType
*));
2440 mono_loader_lock ();
2442 ginst
= g_hash_table_lookup (generic_inst_cache
, ginst
);
2444 ginst
= g_malloc (size
);
2445 ginst
->id
= ++next_generic_inst_id
;
2446 ginst
->is_open
= is_open
;
2447 ginst
->type_argc
= type_argc
;
2449 for (i
= 0; i
< type_argc
; ++i
)
2450 ginst
->type_argv
[i
] = mono_metadata_type_dup (NULL
, type_argv
[i
]);
2452 g_hash_table_insert (generic_inst_cache
, ginst
, ginst
);
2455 mono_loader_unlock ();
2460 mono_metadata_is_type_builder_generic_type_definition (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
2462 MonoGenericContainer
*container
= container_class
->generic_container
;
2464 if (!is_dynamic
|| container_class
->wastypebuilder
|| container
->type_argc
!= inst
->type_argc
)
2466 return inst
== container
->context
.class_inst
;
2470 * mono_metadata_lookup_generic_class:
2472 * Returns a MonoGenericClass with the given properties.
2476 mono_metadata_lookup_generic_class (MonoClass
*container_class
, MonoGenericInst
*inst
, gboolean is_dynamic
)
2478 MonoGenericClass
*gclass
;
2479 MonoGenericClass helper
;
2480 gboolean is_tb_open
= mono_metadata_is_type_builder_generic_type_definition (container_class
, inst
, is_dynamic
);
2482 helper
.container_class
= container_class
;
2483 helper
.context
.class_inst
= inst
;
2484 helper
.context
.method_inst
= NULL
;
2485 helper
.is_dynamic
= is_dynamic
; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
2486 helper
.is_tb_open
= is_tb_open
;
2487 helper
.cached_class
= NULL
;
2489 mono_loader_lock ();
2491 gclass
= g_hash_table_lookup (generic_class_cache
, &helper
);
2493 /* A tripwire just to keep us honest */
2494 g_assert (!helper
.cached_class
);
2497 mono_loader_unlock ();
2502 MonoDynamicGenericClass
*dgclass
= g_new0 (MonoDynamicGenericClass
, 1);
2503 gclass
= &dgclass
->generic_class
;
2504 gclass
->is_dynamic
= 1;
2506 gclass
= g_new0 (MonoGenericClass
, 1);
2509 gclass
->is_tb_open
= is_tb_open
;
2510 gclass
->container_class
= container_class
;
2511 gclass
->context
.class_inst
= inst
;
2512 gclass
->context
.method_inst
= NULL
;
2513 if (inst
== container_class
->generic_container
->context
.class_inst
&& !is_tb_open
)
2514 gclass
->cached_class
= container_class
;
2516 g_hash_table_insert (generic_class_cache
, gclass
, gclass
);
2518 mono_loader_unlock ();
2524 * mono_metadata_inflate_generic_inst:
2526 * Instantiate the generic instance @ginst with the context @context.
2530 mono_metadata_inflate_generic_inst (MonoGenericInst
*ginst
, MonoGenericContext
*context
)
2532 MonoType
**type_argv
;
2533 MonoGenericInst
*nginst
;
2536 if (!ginst
->is_open
)
2539 type_argv
= g_new0 (MonoType
*, ginst
->type_argc
);
2541 for (i
= 0; i
< ginst
->type_argc
; i
++)
2542 type_argv
[i
] = mono_class_inflate_generic_type (ginst
->type_argv
[i
], context
);
2544 nginst
= mono_metadata_get_generic_inst (ginst
->type_argc
, type_argv
);
2546 for (i
= 0; i
< ginst
->type_argc
; i
++)
2547 mono_metadata_free_type (type_argv
[i
]);
2554 mono_metadata_parse_generic_inst (MonoImage
*m
, MonoGenericContainer
*container
,
2555 int count
, const char *ptr
, const char **rptr
)
2557 MonoType
**type_argv
;
2558 MonoGenericInst
*ginst
;
2561 type_argv
= g_new0 (MonoType
*, count
);
2563 for (i
= 0; i
< count
; i
++) {
2564 MonoType
*t
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
2575 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
2583 do_mono_metadata_parse_generic_class (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
2584 const char *ptr
, const char **rptr
)
2586 MonoGenericInst
*inst
;
2591 gtype
= mono_metadata_parse_type (m
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
2595 gklass
= mono_class_from_mono_type (gtype
);
2596 if (!gklass
->generic_container
)
2599 count
= mono_metadata_decode_value (ptr
, &ptr
);
2600 inst
= mono_metadata_parse_generic_inst (m
, container
, count
, ptr
, &ptr
);
2607 type
->data
.generic_class
= mono_metadata_lookup_generic_class (gklass
, inst
, FALSE
);
2613 * @gc: The generic container to normalize
2614 * @type: The kind of generic parameters the resulting generic-container should contain
2617 static MonoGenericContainer
*
2618 select_container (MonoGenericContainer
*gc
, MonoTypeEnum type
)
2620 gboolean is_var
= (type
== MONO_TYPE_VAR
);
2624 g_assert (is_var
|| type
== MONO_TYPE_MVAR
);
2627 if (gc
->is_method
|| gc
->parent
)
2629 * The current MonoGenericContainer is a generic method -> its `parent'
2630 * points to the containing class'es container.
2639 * mono_metadata_parse_generic_param:
2640 * @generic_container: Our MonoClass's or MonoMethodNormal's MonoGenericContainer;
2641 * see mono_metadata_parse_type_full() for details.
2642 * Internal routine to parse a generic type parameter.
2643 * LOCKING: Acquires the loader lock
2645 static MonoGenericParam
*
2646 mono_metadata_parse_generic_param (MonoImage
*m
, MonoGenericContainer
*generic_container
,
2647 MonoTypeEnum type
, const char *ptr
, const char **rptr
)
2649 int index
= mono_metadata_decode_value (ptr
, &ptr
);
2653 generic_container
= select_container (generic_container
, type
);
2654 if (!generic_container
) {
2655 /* Create dummy MonoGenericParam */
2656 MonoGenericParam
*param
;
2658 param
= mono_image_alloc0 (m
, sizeof (MonoGenericParam
));
2665 if (index
>= generic_container
->type_argc
)
2668 return mono_generic_container_get_param (generic_container
, index
);
2672 * mono_metadata_get_shared_type:
2674 * Return a shared instance of TYPE, if available, NULL otherwise.
2675 * Shared MonoType instances help save memory. Their contents should not be modified
2676 * by the caller. They do not need to be freed as their lifetime is bound by either
2677 * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
2678 * instance they are embedded in. If they are freed, they should be freed using
2679 * mono_metadata_free_type () instead of g_free ().
2682 mono_metadata_get_shared_type (MonoType
*type
)
2686 /* No need to use locking since nobody is modifying the hash table */
2687 if ((cached
= g_hash_table_lookup (type_cache
, type
)))
2690 switch (type
->type
){
2691 case MONO_TYPE_CLASS
:
2692 case MONO_TYPE_VALUETYPE
:
2693 if (type
== &type
->data
.klass
->byval_arg
)
2695 if (type
== &type
->data
.klass
->this_arg
)
2704 * do_mono_metadata_parse_type:
2705 * @type: MonoType to be filled in with the return value
2707 * @generic_context: generics_context
2708 * @ptr: pointer to the encoded type
2709 * @rptr: pointer where the end of the encoded type is saved
2711 * Internal routine used to "fill" the contents of @type from an
2712 * allocated pointer. This is done this way to avoid doing too
2713 * many mini-allocations (particularly for the MonoFieldType which
2714 * most of the time is just a MonoType, but sometimes might be augmented).
2716 * This routine is used by mono_metadata_parse_type and
2717 * mono_metadata_parse_field_type
2719 * This extracts a Type as specified in Partition II (22.2.12)
2721 * Returns: FALSE if the type could not be loaded
2724 do_mono_metadata_parse_type (MonoType
*type
, MonoImage
*m
, MonoGenericContainer
*container
,
2725 const char *ptr
, const char **rptr
)
2728 type
->type
= mono_metadata_decode_value (ptr
, &ptr
);
2730 switch (type
->type
){
2731 case MONO_TYPE_VOID
:
2732 case MONO_TYPE_BOOLEAN
:
2733 case MONO_TYPE_CHAR
:
2746 case MONO_TYPE_STRING
:
2747 case MONO_TYPE_OBJECT
:
2748 case MONO_TYPE_TYPEDBYREF
:
2750 case MONO_TYPE_VALUETYPE
:
2751 case MONO_TYPE_CLASS
: {
2753 token
= mono_metadata_parse_typedef_or_ref (m
, ptr
, &ptr
);
2754 type
->data
.klass
= mono_class_get (m
, token
);
2755 if (!type
->data
.klass
)
2759 case MONO_TYPE_SZARRAY
: {
2760 MonoType
*etype
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_MOD_TYPE
, 0, ptr
, &ptr
);
2763 type
->data
.klass
= mono_class_from_mono_type (etype
);
2764 if (!type
->data
.klass
)
2769 type
->data
.type
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_MOD_TYPE
, 0, ptr
, &ptr
);
2770 if (!type
->data
.type
)
2773 case MONO_TYPE_FNPTR
:
2774 type
->data
.method
= mono_metadata_parse_method_signature_full (m
, container
, 0, ptr
, &ptr
);
2775 if (!type
->data
.method
)
2778 case MONO_TYPE_ARRAY
:
2779 type
->data
.array
= mono_metadata_parse_array_full (m
, container
, ptr
, &ptr
);
2780 if (!type
->data
.array
)
2783 case MONO_TYPE_MVAR
:
2784 if (container
&& !container
->is_method
)
2787 type
->data
.generic_param
= mono_metadata_parse_generic_param (m
, container
, type
->type
, ptr
, &ptr
);
2788 if (!type
->data
.generic_param
)
2791 case MONO_TYPE_GENERICINST
:
2792 ok
= do_mono_metadata_parse_generic_class (type
, m
, container
, ptr
, &ptr
);
2795 g_warning ("type 0x%02x not handled in do_mono_metadata_parse_type on image %s", type
->type
, m
->name
);
2805 * mono_metadata_free_type:
2806 * @type: type to free
2808 * Free the memory allocated for type @type which is allocated on the heap.
2811 mono_metadata_free_type (MonoType
*type
)
2813 if (type
>= builtin_types
&& type
< builtin_types
+ NBUILTIN_TYPES ())
2816 switch (type
->type
){
2817 case MONO_TYPE_OBJECT
:
2818 case MONO_TYPE_STRING
:
2819 if (!type
->data
.klass
)
2822 case MONO_TYPE_CLASS
:
2823 case MONO_TYPE_VALUETYPE
:
2824 if (type
== &type
->data
.klass
->byval_arg
|| type
== &type
->data
.klass
->this_arg
)
2828 mono_metadata_free_type (type
->data
.type
);
2830 case MONO_TYPE_FNPTR
:
2831 mono_metadata_free_method_signature (type
->data
.method
);
2833 case MONO_TYPE_ARRAY
:
2834 mono_metadata_free_array (type
->data
.array
);
2843 hex_dump (const char *buffer
, int base
, int count
)
2845 int show_header
= 1;
2853 for (i
= 0; i
< count
; i
++){
2856 printf ("\n0x%08x: ", (unsigned char) base
+ i
);
2858 printf ("%02x ", (unsigned char) (buffer
[i
]));
2865 * @mh: The Method header
2866 * @ptr: Points to the beginning of the Section Data (25.3)
2869 parse_section_data (MonoImage
*m
, MonoMethodHeader
*mh
, const unsigned char *ptr
)
2871 unsigned char sect_data_flags
;
2872 const unsigned char *sptr
;
2874 guint32 sect_data_len
;
2877 /* align on 32-bit boundary */
2878 sptr
= ptr
= dword_align (ptr
);
2879 sect_data_flags
= *ptr
;
2882 is_fat
= sect_data_flags
& METHOD_HEADER_SECTION_FAT_FORMAT
;
2884 sect_data_len
= (ptr
[2] << 16) | (ptr
[1] << 8) | ptr
[0];
2887 sect_data_len
= ptr
[0];
2891 g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
2892 hex_dump (sptr, 0, sect_data_len+8);
2893 g_print ("\nheader: ");
2894 hex_dump (sptr-4, 0, 4);
2898 if (sect_data_flags
& METHOD_HEADER_SECTION_EHTABLE
) {
2899 const unsigned char *p
= dword_align (ptr
);
2901 mh
->num_clauses
= is_fat
? sect_data_len
/ 24: sect_data_len
/ 12;
2902 /* we could just store a pointer if we don't need to byteswap */
2903 mh
->clauses
= mono_image_alloc0 (m
, sizeof (MonoExceptionClause
) * mh
->num_clauses
);
2904 for (i
= 0; i
< mh
->num_clauses
; ++i
) {
2905 MonoExceptionClause
*ec
= &mh
->clauses
[i
];
2908 ec
->flags
= read32 (p
);
2909 ec
->try_offset
= read32 (p
+ 4);
2910 ec
->try_len
= read32 (p
+ 8);
2911 ec
->handler_offset
= read32 (p
+ 12);
2912 ec
->handler_len
= read32 (p
+ 16);
2913 tof_value
= read32 (p
+ 20);
2916 ec
->flags
= read16 (p
);
2917 ec
->try_offset
= read16 (p
+ 2);
2918 ec
->try_len
= *(p
+ 4);
2919 ec
->handler_offset
= read16 (p
+ 5);
2920 ec
->handler_len
= *(p
+ 7);
2921 tof_value
= read32 (p
+ 8);
2924 if (ec
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
) {
2925 ec
->data
.filter_offset
= tof_value
;
2926 } else if (ec
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) {
2927 ec
->data
.catch_class
= tof_value
? mono_class_get (m
, tof_value
): 0;
2929 ec
->data
.catch_class
= NULL
;
2931 /* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
2935 if (sect_data_flags
& METHOD_HEADER_SECTION_MORE_SECTS
)
2936 ptr
+= sect_data_len
- 4; /* LAMESPEC: it seems the size includes the header */
2943 * mono_metadata_parse_mh_full:
2944 * @m: metadata context
2945 * @generic_context: generics context
2946 * @ptr: pointer to the method header.
2948 * Decode the method header at @ptr, including pointer to the IL code,
2949 * info about local variables and optional exception tables.
2950 * This is a Mono runtime internal function.
2952 * LOCKING: Acquires the loader lock.
2954 * Returns: a MonoMethodHeader allocated from the image mempool.
2957 mono_metadata_parse_mh_full (MonoImage
*m
, MonoGenericContainer
*container
, const char *ptr
)
2959 MonoMethodHeader
*mh
;
2960 unsigned char flags
= *(const unsigned char *) ptr
;
2961 unsigned char format
= flags
& METHOD_HEADER_FORMAT_MASK
;
2963 guint32 local_var_sig_tok
, max_stack
, code_size
, init_locals
;
2964 const unsigned char *code
;
2967 g_return_val_if_fail (ptr
!= NULL
, NULL
);
2970 case METHOD_HEADER_TINY_FORMAT
:
2971 mh
= mono_image_alloc0 (m
, MONO_SIZEOF_METHOD_HEADER
);
2974 local_var_sig_tok
= 0;
2975 mh
->code_size
= flags
>> 2;
2976 mh
->code
= (unsigned char*)ptr
;
2978 case METHOD_HEADER_FAT_FORMAT
:
2979 fat_flags
= read16 (ptr
);
2981 hsize
= (fat_flags
>> 12) & 0xf;
2982 max_stack
= read16 (ptr
);
2984 code_size
= read32 (ptr
);
2986 local_var_sig_tok
= read32 (ptr
);
2989 if (fat_flags
& METHOD_HEADER_INIT_LOCALS
)
2994 code
= (unsigned char*)ptr
;
2996 if (!(fat_flags
& METHOD_HEADER_MORE_SECTS
))
3000 * There are more sections
3002 ptr
= (char*)code
+ code_size
;
3008 if (local_var_sig_tok
) {
3009 MonoTableInfo
*t
= &m
->tables
[MONO_TABLE_STANDALONESIG
];
3010 const char *locals_ptr
;
3011 guint32 cols
[MONO_STAND_ALONE_SIGNATURE_SIZE
];
3012 int len
=0, i
, bsize
;
3014 mono_metadata_decode_row (t
, (local_var_sig_tok
& 0xffffff)-1, cols
, 1);
3016 if (!mono_verifier_verify_standalone_signature (m
, cols
[MONO_STAND_ALONE_SIGNATURE
], NULL
))
3019 locals_ptr
= mono_metadata_blob_heap (m
, cols
[MONO_STAND_ALONE_SIGNATURE
]);
3020 bsize
= mono_metadata_decode_blob_size (locals_ptr
, &locals_ptr
);
3021 if (*locals_ptr
!= 0x07)
3022 g_warning ("wrong signature for locals blob");
3024 len
= mono_metadata_decode_value (locals_ptr
, &locals_ptr
);
3025 mh
= mono_image_alloc0 (m
, MONO_SIZEOF_METHOD_HEADER
+ len
* sizeof (MonoType
*));
3026 mh
->num_locals
= len
;
3027 for (i
= 0; i
< len
; ++i
) {
3028 mh
->locals
[i
] = mono_metadata_parse_type_full (
3029 m
, container
, MONO_PARSE_LOCAL
, 0, locals_ptr
, &locals_ptr
);
3030 if (!mh
->locals
[i
]) {
3035 mh
= mono_image_alloc0 (m
, MONO_SIZEOF_METHOD_HEADER
);
3038 mh
->code_size
= code_size
;
3039 mh
->max_stack
= max_stack
;
3040 mh
->init_locals
= init_locals
;
3041 if (fat_flags
& METHOD_HEADER_MORE_SECTS
)
3042 parse_section_data (m
, mh
, (const unsigned char*)ptr
);
3047 * mono_metadata_parse_mh:
3048 * @generic_context: generics context
3049 * @ptr: pointer to the method header.
3051 * Decode the method header at @ptr, including pointer to the IL code,
3052 * info about local variables and optional exception tables.
3053 * This is a Mono runtime internal function.
3055 * Returns: a MonoMethodHeader.
3058 mono_metadata_parse_mh (MonoImage
*m
, const char *ptr
)
3060 MonoMethodHeader
*res
;
3062 mono_loader_lock ();
3064 res
= mono_metadata_parse_mh_full (m
, NULL
, ptr
);
3066 mono_loader_unlock ();
3072 * mono_metadata_free_mh:
3073 * @mh: a method header
3075 * Free the memory allocated for the method header.
3076 * This is a Mono runtime internal function.
3079 mono_metadata_free_mh (MonoMethodHeader
*mh
)
3081 /* Allocated from the mempool */
3085 * mono_method_header_get_code:
3086 * @header: a MonoMethodHeader pointer
3087 * @code_size: memory location for returning the code size
3088 * @max_stack: memory location for returning the max stack
3090 * Method header accessor to retreive info about the IL code properties:
3091 * a pointer to the IL code itself, the size of the code and the max number
3092 * of stack slots used by the code.
3094 * Returns: pointer to the IL code represented by the method header.
3096 const unsigned char*
3097 mono_method_header_get_code (MonoMethodHeader
*header
, guint32
* code_size
, guint32
* max_stack
)
3100 *code_size
= header
->code_size
;
3102 *max_stack
= header
->max_stack
;
3103 return header
->code
;
3107 * mono_method_header_get_locals:
3108 * @header: a MonoMethodHeader pointer
3109 * @num_locals: memory location for returning the number of local variables
3110 * @init_locals: memory location for returning the init_locals flag
3112 * Method header accessor to retreive info about the local variables:
3113 * an array of local types, the number of locals and whether the locals
3114 * are supposed to be initialized to 0 on method entry
3116 * Returns: pointer to an array of types of the local variables
3119 mono_method_header_get_locals (MonoMethodHeader
*header
, guint32
* num_locals
, gboolean
*init_locals
)
3122 *num_locals
= header
->num_locals
;
3124 *init_locals
= header
->init_locals
;
3125 return header
->locals
;
3129 * mono_method_header_get_num_clauses:
3130 * @header: a MonoMethodHeader pointer
3132 * Method header accessor to retreive the number of exception clauses.
3134 * Returns: the number of exception clauses present
3137 mono_method_header_get_num_clauses (MonoMethodHeader
*header
)
3139 return header
->num_clauses
;
3143 * mono_method_header_get_clauses:
3144 * @header: a MonoMethodHeader pointer
3145 * @method: MonoMethod the header belongs to
3146 * @iter: pointer to a iterator
3147 * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
3149 * Get the info about the exception clauses in the method. Set *iter to NULL to
3150 * initiate the iteration, then call the method repeatedly until it returns FALSE.
3151 * At each iteration, the structure pointed to by clause if filled with the
3152 * exception clause information.
3154 * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
3158 mono_method_header_get_clauses (MonoMethodHeader
*header
, MonoMethod
*method
, gpointer
*iter
, MonoExceptionClause
*clause
)
3160 MonoExceptionClause
*sc
;
3161 /* later we'll be able to use this interface to parse the clause info on demand,
3162 * without allocating anything.
3164 if (!iter
|| !header
->num_clauses
)
3167 *iter
= sc
= header
->clauses
;
3173 if (sc
< header
->clauses
+ header
->num_clauses
) {
3182 * mono_metadata_parse_field_type:
3183 * @m: metadata context to extract information from
3184 * @ptr: pointer to the field signature
3185 * @rptr: pointer updated to match the end of the decoded stream
3187 * Parses the field signature, and returns the type information for it.
3189 * Returns: The MonoType that was extracted from @ptr.
3192 mono_metadata_parse_field_type (MonoImage
*m
, short field_flags
, const char *ptr
, const char **rptr
)
3194 return mono_metadata_parse_type (m
, MONO_PARSE_FIELD
, field_flags
, ptr
, rptr
);
3198 * mono_metadata_parse_param:
3199 * @m: metadata context to extract information from
3200 * @ptr: pointer to the param signature
3201 * @rptr: pointer updated to match the end of the decoded stream
3203 * Parses the param signature, and returns the type information for it.
3205 * Returns: The MonoType that was extracted from @ptr.
3208 mono_metadata_parse_param (MonoImage
*m
, const char *ptr
, const char **rptr
)
3210 return mono_metadata_parse_type (m
, MONO_PARSE_PARAM
, 0, ptr
, rptr
);
3214 * mono_metadata_token_from_dor:
3215 * @dor_token: A TypeDefOrRef coded index
3217 * dor_token is a TypeDefOrRef coded index: it contains either
3218 * a TypeDef, TypeRef or TypeSpec in the lower bits, and the upper
3219 * bits contain an index into the table.
3221 * Returns: an expanded token
3224 mono_metadata_token_from_dor (guint32 dor_index
)
3228 table
= dor_index
& 0x03;
3229 idx
= dor_index
>> 2;
3232 case 0: /* TypeDef */
3233 return MONO_TOKEN_TYPE_DEF
| idx
;
3234 case 1: /* TypeRef */
3235 return MONO_TOKEN_TYPE_REF
| idx
;
3236 case 2: /* TypeSpec */
3237 return MONO_TOKEN_TYPE_SPEC
| idx
;
3239 g_assert_not_reached ();
3246 * We use this to pass context information to the row locator
3249 int idx
; /* The index that we are trying to locate */
3250 int col_idx
; /* The index in the row where idx may be stored */
3251 MonoTableInfo
*t
; /* pointer to the table */
3256 * How the row locator works.
3261 * ___|___------> _______
3264 * A column in the rows of table A references an index in table B.
3265 * For example A may be the TYPEDEF table and B the METHODDEF table.
3267 * Given an index in table B we want to get the row in table A
3268 * where the column n references our index in B.
3270 * In the locator_t structure:
3272 * col_idx is the column number
3273 * index is the index in table B
3274 * result will be the index in table A
3277 * Table A Table B column (in table A)
3278 * TYPEDEF METHODDEF MONO_TYPEDEF_METHOD_LIST
3279 * TYPEDEF FIELD MONO_TYPEDEF_FIELD_LIST
3280 * PROPERTYMAP PROPERTY MONO_PROPERTY_MAP_PROPERTY_LIST
3281 * INTERFIMPL TYPEDEF MONO_INTERFACEIMPL_CLASS
3282 * METHODSEM PROPERTY ASSOCIATION (encoded index)
3284 * Note that we still don't support encoded indexes.
3288 typedef_locator (const void *a
, const void *b
)
3290 locator_t
*loc
= (locator_t
*) a
;
3291 const char *bb
= (const char *) b
;
3292 int typedef_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3293 guint32 col
, col_next
;
3295 col
= mono_metadata_decode_row_col (loc
->t
, typedef_index
, loc
->col_idx
);
3301 * Need to check that the next row is valid.
3303 if (typedef_index
+ 1 < loc
->t
->rows
) {
3304 col_next
= mono_metadata_decode_row_col (loc
->t
, typedef_index
+ 1, loc
->col_idx
);
3305 if (loc
->idx
>= col_next
)
3308 if (col
== col_next
)
3312 loc
->result
= typedef_index
;
3318 table_locator (const void *a
, const void *b
)
3320 locator_t
*loc
= (locator_t
*) a
;
3321 const char *bb
= (const char *) b
;
3322 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3325 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
3327 if (loc
->idx
== col
) {
3328 loc
->result
= table_index
;
3338 declsec_locator (const void *a
, const void *b
)
3340 locator_t
*loc
= (locator_t
*) a
;
3341 const char *bb
= (const char *) b
;
3342 guint32 table_index
= (bb
- loc
->t
->base
) / loc
->t
->row_size
;
3345 col
= mono_metadata_decode_row_col (loc
->t
, table_index
, loc
->col_idx
);
3347 if (loc
->idx
== col
) {
3348 loc
->result
= table_index
;
3360 * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
3361 * which contains IDX.
3364 search_ptr_table (MonoImage
*image
, int table
, int idx
)
3366 MonoTableInfo
*ptrdef
= &image
->tables
[table
];
3369 /* Use a linear search to find our index in the table */
3370 for (i
= 0; i
< ptrdef
->rows
; i
++)
3371 /* All the Ptr tables have the same structure */
3372 if (mono_metadata_decode_row_col (ptrdef
, i
, 0) == idx
)
3375 if (i
< ptrdef
->rows
)
3382 * mono_metadata_typedef_from_field:
3383 * @meta: metadata context
3384 * @index: FieldDef token
3386 * Returns: the 1-based index into the TypeDef table of the type that
3387 * declared the field described by @index, or 0 if not found.
3390 mono_metadata_typedef_from_field (MonoImage
*meta
, guint32 index
)
3392 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
3398 loc
.idx
= mono_metadata_token_index (index
);
3399 loc
.col_idx
= MONO_TYPEDEF_FIELD_LIST
;
3402 if (meta
->uncompressed_metadata
)
3403 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
3405 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
3406 g_assert_not_reached ();
3408 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3409 return loc
.result
+ 1;
3413 * mono_metadata_typedef_from_method:
3414 * @meta: metadata context
3415 * @index: MethodDef token
3417 * Returns: the 1-based index into the TypeDef table of the type that
3418 * declared the method described by @index. 0 if not found.
3421 mono_metadata_typedef_from_method (MonoImage
*meta
, guint32 index
)
3423 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_TYPEDEF
];
3429 loc
.idx
= mono_metadata_token_index (index
);
3430 loc
.col_idx
= MONO_TYPEDEF_METHOD_LIST
;
3433 if (meta
->uncompressed_metadata
)
3434 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_METHOD_POINTER
, loc
.idx
);
3436 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, typedef_locator
))
3437 g_assert_not_reached ();
3439 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3440 return loc
.result
+ 1;
3444 * mono_metadata_interfaces_from_typedef_full:
3445 * @meta: metadata context
3446 * @index: typedef token
3447 * @interfaces: Out parameter used to store the interface array
3448 * @count: Out parameter used to store the number of interfaces
3449 * @heap_alloc_result: if TRUE the result array will be g_malloc'd
3450 * @context: The generic context
3452 * The array of interfaces that the @index typedef token implements is returned in
3453 * @interfaces. The number of elements in the array is returned in @count.
3455 * LOCKING: Assumes the loader lock is held.
3457 * Returns: TRUE on success, FALSE on failure.
3460 mono_metadata_interfaces_from_typedef_full (MonoImage
*meta
, guint32 index
, MonoClass
***interfaces
, guint
*count
, gboolean heap_alloc_result
, MonoGenericContext
*context
)
3462 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_INTERFACEIMPL
];
3465 guint32 cols
[MONO_INTERFACEIMPL_SIZE
];
3474 loc
.idx
= mono_metadata_token_index (index
);
3475 loc
.col_idx
= MONO_INTERFACEIMPL_CLASS
;
3478 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
3483 * We may end up in the middle of the rows...
3486 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_INTERFACEIMPL_CLASS
))
3492 while (pos
< tdef
->rows
) {
3493 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
3494 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
3499 if (heap_alloc_result
)
3500 result
= g_new0 (MonoClass
*, pos
- start
);
3502 result
= mono_image_alloc0 (meta
, sizeof (MonoClass
*) * (pos
- start
));
3505 while (pos
< tdef
->rows
) {
3508 mono_metadata_decode_row (tdef
, pos
, cols
, MONO_INTERFACEIMPL_SIZE
);
3509 if (cols
[MONO_INTERFACEIMPL_CLASS
] != loc
.idx
)
3511 iface
= mono_class_get_full (
3512 meta
, mono_metadata_token_from_dor (cols
[MONO_INTERFACEIMPL_INTERFACE
]), context
);
3515 result
[pos
- start
] = iface
;
3518 *count
= pos
- start
;
3519 *interfaces
= result
;
3524 * @meta: metadata context
3525 * @index: typedef token
3526 * @count: Out parameter used to store the number of interfaces
3528 * The array of interfaces that the @index typedef token implements is returned in
3529 * @interfaces. The number of elements in the array is returned in @count. The returned
3530 * array is g_malloc'd and the caller must free it.
3532 * LOCKING: Acquires the loader lock .
3534 * Returns: the interface array on success, NULL on failure.
3538 mono_metadata_interfaces_from_typedef (MonoImage
*meta
, guint32 index
, guint
*count
)
3540 MonoClass
**interfaces
;
3543 mono_loader_lock ();
3544 rv
= mono_metadata_interfaces_from_typedef_full (meta
, index
, &interfaces
, count
, TRUE
, NULL
);
3545 mono_loader_unlock ();
3553 * mono_metadata_nested_in_typedef:
3554 * @meta: metadata context
3555 * @index: typedef token
3557 * Returns: the 1-based index into the TypeDef table of the type
3558 * where the type described by @index is nested.
3559 * Retruns 0 if @index describes a non-nested type.
3562 mono_metadata_nested_in_typedef (MonoImage
*meta
, guint32 index
)
3564 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
3570 loc
.idx
= mono_metadata_token_index (index
);
3571 loc
.col_idx
= MONO_NESTED_CLASS_NESTED
;
3574 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
3577 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3578 return mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_NESTED_CLASS_ENCLOSING
) | MONO_TOKEN_TYPE_DEF
;
3582 * mono_metadata_nesting_typedef:
3583 * @meta: metadata context
3584 * @index: typedef token
3586 * Returns: the 1-based index into the TypeDef table of the first type
3587 * that is nested inside the type described by @index. The search starts at
3588 * @start_index. returns 0 if no such type is found.
3591 mono_metadata_nesting_typedef (MonoImage
*meta
, guint32 index
, guint32 start_index
)
3593 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_NESTEDCLASS
];
3595 guint32 class_index
= mono_metadata_token_index (index
);
3600 start
= start_index
;
3602 while (start
<= tdef
->rows
) {
3603 if (class_index
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_NESTED_CLASS_ENCLOSING
))
3609 if (start
> tdef
->rows
)
3616 * mono_metadata_packing_from_typedef:
3617 * @meta: metadata context
3618 * @index: token representing a type
3620 * Returns: the info stored in the ClassLAyout table for the given typedef token
3621 * into the @packing and @size pointers.
3622 * Returns 0 if the info is not found.
3625 mono_metadata_packing_from_typedef (MonoImage
*meta
, guint32 index
, guint32
*packing
, guint32
*size
)
3627 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CLASSLAYOUT
];
3629 guint32 cols
[MONO_CLASS_LAYOUT_SIZE
];
3634 loc
.idx
= mono_metadata_token_index (index
);
3635 loc
.col_idx
= MONO_CLASS_LAYOUT_PARENT
;
3638 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
3641 mono_metadata_decode_row (tdef
, loc
.result
, cols
, MONO_CLASS_LAYOUT_SIZE
);
3643 *packing
= cols
[MONO_CLASS_LAYOUT_PACKING_SIZE
];
3645 *size
= cols
[MONO_CLASS_LAYOUT_CLASS_SIZE
];
3647 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3648 return loc
.result
+ 1;
3652 * mono_metadata_custom_attrs_from_index:
3653 * @meta: metadata context
3654 * @index: token representing the parent
3656 * Returns: the 1-based index into the CustomAttribute table of the first
3657 * attribute which belongs to the metadata object described by @index.
3658 * Returns 0 if no such attribute is found.
3661 mono_metadata_custom_attrs_from_index (MonoImage
*meta
, guint32 index
)
3663 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
3670 loc
.col_idx
= MONO_CUSTOM_ATTR_PARENT
;
3673 /* FIXME: Index translation */
3675 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
3678 /* Find the first entry by searching backwards */
3679 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_CUSTOM_ATTR_PARENT
) == index
))
3682 /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
3683 return loc
.result
+ 1;
3687 * mono_metadata_declsec_from_index:
3688 * @meta: metadata context
3689 * @index: token representing the parent
3691 * Returns: the 0-based index into the DeclarativeSecurity table of the first
3692 * attribute which belongs to the metadata object described by @index.
3693 * Returns -1 if no such attribute is found.
3696 mono_metadata_declsec_from_index (MonoImage
*meta
, guint32 index
)
3698 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_DECLSECURITY
];
3705 loc
.col_idx
= MONO_DECL_SECURITY_PARENT
;
3708 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, declsec_locator
))
3711 /* Find the first entry by searching backwards */
3712 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_DECL_SECURITY_PARENT
) == index
))
3720 mono_backtrace (int limit
)
3725 backtrace (array
, limit
);
3726 names
= backtrace_symbols (array
, limit
);
3727 for (i
=0; i
< limit
; ++i
) {
3728 g_print ("\t%s\n", names
[i
]);
3735 /*#define __alignof__(a) sizeof(a)*/
3736 #define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
3741 * @t: the type to return the size of
3743 * Returns: the number of bytes required to hold an instance of this
3747 mono_type_size (MonoType
*t
, int *align
)
3754 *align
= __alignof__(gpointer
);
3755 return sizeof (gpointer
);
3759 case MONO_TYPE_VOID
:
3762 case MONO_TYPE_BOOLEAN
:
3763 *align
= __alignof__(gint8
);
3767 *align
= __alignof__(gint8
);
3769 case MONO_TYPE_CHAR
:
3772 *align
= __alignof__(gint16
);
3776 *align
= __alignof__(gint32
);
3779 *align
= __alignof__(float);
3783 *align
= __alignof__(gint64
);
3786 *align
= __alignof__(double);
3790 *align
= __alignof__(gpointer
);
3791 return sizeof (gpointer
);
3792 case MONO_TYPE_STRING
:
3793 *align
= __alignof__(gpointer
);
3794 return sizeof (gpointer
);
3795 case MONO_TYPE_OBJECT
:
3796 *align
= __alignof__(gpointer
);
3797 return sizeof (gpointer
);
3798 case MONO_TYPE_VALUETYPE
: {
3799 if (t
->data
.klass
->enumtype
)
3800 return mono_type_size (mono_class_enum_basetype (t
->data
.klass
), align
);
3802 return mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
3804 case MONO_TYPE_CLASS
:
3805 case MONO_TYPE_SZARRAY
:
3807 case MONO_TYPE_FNPTR
:
3808 case MONO_TYPE_ARRAY
:
3809 *align
= __alignof__(gpointer
);
3810 return sizeof (gpointer
);
3811 case MONO_TYPE_TYPEDBYREF
:
3812 return mono_class_value_size (mono_defaults
.typed_reference_class
, (guint32
*)align
);
3813 case MONO_TYPE_GENERICINST
: {
3814 MonoGenericClass
*gclass
= t
->data
.generic_class
;
3815 MonoClass
*container_class
= gclass
->container_class
;
3817 // g_assert (!gclass->inst->is_open);
3819 if (container_class
->valuetype
) {
3820 if (container_class
->enumtype
)
3821 return mono_type_size (mono_class_enum_basetype (container_class
), align
);
3823 return mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
3825 *align
= __alignof__(gpointer
);
3826 return sizeof (gpointer
);
3830 case MONO_TYPE_MVAR
:
3831 /* FIXME: Martin, this is wrong. */
3832 *align
= __alignof__(gpointer
);
3833 return sizeof (gpointer
);
3835 g_error ("mono_type_size: type 0x%02x unknown", t
->type
);
3841 * mono_type_stack_size:
3842 * @t: the type to return the size it uses on the stack
3844 * Returns: the number of bytes required to hold an instance of this
3845 * type on the runtime stack
3848 mono_type_stack_size (MonoType
*t
, int *align
)
3850 return mono_type_stack_size_internal (t
, align
, FALSE
);
3854 mono_type_stack_size_internal (MonoType
*t
, int *align
, gboolean allow_open
)
3857 #if SIZEOF_VOID_P == SIZEOF_REGISTER
3858 int stack_slot_size
= sizeof (gpointer
);
3859 int stack_slot_align
= __alignof__ (gpointer
);
3860 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
3861 int stack_slot_size
= SIZEOF_REGISTER
;
3862 int stack_slot_align
= SIZEOF_REGISTER
;
3865 g_assert (t
!= NULL
);
3871 *align
= stack_slot_align
;
3872 return stack_slot_size
;
3876 case MONO_TYPE_BOOLEAN
:
3877 case MONO_TYPE_CHAR
:
3886 case MONO_TYPE_STRING
:
3887 case MONO_TYPE_OBJECT
:
3888 case MONO_TYPE_CLASS
:
3889 case MONO_TYPE_SZARRAY
:
3891 case MONO_TYPE_FNPTR
:
3892 case MONO_TYPE_ARRAY
:
3893 *align
= stack_slot_align
;
3894 return stack_slot_size
;
3896 case MONO_TYPE_MVAR
:
3897 g_assert (allow_open
);
3898 *align
= stack_slot_align
;
3899 return stack_slot_size
;
3900 case MONO_TYPE_TYPEDBYREF
:
3901 *align
= stack_slot_align
;
3902 return stack_slot_size
* 3;
3904 *align
= __alignof__(float);
3905 return sizeof (float);
3908 *align
= __alignof__(gint64
);
3909 return sizeof (gint64
);
3911 *align
= __alignof__(double);
3912 return sizeof (double);
3913 case MONO_TYPE_VALUETYPE
: {
3916 if (t
->data
.klass
->enumtype
)
3917 return mono_type_stack_size_internal (mono_class_enum_basetype (t
->data
.klass
), align
, allow_open
);
3919 size
= mono_class_value_size (t
->data
.klass
, (guint32
*)align
);
3921 *align
= *align
+ stack_slot_align
- 1;
3922 *align
&= ~(stack_slot_align
- 1);
3924 size
+= stack_slot_size
- 1;
3925 size
&= ~(stack_slot_size
- 1);
3930 case MONO_TYPE_GENERICINST
: {
3931 MonoGenericClass
*gclass
= t
->data
.generic_class
;
3932 MonoClass
*container_class
= gclass
->container_class
;
3935 g_assert (!gclass
->context
.class_inst
->is_open
);
3937 if (container_class
->valuetype
) {
3938 if (container_class
->enumtype
)
3939 return mono_type_stack_size_internal (mono_class_enum_basetype (container_class
), align
, allow_open
);
3941 guint32 size
= mono_class_value_size (mono_class_from_mono_type (t
), (guint32
*)align
);
3943 *align
= *align
+ stack_slot_align
- 1;
3944 *align
&= ~(stack_slot_align
- 1);
3946 size
+= stack_slot_size
- 1;
3947 size
&= ~(stack_slot_size
- 1);
3952 *align
= stack_slot_align
;
3953 return stack_slot_size
;
3957 g_error ("type 0x%02x unknown", t
->type
);
3963 mono_type_generic_inst_is_valuetype (MonoType
*type
)
3965 g_assert (type
->type
== MONO_TYPE_GENERICINST
);
3966 return type
->data
.generic_class
->container_class
->valuetype
;
3970 mono_metadata_generic_class_is_valuetype (MonoGenericClass
*gclass
)
3972 return gclass
->container_class
->valuetype
;
3976 _mono_metadata_generic_class_equal (const MonoGenericClass
*g1
, const MonoGenericClass
*g2
, gboolean signature_only
)
3978 MonoGenericInst
*i1
= g1
->context
.class_inst
;
3979 MonoGenericInst
*i2
= g2
->context
.class_inst
;
3981 if (g1
->is_dynamic
!= g2
->is_dynamic
)
3983 if (!mono_metadata_class_equal (g1
->container_class
, g2
->container_class
, signature_only
))
3985 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
3987 return g1
->is_tb_open
== g2
->is_tb_open
;
3991 _mono_metadata_generic_class_container_equal (const MonoGenericClass
*g1
, MonoClass
*c2
, gboolean signature_only
)
3993 MonoGenericInst
*i1
= g1
->context
.class_inst
;
3994 MonoGenericInst
*i2
= c2
->generic_container
->context
.class_inst
;
3996 if (!mono_metadata_class_equal (g1
->container_class
, c2
, signature_only
))
3998 if (!mono_generic_inst_equal_full (i1
, i2
, signature_only
))
4000 return !g1
->is_tb_open
;
4004 mono_metadata_generic_context_hash (const MonoGenericContext
*context
)
4006 /* FIXME: check if this seed is good enough */
4007 guint hash
= 0xc01dfee7;
4008 if (context
->class_inst
)
4009 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->class_inst
);
4010 if (context
->method_inst
)
4011 hash
= ((hash
<< 5) - hash
) ^ mono_metadata_generic_inst_hash (context
->method_inst
);
4016 mono_metadata_generic_context_equal (const MonoGenericContext
*g1
, const MonoGenericContext
*g2
)
4018 return g1
->class_inst
== g2
->class_inst
&& g1
->method_inst
== g2
->method_inst
;
4022 * mono_metadata_type_hash:
4025 * Computes an hash value for @t1 to be used in GHashTable.
4028 mono_metadata_type_hash (MonoType
*t1
)
4030 guint hash
= t1
->type
;
4032 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
4034 case MONO_TYPE_VALUETYPE
:
4035 case MONO_TYPE_CLASS
:
4036 case MONO_TYPE_SZARRAY
:
4037 /* check if the distribution is good enough */
4038 return ((hash
<< 5) - hash
) ^ g_str_hash (t1
->data
.klass
->name
);
4040 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (t1
->data
.type
);
4041 case MONO_TYPE_ARRAY
:
4042 return ((hash
<< 5) - hash
) ^ mono_metadata_type_hash (&t1
->data
.array
->eklass
->byval_arg
);
4043 case MONO_TYPE_GENERICINST
:
4044 return ((hash
<< 5) - hash
) ^ mono_generic_class_hash (t1
->data
.generic_class
);
4050 mono_metadata_generic_param_equal (MonoGenericParam
*p1
, MonoGenericParam
*p2
, gboolean signature_only
)
4054 if (mono_generic_param_num (p1
) != mono_generic_param_num (p2
))
4058 * We have to compare the image as well because if we didn't,
4059 * the generic_inst_cache lookup wouldn't care about the image
4060 * of generic params, so what could happen is that a generic
4061 * inst with params from image A is put into the cache, then
4062 * image B gets that generic inst from the cache, image A is
4063 * unloaded, so the inst is deleted, but image B still retains
4066 * The AOT runtime doesn't set the image when it's decoding
4067 * types, so we only compare it when the owner is NULL.
4069 if (mono_generic_param_owner (p1
) == mono_generic_param_owner (p2
) &&
4070 (mono_generic_param_owner (p1
) || p1
->image
== p2
->image
))
4074 * If `signature_only' is true, we're comparing two (method) signatures.
4075 * In this case, the owner of two type parameters doesn't need to match.
4078 return signature_only
;
4082 mono_metadata_class_equal (MonoClass
*c1
, MonoClass
*c2
, gboolean signature_only
)
4086 if (c1
->generic_class
&& c2
->generic_class
)
4087 return _mono_metadata_generic_class_equal (c1
->generic_class
, c2
->generic_class
, signature_only
);
4088 if (c1
->generic_class
&& c2
->generic_container
)
4089 return _mono_metadata_generic_class_container_equal (c1
->generic_class
, c2
, signature_only
);
4090 if (c1
->generic_container
&& c2
->generic_class
)
4091 return _mono_metadata_generic_class_container_equal (c2
->generic_class
, c1
, signature_only
);
4092 if ((c1
->byval_arg
.type
== MONO_TYPE_VAR
) && (c2
->byval_arg
.type
== MONO_TYPE_VAR
))
4093 return mono_metadata_generic_param_equal (
4094 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
4095 if ((c1
->byval_arg
.type
== MONO_TYPE_MVAR
) && (c2
->byval_arg
.type
== MONO_TYPE_MVAR
))
4096 return mono_metadata_generic_param_equal (
4097 c1
->byval_arg
.data
.generic_param
, c2
->byval_arg
.data
.generic_param
, signature_only
);
4098 if (signature_only
&&
4099 (c1
->byval_arg
.type
== MONO_TYPE_SZARRAY
) && (c2
->byval_arg
.type
== MONO_TYPE_SZARRAY
))
4100 return mono_metadata_class_equal (c1
->byval_arg
.data
.klass
, c2
->byval_arg
.data
.klass
, signature_only
);
4105 mono_metadata_fnptr_equal (MonoMethodSignature
*s1
, MonoMethodSignature
*s2
, gboolean signature_only
)
4107 gpointer iter1
= 0, iter2
= 0;
4111 if (s1
->call_convention
!= s2
->call_convention
)
4113 if (s1
->sentinelpos
!= s2
->sentinelpos
)
4115 if (s1
->hasthis
!= s2
->hasthis
)
4117 if (s1
->explicit_this
!= s2
->explicit_this
)
4119 if (! do_mono_metadata_type_equal (s1
->ret
, s2
->ret
, signature_only
))
4121 if (s1
->param_count
!= s2
->param_count
)
4125 MonoType
*t1
= mono_signature_get_params (s1
, &iter1
);
4126 MonoType
*t2
= mono_signature_get_params (s2
, &iter2
);
4128 if (t1
== NULL
|| t2
== NULL
)
4130 if (! do_mono_metadata_type_equal (t1
, t2
, signature_only
))
4136 * mono_metadata_type_equal:
4140 * Determine if @t1 and @t2 represent the same type.
4141 * Returns: #TRUE if @t1 and @t2 are equal.
4144 do_mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
4146 if (t1
->type
!= t2
->type
|| t1
->byref
!= t2
->byref
)
4150 case MONO_TYPE_VOID
:
4151 case MONO_TYPE_BOOLEAN
:
4152 case MONO_TYPE_CHAR
:
4163 case MONO_TYPE_STRING
:
4166 case MONO_TYPE_OBJECT
:
4167 case MONO_TYPE_TYPEDBYREF
:
4169 case MONO_TYPE_VALUETYPE
:
4170 case MONO_TYPE_CLASS
:
4171 case MONO_TYPE_SZARRAY
:
4172 return mono_metadata_class_equal (t1
->data
.klass
, t2
->data
.klass
, signature_only
);
4174 return do_mono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
, signature_only
);
4175 case MONO_TYPE_ARRAY
:
4176 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
4178 return mono_metadata_class_equal (t1
->data
.array
->eklass
, t2
->data
.array
->eklass
, signature_only
);
4179 case MONO_TYPE_GENERICINST
:
4180 return _mono_metadata_generic_class_equal (
4181 t1
->data
.generic_class
, t2
->data
.generic_class
, signature_only
);
4183 return mono_metadata_generic_param_equal (
4184 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
4185 case MONO_TYPE_MVAR
:
4186 return mono_metadata_generic_param_equal (
4187 t1
->data
.generic_param
, t2
->data
.generic_param
, signature_only
);
4188 case MONO_TYPE_FNPTR
:
4189 return mono_metadata_fnptr_equal (t1
->data
.method
, t2
->data
.method
, signature_only
);
4191 g_error ("implement type compare for %0x!", t1
->type
);
4199 mono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
4201 return do_mono_metadata_type_equal (t1
, t2
, FALSE
);
4205 * mono_metadata_type_equal_full:
4208 * @signature_only: if signature only comparison should be made
4210 * Determine if @t1 and @t2 are signature compatible if @signature_only is #TRUE, otherwise
4211 * behaves the same way as mono_metadata_type_equal.
4212 * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
4213 * Returns: #TRUE if @t1 and @t2 are equal taking @signature_only into account.
4216 mono_metadata_type_equal_full (MonoType
*t1
, MonoType
*t2
, gboolean signature_only
)
4218 return do_mono_metadata_type_equal (t1
, t2
, signature_only
);
4222 * mono_metadata_signature_equal:
4223 * @sig1: a signature
4224 * @sig2: another signature
4226 * Determine if @sig1 and @sig2 represent the same signature, with the
4227 * same number of arguments and the same types.
4228 * Returns: #TRUE if @sig1 and @sig2 are equal.
4231 mono_metadata_signature_equal (MonoMethodSignature
*sig1
, MonoMethodSignature
*sig2
)
4235 if (sig1
->hasthis
!= sig2
->hasthis
|| sig1
->param_count
!= sig2
->param_count
)
4238 if (sig1
->generic_param_count
!= sig2
->generic_param_count
)
4242 * We're just comparing the signatures of two methods here:
4244 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
4245 * U and V are equal here.
4247 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
4250 for (i
= 0; i
< sig1
->param_count
; i
++) {
4251 MonoType
*p1
= sig1
->params
[i
];
4252 MonoType
*p2
= sig2
->params
[i
];
4254 /* if (p1->attrs != p2->attrs)
4257 if (!do_mono_metadata_type_equal (p1
, p2
, TRUE
))
4261 if (!do_mono_metadata_type_equal (sig1
->ret
, sig2
->ret
, TRUE
))
4267 * mono_metadata_type_dup:
4268 * @image: image to alloc memory from
4269 * @original: type to duplicate
4271 * Returns: copy of type allocated from the image's mempool (or from the heap, if @image is null).
4274 mono_metadata_type_dup (MonoImage
*image
, const MonoType
*o
)
4277 int sizeof_o
= MONO_SIZEOF_TYPE
;
4279 sizeof_o
+= o
->num_mods
* sizeof (MonoCustomMod
);
4281 r
= image
? mono_image_alloc0 (image
, sizeof_o
) : g_malloc (sizeof_o
);
4283 memcpy (r
, o
, sizeof_o
);
4285 if (o
->type
== MONO_TYPE_PTR
) {
4286 r
->data
.type
= mono_metadata_type_dup (image
, o
->data
.type
);
4287 } else if (o
->type
== MONO_TYPE_ARRAY
) {
4288 r
->data
.array
= mono_dup_array_type (image
, o
->data
.array
);
4289 } else if (o
->type
== MONO_TYPE_FNPTR
) {
4290 /*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
4291 r
->data
.method
= mono_metadata_signature_deep_dup (image
, o
->data
.method
);
4297 mono_signature_hash (MonoMethodSignature
*sig
)
4299 guint i
, res
= sig
->ret
->type
;
4301 for (i
= 0; i
< sig
->param_count
; i
++)
4302 res
= (res
<< 5) - res
+ mono_type_hash (sig
->params
[i
]);
4308 * mono_metadata_encode_value:
4309 * @value: value to encode
4310 * @buf: buffer where to write the compressed representation
4311 * @endbuf: pointer updated to point at the end of the encoded output
4313 * Encodes the value @value in the compressed representation used
4314 * in metadata and stores the result in @buf. @buf needs to be big
4315 * enough to hold the data (4 bytes).
4318 mono_metadata_encode_value (guint32 value
, char *buf
, char **endbuf
)
4324 else if (value
< 0x4000) {
4325 p
[0] = 0x80 | (value
>> 8);
4326 p
[1] = value
& 0xff;
4329 p
[0] = (value
>> 24) | 0xc0;
4330 p
[1] = (value
>> 16) & 0xff;
4331 p
[2] = (value
>> 8) & 0xff;
4332 p
[3] = value
& 0xff;
4340 * mono_metadata_field_info:
4341 * @meta: the Image the field is defined in
4342 * @index: the index in the field table representing the field
4343 * @offset: a pointer to an integer where to store the offset that
4344 * may have been specified for the field in a FieldLayout table
4345 * @rva: a pointer to the RVA of the field data in the image that
4346 * may have been defined in a FieldRVA table
4347 * @marshal_spec: a pointer to the marshal spec that may have been
4348 * defined for the field in a FieldMarshal table.
4350 * Gather info for field @index that may have been defined in the FieldLayout,
4351 * FieldRVA and FieldMarshal tables.
4352 * Either of offset, rva and marshal_spec can be NULL if you're not interested
4356 mono_metadata_field_info (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
4357 MonoMarshalSpec
**marshal_spec
)
4359 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, FALSE
);
4363 mono_metadata_field_info_with_mempool (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
4364 MonoMarshalSpec
**marshal_spec
)
4366 mono_metadata_field_info_full (meta
, index
, offset
, rva
, marshal_spec
, TRUE
);
4370 mono_metadata_field_info_full (MonoImage
*meta
, guint32 index
, guint32
*offset
, guint32
*rva
,
4371 MonoMarshalSpec
**marshal_spec
, gboolean alloc_from_image
)
4373 MonoTableInfo
*tdef
;
4376 loc
.idx
= index
+ 1;
4377 if (meta
->uncompressed_metadata
)
4378 loc
.idx
= search_ptr_table (meta
, MONO_TABLE_FIELD_POINTER
, loc
.idx
);
4381 tdef
= &meta
->tables
[MONO_TABLE_FIELDLAYOUT
];
4383 loc
.col_idx
= MONO_FIELD_LAYOUT_FIELD
;
4386 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4387 *offset
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_LAYOUT_OFFSET
);
4389 *offset
= (guint32
)-1;
4393 tdef
= &meta
->tables
[MONO_TABLE_FIELDRVA
];
4395 loc
.col_idx
= MONO_FIELD_RVA_FIELD
;
4398 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4400 * LAMESPEC: There is no signature, no nothing, just the raw data.
4402 *rva
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_RVA_RVA
);
4410 if ((p
= mono_metadata_get_marshal_info (meta
, index
, TRUE
))) {
4411 *marshal_spec
= mono_metadata_parse_marshal_spec_full (alloc_from_image
? meta
: NULL
, p
);
4418 * mono_metadata_get_constant_index:
4419 * @meta: the Image the field is defined in
4420 * @index: the token that may have a row defined in the constants table
4421 * @hint: possible position for the row
4423 * @token must be a FieldDef, ParamDef or PropertyDef token.
4425 * Returns: the index into the Constants table or 0 if not found.
4428 mono_metadata_get_constant_index (MonoImage
*meta
, guint32 token
, guint32 hint
)
4430 MonoTableInfo
*tdef
;
4432 guint32 index
= mono_metadata_token_index (token
);
4434 tdef
= &meta
->tables
[MONO_TABLE_CONSTANT
];
4435 index
<<= MONO_HASCONSTANT_BITS
;
4436 switch (mono_metadata_token_table (token
)) {
4437 case MONO_TABLE_FIELD
:
4438 index
|= MONO_HASCONSTANT_FIEDDEF
;
4440 case MONO_TABLE_PARAM
:
4441 index
|= MONO_HASCONSTANT_PARAM
;
4443 case MONO_TABLE_PROPERTY
:
4444 index
|= MONO_HASCONSTANT_PROPERTY
;
4447 g_warning ("Not a valid token for the constant table: 0x%08x", token
);
4451 loc
.col_idx
= MONO_CONSTANT_PARENT
;
4454 /* FIXME: Index translation */
4456 if ((hint
> 0) && (hint
< tdef
->rows
) && (mono_metadata_decode_row_col (tdef
, hint
- 1, MONO_CONSTANT_PARENT
) == index
))
4459 if (tdef
->base
&& bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
)) {
4460 return loc
.result
+ 1;
4466 * mono_metadata_events_from_typedef:
4467 * @meta: metadata context
4468 * @index: 0-based index (in the TypeDef table) describing a type
4470 * Returns: the 0-based index in the Event table for the events in the
4471 * type. The last event that belongs to the type (plus 1) is stored
4472 * in the @end_idx pointer.
4475 mono_metadata_events_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
4479 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_EVENTMAP
];
4487 loc
.col_idx
= MONO_EVENT_MAP_PARENT
;
4488 loc
.idx
= index
+ 1;
4490 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4493 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_EVENT_MAP_EVENTLIST
);
4494 if (loc
.result
+ 1 < tdef
->rows
) {
4495 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_EVENT_MAP_EVENTLIST
) - 1;
4497 end
= meta
->tables
[MONO_TABLE_EVENT
].rows
;
4505 * mono_metadata_methods_from_event:
4506 * @meta: metadata context
4507 * @index: 0-based index (in the Event table) describing a event
4509 * Returns: the 0-based index in the MethodDef table for the methods in the
4510 * event. The last method that belongs to the event (plus 1) is stored
4511 * in the @end_idx pointer.
4514 mono_metadata_methods_from_event (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
4518 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
4519 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
4525 if (meta
->uncompressed_metadata
)
4526 index
= search_ptr_table (meta
, MONO_TABLE_EVENT_POINTER
, index
+ 1) - 1;
4529 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
4530 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
; /* Method association coded index */
4532 if (!bsearch (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
4537 * We may end up in the middle of the rows...
4540 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
4546 while (end
< msemt
->rows
) {
4547 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
4548 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
4557 * mono_metadata_properties_from_typedef:
4558 * @meta: metadata context
4559 * @index: 0-based index (in the TypeDef table) describing a type
4561 * Returns: the 0-based index in the Property table for the properties in the
4562 * type. The last property that belongs to the type (plus 1) is stored
4563 * in the @end_idx pointer.
4566 mono_metadata_properties_from_typedef (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
4570 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_PROPERTYMAP
];
4578 loc
.col_idx
= MONO_PROPERTY_MAP_PARENT
;
4579 loc
.idx
= index
+ 1;
4581 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4584 start
= mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_PROPERTY_MAP_PROPERTY_LIST
);
4585 if (loc
.result
+ 1 < tdef
->rows
) {
4586 end
= mono_metadata_decode_row_col (tdef
, loc
.result
+ 1, MONO_PROPERTY_MAP_PROPERTY_LIST
) - 1;
4588 end
= meta
->tables
[MONO_TABLE_PROPERTY
].rows
;
4596 * mono_metadata_methods_from_property:
4597 * @meta: metadata context
4598 * @index: 0-based index (in the PropertyDef table) describing a property
4600 * Returns: the 0-based index in the MethodDef table for the methods in the
4601 * property. The last method that belongs to the property (plus 1) is stored
4602 * in the @end_idx pointer.
4605 mono_metadata_methods_from_property (MonoImage
*meta
, guint32 index
, guint
*end_idx
)
4609 guint32 cols
[MONO_METHOD_SEMA_SIZE
];
4610 MonoTableInfo
*msemt
= &meta
->tables
[MONO_TABLE_METHODSEMANTICS
];
4616 if (meta
->uncompressed_metadata
)
4617 index
= search_ptr_table (meta
, MONO_TABLE_PROPERTY_POINTER
, index
+ 1) - 1;
4620 loc
.col_idx
= MONO_METHOD_SEMA_ASSOCIATION
;
4621 loc
.idx
= ((index
+ 1) << MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
; /* Method association coded index */
4623 if (!bsearch (&loc
, msemt
->base
, msemt
->rows
, msemt
->row_size
, table_locator
))
4628 * We may end up in the middle of the rows...
4631 if (loc
.idx
== mono_metadata_decode_row_col (msemt
, start
- 1, MONO_METHOD_SEMA_ASSOCIATION
))
4637 while (end
< msemt
->rows
) {
4638 mono_metadata_decode_row (msemt
, end
, cols
, MONO_METHOD_SEMA_SIZE
);
4639 if (cols
[MONO_METHOD_SEMA_ASSOCIATION
] != loc
.idx
)
4648 mono_metadata_implmap_from_method (MonoImage
*meta
, guint32 method_idx
)
4651 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_IMPLMAP
];
4656 /* No index translation seems to be needed */
4659 loc
.col_idx
= MONO_IMPLMAP_MEMBER
;
4660 loc
.idx
= ((method_idx
+ 1) << MONO_MEMBERFORWD_BITS
) | MONO_MEMBERFORWD_METHODDEF
;
4662 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
4665 return loc
.result
+ 1;
4669 * @image: context where the image is created
4670 * @type_spec: typespec token
4672 * Creates a MonoType representing the TypeSpec indexed by the @type_spec
4676 mono_type_create_from_typespec (MonoImage
*image
, guint32 type_spec
)
4678 guint32 idx
= mono_metadata_token_index (type_spec
);
4680 guint32 cols
[MONO_TYPESPEC_SIZE
];
4683 MonoType
*type
, *type2
;
4684 MonoType stack_type
;
4686 mono_loader_lock ();
4688 type
= g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
4690 mono_loader_unlock ();
4694 t
= &image
->tables
[MONO_TABLE_TYPESPEC
];
4696 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPESPEC_SIZE
);
4697 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_TYPESPEC_SIGNATURE
]);
4699 if (!mono_verifier_verify_typespec_signature (image
, cols
[MONO_TYPESPEC_SIGNATURE
], NULL
)) {
4700 mono_loader_unlock ();
4704 len
= mono_metadata_decode_value (ptr
, &ptr
);
4707 memset (type
, 0, MONO_SIZEOF_TYPE
);
4709 if (*ptr
== MONO_TYPE_BYREF
) {
4714 if (!do_mono_metadata_parse_type (type
, image
, NULL
, ptr
, &ptr
)) {
4715 mono_loader_unlock ();
4719 type2
= g_hash_table_lookup (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
));
4722 mono_loader_unlock ();
4726 type2
= mono_image_alloc (image
, MONO_SIZEOF_TYPE
);
4727 memcpy (type2
, type
, MONO_SIZEOF_TYPE
);
4728 g_hash_table_insert (image
->typespec_cache
, GUINT_TO_POINTER (type_spec
), type2
);
4730 mono_loader_unlock ();
4737 mono_image_strndup (MonoImage
*image
, const char *data
, guint len
)
4741 return g_strndup (data
, len
);
4742 res
= mono_image_alloc (image
, len
+ 1);
4743 memcpy (res
, data
, len
);
4749 mono_metadata_parse_marshal_spec (MonoImage
*image
, const char *ptr
)
4751 return mono_metadata_parse_marshal_spec_full (NULL
, ptr
);
4755 mono_metadata_parse_marshal_spec_full (MonoImage
*image
, const char *ptr
)
4757 MonoMarshalSpec
*res
;
4759 const char *start
= ptr
;
4761 /* fixme: this is incomplete, but I cant find more infos in the specs */
4764 res
= mono_image_alloc0 (image
, sizeof (MonoMarshalSpec
));
4766 res
= g_new0 (MonoMarshalSpec
, 1);
4768 len
= mono_metadata_decode_value (ptr
, &ptr
);
4769 res
->native
= *ptr
++;
4771 if (res
->native
== MONO_NATIVE_LPARRAY
) {
4772 res
->data
.array_data
.param_num
= -1;
4773 res
->data
.array_data
.num_elem
= -1;
4774 res
->data
.array_data
.elem_mult
= -1;
4776 if (ptr
- start
<= len
)
4777 res
->data
.array_data
.elem_type
= *ptr
++;
4778 if (ptr
- start
<= len
)
4779 res
->data
.array_data
.param_num
= mono_metadata_decode_value (ptr
, &ptr
);
4780 if (ptr
- start
<= len
)
4781 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
4782 if (ptr
- start
<= len
) {
4784 * LAMESPEC: Older spec versions say this parameter comes before
4785 * num_elem. Never spec versions don't talk about elem_mult at
4786 * all, but csc still emits it, and it is used to distinguish
4787 * between param_num being 0, and param_num being omitted.
4788 * So if (param_num == 0) && (num_elem > 0), then
4789 * elem_mult == 0 -> the array size is num_elem
4790 * elem_mult == 1 -> the array size is @param_num + num_elem
4792 res
->data
.array_data
.elem_mult
= mono_metadata_decode_value (ptr
, &ptr
);
4796 if (res
->native
== MONO_NATIVE_BYVALTSTR
) {
4797 if (ptr
- start
<= len
)
4798 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
4801 if (res
->native
== MONO_NATIVE_BYVALARRAY
) {
4802 if (ptr
- start
<= len
)
4803 res
->data
.array_data
.num_elem
= mono_metadata_decode_value (ptr
, &ptr
);
4806 if (res
->native
== MONO_NATIVE_CUSTOM
) {
4807 /* skip unused type guid */
4808 len
= mono_metadata_decode_value (ptr
, &ptr
);
4810 /* skip unused native type name */
4811 len
= mono_metadata_decode_value (ptr
, &ptr
);
4813 /* read custom marshaler type name */
4814 len
= mono_metadata_decode_value (ptr
, &ptr
);
4815 res
->data
.custom_data
.custom_name
= mono_image_strndup (image
, ptr
, len
);
4817 /* read cookie string */
4818 len
= mono_metadata_decode_value (ptr
, &ptr
);
4819 res
->data
.custom_data
.cookie
= mono_image_strndup (image
, ptr
, len
);
4822 if (res
->native
== MONO_NATIVE_SAFEARRAY
) {
4823 res
->data
.safearray_data
.elem_type
= 0;
4824 res
->data
.safearray_data
.num_elem
= 0;
4825 if (ptr
- start
<= len
)
4826 res
->data
.safearray_data
.elem_type
= *ptr
++;
4827 if (ptr
- start
<= len
)
4828 res
->data
.safearray_data
.num_elem
= *ptr
++;
4834 mono_metadata_free_marshal_spec (MonoMarshalSpec
*spec
)
4836 if (spec
->native
== MONO_NATIVE_CUSTOM
) {
4837 g_free (spec
->data
.custom_data
.custom_name
);
4838 g_free (spec
->data
.custom_data
.cookie
);
4844 * mono_type_to_unmanaged:
4846 * Returns: A MonoMarshalNative enumeration value (MONO_NATIVE_) value
4847 * describing the underlying native reprensetation of the type.
4849 * In addition the value pointed by
4850 * "conv" will contain the kind of marshalling required for this
4851 * particular type one of the MONO_MARSHAL_CONV_ enumeration values.
4854 mono_type_to_unmanaged (MonoType
*type
, MonoMarshalSpec
*mspec
, gboolean as_field
,
4855 gboolean unicode
, MonoMarshalConv
*conv
)
4857 MonoMarshalConv dummy_conv
;
4863 *conv
= MONO_MARSHAL_CONV_NONE
;
4866 return MONO_NATIVE_UINT
;
4870 case MONO_TYPE_BOOLEAN
:
4872 switch (mspec
->native
) {
4873 case MONO_NATIVE_VARIANTBOOL
:
4874 *conv
= MONO_MARSHAL_CONV_BOOL_VARIANTBOOL
;
4875 return MONO_NATIVE_VARIANTBOOL
;
4876 case MONO_NATIVE_BOOLEAN
:
4877 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
4878 return MONO_NATIVE_BOOLEAN
;
4879 case MONO_NATIVE_I1
:
4880 case MONO_NATIVE_U1
:
4881 return mspec
->native
;
4883 g_error ("cant marshal bool to native type %02x", mspec
->native
);
4886 *conv
= MONO_MARSHAL_CONV_BOOL_I4
;
4887 return MONO_NATIVE_BOOLEAN
;
4888 case MONO_TYPE_CHAR
: return MONO_NATIVE_U2
;
4889 case MONO_TYPE_I1
: return MONO_NATIVE_I1
;
4890 case MONO_TYPE_U1
: return MONO_NATIVE_U1
;
4891 case MONO_TYPE_I2
: return MONO_NATIVE_I2
;
4892 case MONO_TYPE_U2
: return MONO_NATIVE_U2
;
4893 case MONO_TYPE_I4
: return MONO_NATIVE_I4
;
4894 case MONO_TYPE_U4
: return MONO_NATIVE_U4
;
4895 case MONO_TYPE_I8
: return MONO_NATIVE_I8
;
4896 case MONO_TYPE_U8
: return MONO_NATIVE_U8
;
4897 case MONO_TYPE_R4
: return MONO_NATIVE_R4
;
4898 case MONO_TYPE_R8
: return MONO_NATIVE_R8
;
4899 case MONO_TYPE_STRING
:
4901 switch (mspec
->native
) {
4902 case MONO_NATIVE_BSTR
:
4903 *conv
= MONO_MARSHAL_CONV_STR_BSTR
;
4904 return MONO_NATIVE_BSTR
;
4905 case MONO_NATIVE_LPSTR
:
4906 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
4907 return MONO_NATIVE_LPSTR
;
4908 case MONO_NATIVE_LPWSTR
:
4909 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
4910 return MONO_NATIVE_LPWSTR
;
4911 case MONO_NATIVE_LPTSTR
:
4912 *conv
= MONO_MARSHAL_CONV_STR_LPTSTR
;
4913 return MONO_NATIVE_LPTSTR
;
4914 case MONO_NATIVE_ANSIBSTR
:
4915 *conv
= MONO_MARSHAL_CONV_STR_ANSIBSTR
;
4916 return MONO_NATIVE_ANSIBSTR
;
4917 case MONO_NATIVE_TBSTR
:
4918 *conv
= MONO_MARSHAL_CONV_STR_TBSTR
;
4919 return MONO_NATIVE_TBSTR
;
4920 case MONO_NATIVE_BYVALTSTR
:
4922 *conv
= MONO_MARSHAL_CONV_STR_BYVALWSTR
;
4924 *conv
= MONO_MARSHAL_CONV_STR_BYVALSTR
;
4925 return MONO_NATIVE_BYVALTSTR
;
4927 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
);
4931 *conv
= MONO_MARSHAL_CONV_STR_LPWSTR
;
4932 return MONO_NATIVE_LPWSTR
;
4935 *conv
= MONO_MARSHAL_CONV_STR_LPSTR
;
4936 return MONO_NATIVE_LPSTR
;
4938 case MONO_TYPE_PTR
: return MONO_NATIVE_UINT
;
4939 case MONO_TYPE_VALUETYPE
: /*FIXME*/
4940 if (type
->data
.klass
->enumtype
) {
4941 t
= mono_class_enum_basetype (type
->data
.klass
)->type
;
4944 if (type
->data
.klass
== mono_defaults
.handleref_class
){
4945 *conv
= MONO_MARSHAL_CONV_HANDLEREF
;
4946 return MONO_NATIVE_INT
;
4948 return MONO_NATIVE_STRUCT
;
4949 case MONO_TYPE_SZARRAY
:
4950 case MONO_TYPE_ARRAY
:
4952 switch (mspec
->native
) {
4953 case MONO_NATIVE_BYVALARRAY
:
4954 if ((type
->data
.klass
->element_class
== mono_defaults
.char_class
) && !unicode
)
4955 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY
;
4957 *conv
= MONO_MARSHAL_CONV_ARRAY_BYVALARRAY
;
4958 return MONO_NATIVE_BYVALARRAY
;
4959 case MONO_NATIVE_SAFEARRAY
:
4960 *conv
= MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
;
4961 return MONO_NATIVE_SAFEARRAY
;
4962 case MONO_NATIVE_LPARRAY
:
4963 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
4964 return MONO_NATIVE_LPARRAY
;
4966 g_error ("cant marshal array as native type %02x", mspec
->native
);
4970 *conv
= MONO_MARSHAL_CONV_ARRAY_LPARRAY
;
4971 return MONO_NATIVE_LPARRAY
;
4972 case MONO_TYPE_I
: return MONO_NATIVE_INT
;
4973 case MONO_TYPE_U
: return MONO_NATIVE_UINT
;
4974 case MONO_TYPE_CLASS
:
4975 case MONO_TYPE_OBJECT
: {
4976 /* FIXME : we need to handle ArrayList and StringBuilder here, probably */
4978 switch (mspec
->native
) {
4979 case MONO_NATIVE_STRUCT
:
4980 return MONO_NATIVE_STRUCT
;
4981 case MONO_NATIVE_CUSTOM
:
4982 return MONO_NATIVE_CUSTOM
;
4983 case MONO_NATIVE_INTERFACE
:
4984 *conv
= MONO_MARSHAL_CONV_OBJECT_INTERFACE
;
4985 return MONO_NATIVE_INTERFACE
;
4986 case MONO_NATIVE_IDISPATCH
:
4987 *conv
= MONO_MARSHAL_CONV_OBJECT_IDISPATCH
;
4988 return MONO_NATIVE_IDISPATCH
;
4989 case MONO_NATIVE_IUNKNOWN
:
4990 *conv
= MONO_MARSHAL_CONV_OBJECT_IUNKNOWN
;
4991 return MONO_NATIVE_IUNKNOWN
;
4992 case MONO_NATIVE_FUNC
:
4993 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
4994 type
->data
.klass
== mono_defaults
.delegate_class
||
4995 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
4996 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
4997 return MONO_NATIVE_FUNC
;
5001 g_error ("cant marshal object as native type %02x", mspec
->native
);
5004 if (t
== MONO_TYPE_CLASS
&& (type
->data
.klass
== mono_defaults
.multicastdelegate_class
||
5005 type
->data
.klass
== mono_defaults
.delegate_class
||
5006 type
->data
.klass
->parent
== mono_defaults
.multicastdelegate_class
)) {
5007 *conv
= MONO_MARSHAL_CONV_DEL_FTN
;
5008 return MONO_NATIVE_FUNC
;
5010 if (mono_defaults
.safehandle_class
&& type
->data
.klass
== mono_defaults
.safehandle_class
){
5011 *conv
= MONO_MARSHAL_CONV_SAFEHANDLE
;
5012 return MONO_NATIVE_INT
;
5014 *conv
= MONO_MARSHAL_CONV_OBJECT_STRUCT
;
5015 return MONO_NATIVE_STRUCT
;
5017 case MONO_TYPE_FNPTR
: return MONO_NATIVE_FUNC
;
5018 case MONO_TYPE_GENERICINST
:
5019 type
= &type
->data
.generic_class
->container_class
->byval_arg
;
5022 case MONO_TYPE_TYPEDBYREF
:
5024 g_error ("type 0x%02x not handled in marshal", t
);
5026 return MONO_NATIVE_MAX
;
5030 mono_metadata_get_marshal_info (MonoImage
*meta
, guint32 idx
, gboolean is_field
)
5033 MonoTableInfo
*tdef
= &meta
->tables
[MONO_TABLE_FIELDMARSHAL
];
5039 loc
.col_idx
= MONO_FIELD_MARSHAL_PARENT
;
5040 loc
.idx
= ((idx
+ 1) << MONO_HAS_FIELD_MARSHAL_BITS
) | (is_field
? MONO_HAS_FIELD_MARSHAL_FIELDSREF
: MONO_HAS_FIELD_MARSHAL_PARAMDEF
);
5042 /* FIXME: Index translation */
5044 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5047 return mono_metadata_blob_heap (meta
, mono_metadata_decode_row_col (tdef
, loc
.result
, MONO_FIELD_MARSHAL_NATIVE_TYPE
));
5051 method_from_method_def_or_ref (MonoImage
*m
, guint32 tok
, MonoGenericContext
*context
)
5053 guint32 idx
= tok
>> MONO_METHODDEFORREF_BITS
;
5055 switch (tok
& MONO_METHODDEFORREF_MASK
) {
5056 case MONO_METHODDEFORREF_METHODDEF
:
5057 return mono_get_method_full (m
, MONO_TOKEN_METHOD_DEF
| idx
, NULL
, context
);
5058 case MONO_METHODDEFORREF_METHODREF
:
5059 return mono_get_method_full (m
, MONO_TOKEN_MEMBER_REF
| idx
, NULL
, context
);
5061 g_assert_not_reached ();
5066 * mono_class_get_overrides_full:
5068 * Return the method overrides belonging to class @type_token in @overrides, and
5069 * the number of overrides in @num_overrides.
5071 * Returns: TRUE on success, FALSE on failure.
5074 mono_class_get_overrides_full (MonoImage
*image
, guint32 type_token
, MonoMethod
***overrides
, gint32
*num_overrides
,
5075 MonoGenericContext
*generic_context
)
5078 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_METHODIMPL
];
5081 guint32 cols
[MONO_METHODIMPL_SIZE
];
5082 MonoMethod
**result
;
5093 loc
.col_idx
= MONO_METHODIMPL_CLASS
;
5094 loc
.idx
= mono_metadata_token_index (type_token
);
5096 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5102 * We may end up in the middle of the rows...
5105 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, start
- 1, MONO_METHODIMPL_CLASS
))
5110 while (end
< tdef
->rows
) {
5111 if (loc
.idx
== mono_metadata_decode_row_col (tdef
, end
, MONO_METHODIMPL_CLASS
))
5117 result
= g_new (MonoMethod
*, num
* 2);
5118 for (i
= 0; i
< num
; ++i
) {
5121 mono_metadata_decode_row (tdef
, start
+ i
, cols
, MONO_METHODIMPL_SIZE
);
5122 method
= method_from_method_def_or_ref (
5123 image
, cols
[MONO_METHODIMPL_DECLARATION
], generic_context
);
5126 result
[i
* 2] = method
;
5127 method
= method_from_method_def_or_ref (
5128 image
, cols
[MONO_METHODIMPL_BODY
], generic_context
);
5131 result
[i
* 2 + 1] = method
;
5134 *overrides
= result
;
5136 *num_overrides
= num
;
5141 * mono_guid_to_string:
5143 * Converts a 16 byte Microsoft GUID to the standard string representation.
5146 mono_guid_to_string (const guint8
*guid
)
5148 return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
5149 guid
[3], guid
[2], guid
[1], guid
[0],
5153 guid
[10], guid
[11], guid
[12], guid
[13], guid
[14], guid
[15]);
5157 get_constraints (MonoImage
*image
, int owner
, MonoClass
***constraints
, MonoGenericContainer
*container
)
5159 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
5160 guint32 cols
[MONO_GENPARCONSTRAINT_SIZE
];
5161 guint32 i
, token
, found
;
5162 MonoClass
*klass
, **res
;
5163 GSList
*cons
= NULL
, *tmp
;
5164 MonoGenericContext
*context
= &container
->context
;
5166 *constraints
= NULL
;
5168 for (i
= 0; i
< tdef
->rows
; ++i
) {
5169 mono_metadata_decode_row (tdef
, i
, cols
, MONO_GENPARCONSTRAINT_SIZE
);
5170 if (cols
[MONO_GENPARCONSTRAINT_GENERICPAR
] == owner
) {
5171 token
= mono_metadata_token_from_dor (cols
[MONO_GENPARCONSTRAINT_CONSTRAINT
]);
5172 klass
= mono_class_get_full (image
, token
, context
);
5174 g_slist_free (cons
);
5177 cons
= g_slist_append (cons
, klass
);
5180 /* contiguous list finished */
5187 res
= g_new0 (MonoClass
*, found
+ 1);
5188 for (i
= 0, tmp
= cons
; i
< found
; ++i
, tmp
= tmp
->next
) {
5189 res
[i
] = tmp
->data
;
5191 g_slist_free (cons
);
5197 * mono_metadata_get_generic_param_row:
5200 * @token: TypeOrMethodDef token, owner for GenericParam
5201 * @owner: coded token, set on return
5203 * Returns: 1-based row-id in the GenericParam table whose
5204 * owner is @token. 0 if not found.
5207 mono_metadata_get_generic_param_row (MonoImage
*image
, guint32 token
, guint32
*owner
)
5209 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
5216 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPEDEF
)
5217 *owner
= MONO_TYPEORMETHOD_TYPE
;
5218 else if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
5219 *owner
= MONO_TYPEORMETHOD_METHOD
;
5221 g_error ("wrong token %x to get_generic_param_row", token
);
5224 *owner
|= mono_metadata_token_index (token
) << MONO_TYPEORMETHOD_BITS
;
5227 loc
.col_idx
= MONO_GENERICPARAM_OWNER
;
5230 if (!bsearch (&loc
, tdef
->base
, tdef
->rows
, tdef
->row_size
, table_locator
))
5233 /* Find the first entry by searching backwards */
5234 while ((loc
.result
> 0) && (mono_metadata_decode_row_col (tdef
, loc
.result
- 1, MONO_GENERICPARAM_OWNER
) == loc
.idx
))
5237 return loc
.result
+ 1;
5241 mono_metadata_has_generic_params (MonoImage
*image
, guint32 token
)
5244 return mono_metadata_get_generic_param_row (image
, token
, &owner
);
5248 mono_metadata_load_generic_param_constraints_full (MonoImage
*image
, guint32 token
,
5249 MonoGenericContainer
*container
)
5252 guint32 start_row
, i
, owner
;
5253 if (! (start_row
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
5255 for (i
= 0; i
< container
->type_argc
; i
++) {
5256 if (!get_constraints (image
, start_row
+ i
, &mono_generic_container_get_param_info (container
, i
)->constraints
, container
))
5263 * mono_metadata_load_generic_param_constraints:
5265 * @image: metadata context
5266 * @token: metadata token to load the contraints, can be methodef or typedef.
5267 * @container: generic container to load into.
5269 * Load the generic parameter constraints for the newly created generic type or method
5270 * represented by @token and @container. The @container is the new container which has
5271 * been returned by a call to mono_metadata_load_generic_params() with this @token.
5274 mono_metadata_load_generic_param_constraints (MonoImage
*image
, guint32 token
,
5275 MonoGenericContainer
*container
)
5277 mono_metadata_load_generic_param_constraints_full (image
, token
, container
);
5278 /*FIXME this function can potentially exit with a pending loader error and cause all sort of havok */
5282 * mono_metadata_load_generic_params:
5284 * Load the type parameters from the type or method definition @token.
5286 * Use this method after parsing a type or method definition to figure out whether it's a generic
5287 * type / method. When parsing a method definition, @parent_container points to the generic container
5288 * of the current class, if any.
5290 * Note: This method does not load the constraints: for typedefs, this has to be done after fully
5291 * creating the type.
5293 * Returns: NULL if @token is not a generic type or method definition or the new generic container.
5295 * LOCKING: Acquires the loader lock
5298 MonoGenericContainer
*
5299 mono_metadata_load_generic_params (MonoImage
*image
, guint32 token
, MonoGenericContainer
*parent_container
)
5301 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_GENERICPARAM
];
5302 guint32 cols
[MONO_GENERICPARAM_SIZE
];
5303 guint32 i
, owner
= 0, n
;
5304 MonoGenericContainer
*container
;
5305 MonoGenericParamFull
*params
;
5306 MonoGenericContext
*context
;
5308 if (!(i
= mono_metadata_get_generic_param_row (image
, token
, &owner
)))
5310 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
5313 container
= mono_image_alloc0 (image
, sizeof (MonoGenericContainer
));
5314 container
->image
= image
;
5317 params
= g_realloc (params
, sizeof (MonoGenericParamFull
) * n
);
5318 memset (¶ms
[n
- 1], 0, sizeof (MonoGenericParamFull
));
5319 params
[n
- 1].param
.owner
= container
;
5320 params
[n
- 1].param
.num
= cols
[MONO_GENERICPARAM_NUMBER
];
5321 params
[n
- 1].info
.token
= i
| MONO_TOKEN_GENERIC_PARAM
;
5322 params
[n
- 1].info
.flags
= cols
[MONO_GENERICPARAM_FLAGS
];
5323 params
[n
- 1].info
.name
= mono_metadata_string_heap (image
, cols
[MONO_GENERICPARAM_NAME
]);
5324 if (params
[n
- 1].param
.num
!= n
- 1)
5325 g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i
);
5326 if (++i
> tdef
->rows
)
5328 mono_metadata_decode_row (tdef
, i
- 1, cols
, MONO_GENERICPARAM_SIZE
);
5329 } while (cols
[MONO_GENERICPARAM_OWNER
] == owner
);
5331 container
->type_argc
= n
;
5332 container
->type_params
= mono_image_alloc0 (image
, sizeof (MonoGenericParamFull
) * n
);
5333 memcpy (container
->type_params
, params
, sizeof (MonoGenericParamFull
) * n
);
5335 container
->parent
= parent_container
;
5337 if (mono_metadata_token_table (token
) == MONO_TABLE_METHOD
)
5338 container
->is_method
= 1;
5340 g_assert (container
->parent
== NULL
|| container
->is_method
);
5342 context
= &container
->context
;
5343 if (container
->is_method
) {
5344 context
->class_inst
= container
->parent
? container
->parent
->context
.class_inst
: NULL
;
5345 context
->method_inst
= mono_get_shared_generic_inst (container
);
5347 context
->class_inst
= mono_get_shared_generic_inst (container
);
5354 mono_get_shared_generic_inst (MonoGenericContainer
*container
)
5356 MonoType
**type_argv
;
5358 MonoGenericInst
*nginst
;
5361 type_argv
= g_new0 (MonoType
*, container
->type_argc
);
5362 helper
= g_new0 (MonoType
, container
->type_argc
);
5364 for (i
= 0; i
< container
->type_argc
; i
++) {
5365 MonoType
*t
= &helper
[i
];
5367 t
->type
= container
->is_method
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
5368 t
->data
.generic_param
= mono_generic_container_get_param (container
, i
);
5373 nginst
= mono_metadata_get_generic_inst (container
->type_argc
, type_argv
);
5382 * mono_type_is_byref:
5383 * @type: the MonoType operated on
5385 * Returns: #TRUE if @type represents a type passed by reference,
5389 mono_type_is_byref (MonoType
*type
)
5395 * mono_type_get_type:
5396 * @type: the MonoType operated on
5398 * Returns: the IL type value for @type. This is one of the MonoTypeEnum
5399 * enum members like MONO_TYPE_I4 or MONO_TYPE_STRING.
5402 mono_type_get_type (MonoType
*type
)
5408 * mono_type_get_signature:
5409 * @type: the MonoType operated on
5411 * It is only valid to call this function if @type is a MONO_TYPE_FNPTR.
5413 * Returns: the MonoMethodSignature pointer that describes the signature
5414 * of the function pointer @type represents.
5416 MonoMethodSignature
*
5417 mono_type_get_signature (MonoType
*type
)
5419 g_assert (type
->type
== MONO_TYPE_FNPTR
);
5420 return type
->data
.method
;
5424 * mono_type_get_class:
5425 * @type: the MonoType operated on
5427 * It is only valid to call this function if @type is a MONO_TYPE_CLASS or a
5428 * MONO_TYPE_VALUETYPE. For more general functionality, use mono_class_from_mono_type (),
5431 * Returns: the MonoClass pointer that describes the class that @type represents.
5434 mono_type_get_class (MonoType
*type
)
5436 /* FIXME: review the runtime users before adding the assert here */
5437 return type
->data
.klass
;
5441 * mono_type_get_array_type:
5442 * @type: the MonoType operated on
5444 * It is only valid to call this function if @type is a MONO_TYPE_ARRAY.
5446 * Returns: a MonoArrayType struct describing the array type that @type
5447 * represents. The info includes details such as rank, array element type
5448 * and the sizes and bounds of multidimensional arrays.
5451 mono_type_get_array_type (MonoType
*type
)
5453 return type
->data
.array
;
5457 * mono_type_get_ptr_type:
5458 * @type: the MonoType operated on
5460 * It is only valid to call this function if @type is a MONO_TYPE_PTR.
5463 * Returns: the MonoType pointer that describes the type that @type
5464 * represents a pointer to.
5467 mono_type_get_ptr_type (MonoType
*type
)
5469 g_assert (type
->type
== MONO_TYPE_PTR
);
5470 return type
->data
.type
;
5474 mono_type_get_modifiers (MonoType
*type
, gboolean
*is_required
, gpointer
*iter
)
5476 /* FIXME: implement */
5481 mono_signature_get_return_type (MonoMethodSignature
*sig
)
5487 mono_signature_get_params (MonoMethodSignature
*sig
, gpointer
*iter
)
5493 /* start from the first */
5494 if (sig
->param_count
) {
5495 *iter
= &sig
->params
[0];
5496 return sig
->params
[0];
5504 if (type
< &sig
->params
[sig
->param_count
]) {
5512 mono_signature_get_param_count (MonoMethodSignature
*sig
)
5514 return sig
->param_count
;
5518 mono_signature_get_call_conv (MonoMethodSignature
*sig
)
5520 return sig
->call_convention
;
5524 mono_signature_vararg_start (MonoMethodSignature
*sig
)
5526 return sig
->sentinelpos
;
5530 mono_signature_is_instance (MonoMethodSignature
*sig
)
5532 return sig
->hasthis
;
5536 mono_signature_explicit_this (MonoMethodSignature
*sig
)
5538 return sig
->explicit_this
;
5541 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
5543 mono_aligned_addr_hash (gconstpointer ptr
)
5545 return GPOINTER_TO_UINT (ptr
) >> 3;
5549 * If @field belongs to an inflated generic class, return the corresponding field of the
5550 * generic type definition class.
5553 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField
*field
)
5558 if (!field
->parent
->generic_class
)
5561 gtd
= field
->parent
->generic_class
->container_class
;
5562 offset
= field
- field
->parent
->fields
;
5563 return gtd
->fields
+ offset
;
5567 * If @event belongs to an inflated generic class, return the corresponding event of the
5568 * generic type definition class.
5571 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent
*event
)
5576 if (!event
->parent
->generic_class
)
5579 gtd
= event
->parent
->generic_class
->container_class
;
5580 offset
= event
- event
->parent
->ext
->events
;
5581 return gtd
->ext
->events
+ offset
;
5585 * If @property belongs to an inflated generic class, return the corresponding property of the
5586 * generic type definition class.
5589 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty
*property
)
5594 if (!property
->parent
->generic_class
)
5597 gtd
= property
->parent
->generic_class
->container_class
;
5598 offset
= property
- property
->parent
->ext
->properties
;
5599 return gtd
->ext
->properties
+ offset
;