1 /**
2  * \file
3  * Routines for accessing the metadata
4  *
5  * Authors:
6  *   Miguel de Icaza (miguel@ximian.com)
7  *   Paolo Molaro (lupus@ximian.com)
8  *
9  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13 
14 #include <config.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <glib.h>
19 #include "metadata.h"
20 #include "tabledefs.h"
21 #include "mono-endian.h"
22 #include "cil-coff.h"
23 #include "tokentype.h"
24 #include "class-internals.h"
25 #include "metadata-internals.h"
26 #include "verify-internals.h"
27 #include "class.h"
28 #include "marshal.h"
29 #include "debug-helpers.h"
30 #include "abi-details.h"
31 #include <mono/utils/mono-error-internals.h>
32 #include <mono/utils/bsearch.h>
33 #include <mono/utils/atomic.h>
34 #include <mono/utils/unlocked.h>
35 #include <mono/utils/mono-counters.h>
36 
37 static gint32 img_set_cache_hit, img_set_cache_miss, img_set_count;
38 
39 
40 /* Auxiliary structure used for caching inflated signatures */
41 typedef struct {
42 	MonoMethodSignature *sig;
43 	MonoGenericContext context;
44 } MonoInflatedMethodSignature;
45 
46 static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, gboolean transient,
47 					 const char *ptr, const char **rptr, MonoError *error);
48 
49 static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
50 static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
51 static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
52 static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
53 						    gboolean signature_only);
54 static void free_generic_inst (MonoGenericInst *ginst);
55 static void free_generic_class (MonoGenericClass *ginst);
56 static void free_inflated_method (MonoMethodInflated *method);
57 static void free_inflated_signature (MonoInflatedMethodSignature *sig);
58 static void mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva, MonoMarshalSpec **marshal_spec, gboolean alloc_from_image);
59 
60 /*
61  * This enumeration is used to describe the data types in the metadata
62  * tables
63  */
64 enum {
65 	MONO_MT_END,
66 
67 	/* Sized elements */
68 	MONO_MT_UINT32,
69 	MONO_MT_UINT16,
70 	MONO_MT_UINT8,
71 
72 	/* Index into Blob heap */
73 	MONO_MT_BLOB_IDX,
74 
75 	/* Index into String heap */
76 	MONO_MT_STRING_IDX,
77 
78 	/* GUID index */
79 	MONO_MT_GUID_IDX,
80 
81 	/* Pointer into a table */
82 	MONO_MT_TABLE_IDX,
83 
84 	/* HasConstant:Parent pointer (Param, Field or Property) */
85 	MONO_MT_CONST_IDX,
86 
87 	/* HasCustomAttribute index.  Indexes any table except CustomAttribute */
88 	MONO_MT_HASCAT_IDX,
89 
90 	/* CustomAttributeType encoded index */
91 	MONO_MT_CAT_IDX,
92 
93 	/* HasDeclSecurity index: TypeDef Method or Assembly */
94 	MONO_MT_HASDEC_IDX,
95 
96 	/* Implementation coded index: File, Export AssemblyRef */
97 	MONO_MT_IMPL_IDX,
98 
99 	/* HasFieldMarshal coded index: Field or Param table */
100 	MONO_MT_HFM_IDX,
101 
102 	/* MemberForwardedIndex: Field or Method */
103 	MONO_MT_MF_IDX,
104 
105 	/* TypeDefOrRef coded index: typedef, typeref, typespec */
106 	MONO_MT_TDOR_IDX,
107 
108 	/* MemberRefParent coded index: typeref, moduleref, method, memberref, typesepc, typedef */
109 	MONO_MT_MRP_IDX,
110 
111 	/* MethodDefOrRef coded index: Method or Member Ref table */
112 	MONO_MT_MDOR_IDX,
113 
114 	/* HasSemantic coded index: Event or Property */
115 	MONO_MT_HS_IDX,
116 
117 	/* ResolutionScope coded index: Module, ModuleRef, AssemblytRef, TypeRef */
118 	MONO_MT_RS_IDX,
119 
120 	/* CustomDebugInformation parent encoded index */
121 	MONO_MT_HASCUSTDEBUG_IDX
122 };
123 
124 const static unsigned char TableSchemas [] = {
125 #define ASSEMBLY_SCHEMA_OFFSET 0
126 	MONO_MT_UINT32,     /* "HashId" }, */
127 	MONO_MT_UINT16,     /* "Major" },  */
128 	MONO_MT_UINT16,     /* "Minor" }, */
129 	MONO_MT_UINT16,     /* "BuildNumber" }, */
130 	MONO_MT_UINT16,     /* "RevisionNumber" }, */
131 	MONO_MT_UINT32,     /* "Flags" }, */
132 	MONO_MT_BLOB_IDX,   /* "PublicKey" }, */
133 	MONO_MT_STRING_IDX, /* "Name" }, */
134 	MONO_MT_STRING_IDX, /* "Culture" }, */
135 	MONO_MT_END,
136 
137 #define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
138 	MONO_MT_UINT32,     /* "OSPlatformID" }, */
139 	MONO_MT_UINT32,     /* "OSMajor" }, */
140 	MONO_MT_UINT32,     /* "OSMinor" }, */
141 	MONO_MT_END,
142 
143 #define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
144 	MONO_MT_UINT32,     /* "Processor" }, */
145 	MONO_MT_END,
146 
147 #define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
148 	MONO_MT_UINT16,     /* "Major" }, */
149 	MONO_MT_UINT16,     /* "Minor" }, */
150 	MONO_MT_UINT16,     /* "Build" }, */
151 	MONO_MT_UINT16,     /* "Revision" }, */
152 	MONO_MT_UINT32,     /* "Flags" }, */
153 	MONO_MT_BLOB_IDX,   /* "PublicKeyOrToken" }, */
154 	MONO_MT_STRING_IDX, /* "Name" }, */
155 	MONO_MT_STRING_IDX, /* "Culture" }, */
156 	MONO_MT_BLOB_IDX,   /* "HashValue" }, */
157 	MONO_MT_END,
158 
159 #define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
160 	MONO_MT_UINT32,     /* "OSPlatformID" }, */
161 	MONO_MT_UINT32,     /* "OSMajorVersion" }, */
162 	MONO_MT_UINT32,     /* "OSMinorVersion" }, */
163 	MONO_MT_TABLE_IDX,  /* "AssemblyRef:AssemblyRef" }, */
164 	MONO_MT_END,
165 
166 #define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
167 	MONO_MT_UINT32,     /* "Processor" }, */
168 	MONO_MT_TABLE_IDX,  /* "AssemblyRef:AssemblyRef" }, */
169 	MONO_MT_END,
170 
171 #define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
172 	MONO_MT_UINT16,     /* "PackingSize" }, */
173 	MONO_MT_UINT32,     /* "ClassSize" }, */
174 	MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
175 	MONO_MT_END,
176 
177 #define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
178 	MONO_MT_UINT8,      /* "Type" }, */
179 	MONO_MT_UINT8,      /* "PaddingZero" }, */
180 	MONO_MT_CONST_IDX,  /* "Parent" }, */
181 	MONO_MT_BLOB_IDX,   /* "Value" }, */
182 	MONO_MT_END,
183 
184 #define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
185 	MONO_MT_HASCAT_IDX, /* "Parent" }, */
186 	MONO_MT_CAT_IDX,    /* "Type" }, */
187 	MONO_MT_BLOB_IDX,   /* "Value" }, */
188 	MONO_MT_END,
189 
190 #define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
191 	MONO_MT_UINT16,     /* "Action" }, */
192 	MONO_MT_HASDEC_IDX, /* "Parent" }, */
193 	MONO_MT_BLOB_IDX,   /* "PermissionSet" }, */
194 	MONO_MT_END,
195 
196 #define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
197 	MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
198 	MONO_MT_TABLE_IDX,  /* "EventList:Event" }, */
199 	MONO_MT_END,
200 
201 #define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
202 	MONO_MT_UINT16,     /* "EventFlags#EventAttribute" }, */
203 	MONO_MT_STRING_IDX, /* "Name" }, */
204 	MONO_MT_TDOR_IDX,  /* "EventType" }, TypeDef or TypeRef or TypeSpec  */
205 	MONO_MT_END,
206 
207 #define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
208 	MONO_MT_TABLE_IDX,  /* "Event" }, */
209 	MONO_MT_END,
210 
211 #define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
212 	MONO_MT_UINT32,     /* "Flags" }, */
213 	MONO_MT_TABLE_IDX,  /* "TypeDefId" }, */
214 	MONO_MT_STRING_IDX, /* "TypeName" }, */
215 	MONO_MT_STRING_IDX, /* "TypeNameSpace" }, */
216 	MONO_MT_IMPL_IDX,   /* "Implementation" }, */
217 	MONO_MT_END,
218 
219 #define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
220 	MONO_MT_UINT16,     /* "Flags" }, */
221 	MONO_MT_STRING_IDX, /* "Name" }, */
222 	MONO_MT_BLOB_IDX,   /* "Signature" }, */
223 	MONO_MT_END,
224 
225 #define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
226 	MONO_MT_UINT32,     /* "Offset" }, */
227 	MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
228 	MONO_MT_END,
229 
230 #define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
231 	MONO_MT_HFM_IDX,    /* "Parent" }, */
232 	MONO_MT_BLOB_IDX,   /* "NativeType" }, */
233 	MONO_MT_END,
234 
235 #define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
236 	MONO_MT_UINT32,     /* "RVA" }, */
237 	MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
238 	MONO_MT_END,
239 
240 #define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
241 	MONO_MT_TABLE_IDX,  /* "Field" }, */
242 	MONO_MT_END,
243 
244 #define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
245 	MONO_MT_UINT32,     /* "Flags" }, */
246 	MONO_MT_STRING_IDX, /* "Name" }, */
247 	MONO_MT_BLOB_IDX,   /* "Value" },  */
248 	MONO_MT_END,
249 
250 #define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
251 	MONO_MT_UINT16,     /* "MappingFlag" }, */
252 	MONO_MT_MF_IDX,     /* "MemberForwarded" }, */
253 	MONO_MT_STRING_IDX, /* "ImportName" }, */
254 	MONO_MT_TABLE_IDX,  /* "ImportScope:ModuleRef" }, */
255 	MONO_MT_END,
256 
257 #define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
258 	MONO_MT_TABLE_IDX,  /* "Class:TypeDef" },  */
259 	MONO_MT_TDOR_IDX,  /* "Interface=TypeDefOrRef" }, */
260 	MONO_MT_END,
261 
262 #define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
263 	MONO_MT_UINT32,     /* "Offset" }, */
264 	MONO_MT_UINT32,     /* "Flags" }, */
265 	MONO_MT_STRING_IDX, /* "Name" }, */
266 	MONO_MT_IMPL_IDX,   /* "Implementation" }, */
267 	MONO_MT_END,
268 
269 #define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
270 	MONO_MT_MRP_IDX,    /* "Class" }, */
271 	MONO_MT_STRING_IDX, /* "Name" }, */
272 	MONO_MT_BLOB_IDX,   /* "Signature" }, */
273 	MONO_MT_END,
274 
275 #define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
276 	MONO_MT_UINT32,     /* "RVA" }, */
277 	MONO_MT_UINT16,     /* "ImplFlags#MethodImplAttributes" }, */
278 	MONO_MT_UINT16,     /* "Flags#MethodAttribute" }, */
279 	MONO_MT_STRING_IDX, /* "Name" }, */
280 	MONO_MT_BLOB_IDX,   /* "Signature" }, */
281 	MONO_MT_TABLE_IDX,  /* "ParamList:Param" }, */
282 	MONO_MT_END,
283 
284 #define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
285 	MONO_MT_TABLE_IDX,  /* "Class:TypeDef" }, */
286 	MONO_MT_MDOR_IDX,   /* "MethodBody" }, */
287 	MONO_MT_MDOR_IDX,   /* "MethodDeclaration" }, */
288 	MONO_MT_END,
289 
290 #define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
291 	MONO_MT_UINT16,     /* "MethodSemantic" }, */
292 	MONO_MT_TABLE_IDX,  /* "Method:Method" }, */
293 	MONO_MT_HS_IDX,     /* "Association" }, */
294 	MONO_MT_END,
295 
296 #define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
297 	MONO_MT_TABLE_IDX,  /* "Method" }, */
298 	MONO_MT_END,
299 
300 #define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
301 	MONO_MT_UINT16,     /* "Generation" }, */
302 	MONO_MT_STRING_IDX, /* "Name" }, */
303 	MONO_MT_GUID_IDX,   /* "MVID" }, */
304 	MONO_MT_GUID_IDX,   /* "EncID" }, */
305 	MONO_MT_GUID_IDX,   /* "EncBaseID" }, */
306 	MONO_MT_END,
307 
308 #define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
309 	MONO_MT_STRING_IDX, /* "Name" }, */
310 	MONO_MT_END,
311 
312 #define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
313 	MONO_MT_TABLE_IDX,  /* "NestedClass:TypeDef" }, */
314 	MONO_MT_TABLE_IDX,  /* "EnclosingClass:TypeDef" }, */
315 	MONO_MT_END,
316 
317 #define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
318 	MONO_MT_UINT16,     /* "Flags" }, */
319 	MONO_MT_UINT16,     /* "Sequence" }, */
320 	MONO_MT_STRING_IDX, /* "Name" }, */
321 	MONO_MT_END,
322 
323 #define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
324 	MONO_MT_TABLE_IDX,  /* "Param" }, */
325 	MONO_MT_END,
326 
327 #define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
328 	MONO_MT_UINT16,     /* "Flags" }, */
329 	MONO_MT_STRING_IDX, /* "Name" }, */
330 	MONO_MT_BLOB_IDX,   /* "Type" }, */
331 	MONO_MT_END,
332 
333 #define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
334 	MONO_MT_TABLE_IDX, /* "Property" }, */
335 	MONO_MT_END,
336 
337 #define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
338 	MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
339 	MONO_MT_TABLE_IDX,  /* "PropertyList:Property" }, */
340 	MONO_MT_END,
341 
342 #define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
343 	MONO_MT_BLOB_IDX,   /* "Signature" }, */
344 	MONO_MT_END,
345 
346 #define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
347 	MONO_MT_UINT32,     /* "Flags" }, */
348 	MONO_MT_STRING_IDX, /* "Name" }, */
349 	MONO_MT_STRING_IDX, /* "Namespace" }, */
350 	MONO_MT_TDOR_IDX,   /* "Extends" }, */
351 	MONO_MT_TABLE_IDX,  /* "FieldList:Field" }, */
352 	MONO_MT_TABLE_IDX,  /* "MethodList:Method" }, */
353 	MONO_MT_END,
354 
355 #define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
356 	MONO_MT_RS_IDX,     /* "ResolutionScope=ResolutionScope" }, */
357 	MONO_MT_STRING_IDX, /* "Name" }, */
358 	MONO_MT_STRING_IDX, /* "Namespace" }, */
359 	MONO_MT_END,
360 
361 #define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
362 	MONO_MT_BLOB_IDX,   /* "Signature" }, */
363 	MONO_MT_END,
364 
365 #define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
366 	MONO_MT_UINT16,     /* "Number" }, */
367 	MONO_MT_UINT16,     /* "Flags" }, */
368 	MONO_MT_TABLE_IDX,  /* "Owner" },  TypeDef or MethodDef */
369 	MONO_MT_STRING_IDX, /* "Name" }, */
370 	MONO_MT_END,
371 
372 #define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
373 	MONO_MT_MDOR_IDX,   /* "Method" }, */
374 	MONO_MT_BLOB_IDX,   /* "Signature" }, */
375 	MONO_MT_END,
376 
377 #define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
378 	MONO_MT_TABLE_IDX,  /* "GenericParam" }, */
379 	MONO_MT_TDOR_IDX,   /* "Constraint" }, */
380 	MONO_MT_END,
381 
382 #define DOCUMENT_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
383 	MONO_MT_BLOB_IDX,   /* Name */
384 	MONO_MT_GUID_IDX,   /* HashAlgorithm */
385 	MONO_MT_BLOB_IDX,   /* Hash */
386 	MONO_MT_GUID_IDX,   /* Language */
387 	MONO_MT_END,
388 
389 #define METHODBODY_SCHEMA_OFFSET DOCUMENT_SCHEMA_OFFSET + 5
390 	MONO_MT_TABLE_IDX,   /* Document */
391 	MONO_MT_BLOB_IDX,   /* SequencePoints */
392 	MONO_MT_END,
393 
394 #define LOCALSCOPE_SCHEMA_OFFSET METHODBODY_SCHEMA_OFFSET + 3
395 	MONO_MT_TABLE_IDX,   /* Method */
396 	MONO_MT_TABLE_IDX,   /* ImportScope */
397 	MONO_MT_TABLE_IDX,   /* VariableList */
398 	MONO_MT_TABLE_IDX,   /* ConstantList */
399 	MONO_MT_UINT32,      /* StartOffset */
400 	MONO_MT_UINT32,      /* Length */
401 	MONO_MT_END,
402 
403 #define LOCALVARIABLE_SCHEMA_OFFSET LOCALSCOPE_SCHEMA_OFFSET + 7
404 	MONO_MT_UINT16,      /* Attributes */
405 	MONO_MT_UINT16,      /* Index */
406 	MONO_MT_STRING_IDX,  /* Name */
407 	MONO_MT_END,
408 
409 #define LOCALCONSTANT_SCHEMA_OFFSET LOCALVARIABLE_SCHEMA_OFFSET + 4
410 	MONO_MT_STRING_IDX,  /* Name (String heap index) */
411 	MONO_MT_BLOB_IDX,    /* Signature (Blob heap index, LocalConstantSig blob) */
412 	MONO_MT_END,
413 
414 #define IMPORTSCOPE_SCHEMA_OFFSET LOCALCONSTANT_SCHEMA_OFFSET + 3
415 	MONO_MT_TABLE_IDX, /* Parent (ImportScope row id or nil) */
416 	MONO_MT_BLOB_IDX,  /* Imports (Blob index, encoding: Imports blob) */
417 	MONO_MT_END,
418 
419 #define ASYNCMETHOD_SCHEMA_OFFSET IMPORTSCOPE_SCHEMA_OFFSET + 3
420 	MONO_MT_TABLE_IDX, /* MoveNextMethod (MethodDef row id) */
421 	MONO_MT_TABLE_IDX, /* KickoffMethod (MethodDef row id) */
422 	MONO_MT_END,
423 
424 #define CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET ASYNCMETHOD_SCHEMA_OFFSET + 3
425 	MONO_MT_HASCUSTDEBUG_IDX, /* Parent (HasCustomDebugInformation coded index) */
426 	MONO_MT_GUID_IDX,  /* Kind (Guid heap index) */
427 	MONO_MT_BLOB_IDX,  /* Value (Blob heap index) */
428 	MONO_MT_END,
429 
430 #define NULL_SCHEMA_OFFSET CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET + 4
431 	MONO_MT_END
432 };
433 
434 /* Must be the same order as MONO_TABLE_* */
435 const static unsigned char
436 table_description [] = {
437 	MODULE_SCHEMA_OFFSET,
438 	TYPEREF_SCHEMA_OFFSET,
439 	TYPEDEF_SCHEMA_OFFSET,
440 	FIELD_POINTER_SCHEMA_OFFSET,
441 	FIELD_SCHEMA_OFFSET,
442 	METHOD_POINTER_SCHEMA_OFFSET,
443 	METHOD_SCHEMA_OFFSET,
444 	PARAM_POINTER_SCHEMA_OFFSET,
445 	PARAM_SCHEMA_OFFSET,
446 	IFACEMAP_SCHEMA_OFFSET,
447 	MEMBERREF_SCHEMA_OFFSET, /* 0xa */
448 	CONSTANT_SCHEMA_OFFSET,
449 	CUSTOM_ATTR_SCHEMA_OFFSET,
450 	FIELD_MARSHAL_SCHEMA_OFFSET,
451 	DECL_SEC_SCHEMA_OFFSET,
452 	CLASS_LAYOUT_SCHEMA_OFFSET,
453 	FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
454 	STDALON_SIG_SCHEMA_OFFSET,
455 	EVENTMAP_SCHEMA_OFFSET,
456 	EVENT_POINTER_SCHEMA_OFFSET,
457 	EVENT_SCHEMA_OFFSET,
458 	PROPERTY_MAP_SCHEMA_OFFSET,
459 	PROPERTY_POINTER_SCHEMA_OFFSET,
460 	PROPERTY_SCHEMA_OFFSET,
461 	METHOD_SEMA_SCHEMA_OFFSET,
462 	METHOD_IMPL_SCHEMA_OFFSET,
463 	MODULEREF_SCHEMA_OFFSET, /* 0x1a */
464 	TYPESPEC_SCHEMA_OFFSET,
465 	IMPLMAP_SCHEMA_OFFSET,
466 	FIELD_RVA_SCHEMA_OFFSET,
467 	NULL_SCHEMA_OFFSET,
468 	NULL_SCHEMA_OFFSET,
469 	ASSEMBLY_SCHEMA_OFFSET, /* 0x20 */
470 	ASSEMBLYPROC_SCHEMA_OFFSET,
471 	ASSEMBLYOS_SCHEMA_OFFSET,
472 	ASSEMBLYREF_SCHEMA_OFFSET,
473 	ASSEMBLYREFPROC_SCHEMA_OFFSET,
474 	ASSEMBLYREFOS_SCHEMA_OFFSET,
475 	FILE_SCHEMA_OFFSET,
476 	EXPORTED_TYPE_SCHEMA_OFFSET,
477 	MANIFEST_SCHEMA_OFFSET,
478 	NESTED_CLASS_SCHEMA_OFFSET,
479 	GENPARAM_SCHEMA_OFFSET, /* 0x2a */
480 	METHOD_SPEC_SCHEMA_OFFSET,
481 	GEN_CONSTRAINT_SCHEMA_OFFSET,
482 	NULL_SCHEMA_OFFSET,
483 	NULL_SCHEMA_OFFSET,
484 	NULL_SCHEMA_OFFSET,
485 	DOCUMENT_SCHEMA_OFFSET, /* 0x30 */
486 	METHODBODY_SCHEMA_OFFSET,
487 	LOCALSCOPE_SCHEMA_OFFSET,
488 	LOCALVARIABLE_SCHEMA_OFFSET,
489 	LOCALCONSTANT_SCHEMA_OFFSET,
490 	IMPORTSCOPE_SCHEMA_OFFSET,
491 	ASYNCMETHOD_SCHEMA_OFFSET,
492 	CUSTOMDEBUGINFORMATION_SCHEMA_OFFSET
493 };
494 
495 #ifdef HAVE_ARRAY_ELEM_INIT
496 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
497 #define MSGSTRFIELD1(line) str##line
498 static const struct msgstr_t {
499 #define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
500 #include "mono/cil/tables.def"
501 #undef TABLEDEF
502 } tablestr = {
503 #define TABLEDEF(a,b) b,
504 #include "mono/cil/tables.def"
505 #undef TABLEDEF
506 };
507 static const gint16 tableidx [] = {
508 #define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
509 #include "mono/cil/tables.def"
510 #undef TABLEDEF
511 };
512 
513 #else
514 #define TABLEDEF(a,b) b,
515 static const char* const
516 mono_tables_names [] = {
517 #include "mono/cil/tables.def"
518 	NULL
519 };
520 
521 #endif
522 
523 /* If TRUE (but also see DISABLE_STICT_STRONG_NAMES #define), Mono will check
524  * that the public key token, culture and version of a candidate assembly matches
525  * the requested strong name.  If FALSE, as long as the name matches, the candidate
526  * will be allowed.
527  */
528 static gboolean check_strong_names_strictly = FALSE;
529 
530 // Amount initially reserved in each imageset's mempool.
531 // FIXME: This number is arbitrary, a more practical number should be found
532 #define INITIAL_IMAGE_SET_SIZE    1024
533 
534 /**
535  * mono_meta_table_name:
536  * \param table table index
537  *
538  * Returns the name of the given ECMA metadata logical format table
539  * as described in ECMA 335, Partition II, Section 22.
540  *
541  * \returns the name for the \p table index
542  */
543 const char *
mono_meta_table_name(int table)544 mono_meta_table_name (int table)
545 {
546 	if ((table < 0) || (table > MONO_TABLE_LAST))
547 		return "";
548 
549 #ifdef HAVE_ARRAY_ELEM_INIT
550 	return (const char*)&tablestr + tableidx [table];
551 #else
552 	return mono_tables_names [table];
553 #endif
554 }
555 
556 /* The guy who wrote the spec for this should not be allowed near a
557  * computer again.
558 
559 If  e is a coded token(see clause 23.1.7) that points into table ti out of n possible tables t0, .. tn-1,
560 then it is stored as e << (log n) & tag{ t0, .. tn-1}[ ti] using 2 bytes if the maximum number of
561 rows of tables t0, ..tn-1, is less than 2^16 - (log n), and using 4 bytes otherwise. The family of
562 finite maps tag{ t0, ..tn-1} is defined below. Note that to decode a physical row, you need the
563 inverse of this mapping.
564 
565  */
566 #define rtsize(meta,s,b) (((s) < (1 << (b)) ? 2 : 4))
567 
568 static inline int
idx_size(MonoImage * meta,int tableidx)569 idx_size (MonoImage *meta, int tableidx)
570 {
571 	if (meta->referenced_tables && (meta->referenced_tables & ((guint64)1 << tableidx)))
572 		return meta->referenced_table_rows [tableidx] < 65536 ? 2 : 4;
573 	else
574 		return meta->tables [tableidx].rows < 65536 ? 2 : 4;
575 }
576 
577 static inline int
get_nrows(MonoImage * meta,int tableidx)578 get_nrows (MonoImage *meta, int tableidx)
579 {
580 	if (meta->referenced_tables && (meta->referenced_tables & ((guint64)1 << tableidx)))
581 		return meta->referenced_table_rows [tableidx];
582 	else
583 		return meta->tables [tableidx].rows;
584 }
585 
586 /* Reference: Partition II - 23.2.6 */
587 /**
588  * mono_metadata_compute_size:
589  * \param meta metadata context
590  * \param tableindex metadata table number
591  * \param result_bitfield pointer to \c guint32 where to store additional info
592  *
593  * \c mono_metadata_compute_size computes the length in bytes of a single
594  * row in a metadata table. The size of each column is encoded in the
595  * \p result_bitfield return value along with the number of columns in the table.
596  * the resulting bitfield should be handed to the \c mono_metadata_table_size
597  * and \c mono_metadata_table_count macros.
598  * This is a Mono runtime internal only function.
599  */
600 int
mono_metadata_compute_size(MonoImage * meta,int tableindex,guint32 * result_bitfield)601 mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
602 {
603 	guint32 bitfield = 0;
604 	int size = 0, field_size = 0;
605 	int i, n, code;
606 	int shift = 0;
607 	const unsigned char *description = TableSchemas + table_description [tableindex];
608 
609 	for (i = 0; (code = description [i]) != MONO_MT_END; i++){
610 		switch (code){
611 		case MONO_MT_UINT32:
612 			field_size = 4; break;
613 
614 		case MONO_MT_UINT16:
615 			field_size = 2; break;
616 
617 		case MONO_MT_UINT8:
618 			field_size = 1; break;
619 
620 		case MONO_MT_BLOB_IDX:
621 			field_size = meta->idx_blob_wide ? 4 : 2; break;
622 
623 		case MONO_MT_STRING_IDX:
624 			field_size = meta->idx_string_wide ? 4 : 2; break;
625 
626 		case MONO_MT_GUID_IDX:
627 			field_size = meta->idx_guid_wide ? 4 : 2; break;
628 
629 		case MONO_MT_TABLE_IDX:
630 			/* Uhm, a table index can point to other tables besides the current one
631 			 * so, it's not correct to use the rowcount of the current table to
632 			 * get the size for this column - lupus
633 			 */
634 			switch (tableindex) {
635 			case MONO_TABLE_ASSEMBLYREFOS:
636 				g_assert (i == 3);
637 				field_size = idx_size (meta, MONO_TABLE_ASSEMBLYREF); break;
638 			case MONO_TABLE_ASSEMBLYREFPROCESSOR:
639 				g_assert (i == 1);
640 				field_size = idx_size (meta, MONO_TABLE_ASSEMBLYREF); break;
641 			case MONO_TABLE_CLASSLAYOUT:
642 				g_assert (i == 2);
643 				field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
644 			case MONO_TABLE_EVENTMAP:
645 				g_assert (i == 0 || i == 1);
646 				field_size = i ? idx_size (meta, MONO_TABLE_EVENT):
647 					idx_size (meta, MONO_TABLE_TYPEDEF);
648 				break;
649 			case MONO_TABLE_EVENT_POINTER:
650 				g_assert (i == 0);
651 				field_size = idx_size (meta, MONO_TABLE_EVENT); break;
652 			case MONO_TABLE_EXPORTEDTYPE:
653 				g_assert (i == 1);
654 				/* the index is in another metadata file, so it must be 4 */
655 				field_size = 4; break;
656 			case MONO_TABLE_FIELDLAYOUT:
657 				g_assert (i == 1);
658 				field_size = idx_size (meta, MONO_TABLE_FIELD); break;
659 			case MONO_TABLE_FIELDRVA:
660 				g_assert (i == 1);
661 				field_size = idx_size (meta, MONO_TABLE_FIELD); break;
662 			case MONO_TABLE_FIELD_POINTER:
663 				g_assert (i == 0);
664 				field_size = idx_size (meta, MONO_TABLE_FIELD); break;
665 			case MONO_TABLE_IMPLMAP:
666 				g_assert (i == 3);
667 				field_size = idx_size (meta, MONO_TABLE_MODULEREF); break;
668 			case MONO_TABLE_INTERFACEIMPL:
669 				g_assert (i == 0);
670 				field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
671 			case MONO_TABLE_METHOD:
672 				g_assert (i == 5);
673 				field_size = idx_size (meta, MONO_TABLE_PARAM); break;
674 			case MONO_TABLE_METHODIMPL:
675 				g_assert (i == 0);
676 				field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
677 			case MONO_TABLE_METHODSEMANTICS:
678 				g_assert (i == 1);
679 				field_size = idx_size (meta, MONO_TABLE_METHOD); break;
680 			case MONO_TABLE_METHOD_POINTER:
681 				g_assert (i == 0);
682 				field_size = idx_size (meta, MONO_TABLE_METHOD); break;
683 			case MONO_TABLE_NESTEDCLASS:
684 				g_assert (i == 0 || i == 1);
685 				field_size = idx_size (meta, MONO_TABLE_TYPEDEF); break;
686 			case MONO_TABLE_PARAM_POINTER:
687 				g_assert (i == 0);
688 				field_size = idx_size (meta, MONO_TABLE_PARAM); break;
689 			case MONO_TABLE_PROPERTYMAP:
690 				g_assert (i == 0 || i == 1);
691 				field_size = i ? idx_size (meta, MONO_TABLE_PROPERTY):
692 					idx_size (meta, MONO_TABLE_TYPEDEF);
693 				break;
694 			case MONO_TABLE_PROPERTY_POINTER:
695 				g_assert (i == 0);
696 				field_size = idx_size (meta, MONO_TABLE_PROPERTY); break;
697 			case MONO_TABLE_TYPEDEF:
698 				g_assert (i == 4 || i == 5);
699 				field_size = i == 4 ? idx_size (meta, MONO_TABLE_FIELD):
700 					idx_size (meta, MONO_TABLE_METHOD);
701 				break;
702 			case MONO_TABLE_GENERICPARAM:
703 				g_assert (i == 2);
704 				n = MAX (get_nrows (meta, MONO_TABLE_METHOD), get_nrows (meta, MONO_TABLE_TYPEDEF));
705 				/*This is a coded token for 2 tables, so takes 1 bit */
706 				field_size = rtsize (meta, n, 16 - MONO_TYPEORMETHOD_BITS);
707 				break;
708 			case MONO_TABLE_GENERICPARAMCONSTRAINT:
709 				g_assert (i == 0);
710 				field_size = idx_size (meta, MONO_TABLE_GENERICPARAM);
711 				break;
712 			case MONO_TABLE_LOCALSCOPE:
713 				switch (i) {
714 				case 0:
715 					// FIXME: This table is in another file
716 					field_size = idx_size (meta, MONO_TABLE_METHOD);
717 					break;
718 				case 1:
719 					field_size = idx_size (meta, MONO_TABLE_IMPORTSCOPE);
720 					break;
721 				case 2:
722 					field_size = idx_size (meta, MONO_TABLE_LOCALVARIABLE);
723 					break;
724 				case 3:
725 					field_size = idx_size (meta, MONO_TABLE_LOCALCONSTANT);
726 					break;
727 				default:
728 					g_assert_not_reached ();
729 					break;
730 				}
731 				break;
732 			case MONO_TABLE_METHODBODY:
733 				g_assert (i == 0);
734 				field_size = idx_size (meta, MONO_TABLE_DOCUMENT); break;
735 			case MONO_TABLE_IMPORTSCOPE:
736 				g_assert(i == 0);
737 				field_size = idx_size (meta, MONO_TABLE_IMPORTSCOPE); break;
738 			case MONO_TABLE_STATEMACHINEMETHOD:
739 				g_assert(i == 0 || i == 1);
740 				field_size = idx_size(meta, MONO_TABLE_METHOD); break;
741 			default:
742 				g_error ("Can't handle MONO_MT_TABLE_IDX for table %d element %d", tableindex, i);
743 			}
744 			break;
745 
746 			/*
747 			 * HasConstant: ParamDef, FieldDef, Property
748 			 */
749 		case MONO_MT_CONST_IDX:
750 			n = MAX (get_nrows (meta, MONO_TABLE_PARAM),
751 				 get_nrows (meta, MONO_TABLE_FIELD));
752 			n = MAX (n, get_nrows (meta, MONO_TABLE_PROPERTY));
753 
754 			/* 2 bits to encode tag */
755 			field_size = rtsize (meta, n, 16-2);
756 			break;
757 
758 			/*
759 			 * HasCustomAttribute: points to any table but
760 			 * itself.
761 			 */
762 		case MONO_MT_HASCAT_IDX:
763 			/*
764 			 * We believe that since the signature and
765 			 * permission are indexing the Blob heap,
766 			 * we should consider the blob size first
767 			 */
768 			/* I'm not a believer - lupus
769 			if (meta->idx_blob_wide){
770 				field_size = 4;
771 				break;
772 			}*/
773 
774 			n = MAX (get_nrows (meta, MONO_TABLE_METHOD),
775 				 get_nrows (meta, MONO_TABLE_FIELD));
776 			n = MAX (n, get_nrows (meta, MONO_TABLE_TYPEREF));
777 			n = MAX (n, get_nrows (meta, MONO_TABLE_TYPEDEF));
778 			n = MAX (n, get_nrows (meta, MONO_TABLE_PARAM));
779 			n = MAX (n, get_nrows (meta, MONO_TABLE_INTERFACEIMPL));
780 			n = MAX (n, get_nrows (meta, MONO_TABLE_MEMBERREF));
781 			n = MAX (n, get_nrows (meta, MONO_TABLE_MODULE));
782 			n = MAX (n, get_nrows (meta, MONO_TABLE_DECLSECURITY));
783 			n = MAX (n, get_nrows (meta, MONO_TABLE_PROPERTY));
784 			n = MAX (n, get_nrows (meta, MONO_TABLE_EVENT));
785 			n = MAX (n, get_nrows (meta, MONO_TABLE_STANDALONESIG));
786 			n = MAX (n, get_nrows (meta, MONO_TABLE_MODULEREF));
787 			n = MAX (n, get_nrows (meta, MONO_TABLE_TYPESPEC));
788 			n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLY));
789 			n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
790 			n = MAX (n, get_nrows (meta, MONO_TABLE_FILE));
791 			n = MAX (n, get_nrows (meta, MONO_TABLE_EXPORTEDTYPE));
792 			n = MAX (n, get_nrows (meta, MONO_TABLE_MANIFESTRESOURCE));
793 			n = MAX (n, get_nrows (meta, MONO_TABLE_GENERICPARAM));
794 			n = MAX (n, get_nrows (meta, MONO_TABLE_GENERICPARAMCONSTRAINT));
795 			n = MAX (n, get_nrows (meta, MONO_TABLE_METHODSPEC));
796 
797 			/* 5 bits to encode */
798 			field_size = rtsize (meta, n, 16-5);
799 			break;
800 
801 			/*
802 			* HasCustomAttribute: points to any table but
803 			* itself.
804 			*/
805 
806 		case MONO_MT_HASCUSTDEBUG_IDX:
807 			n = MAX(get_nrows (meta, MONO_TABLE_METHOD),
808 					get_nrows (meta, MONO_TABLE_FIELD));
809 			n = MAX(n, get_nrows (meta, MONO_TABLE_TYPEREF));
810 			n = MAX(n, get_nrows (meta, MONO_TABLE_TYPEDEF));
811 			n = MAX(n, get_nrows (meta, MONO_TABLE_PARAM));
812 			n = MAX(n, get_nrows (meta, MONO_TABLE_INTERFACEIMPL));
813 			n = MAX(n, get_nrows (meta, MONO_TABLE_MEMBERREF));
814 			n = MAX(n, get_nrows (meta, MONO_TABLE_MODULE));
815 			n = MAX(n, get_nrows (meta, MONO_TABLE_DECLSECURITY));
816 			n = MAX(n, get_nrows (meta, MONO_TABLE_PROPERTY));
817 			n = MAX(n, get_nrows (meta, MONO_TABLE_EVENT));
818 			n = MAX(n, get_nrows (meta, MONO_TABLE_STANDALONESIG));
819 			n = MAX(n, get_nrows (meta, MONO_TABLE_MODULEREF));
820 			n = MAX(n, get_nrows (meta, MONO_TABLE_TYPESPEC));
821 			n = MAX(n, get_nrows (meta, MONO_TABLE_ASSEMBLY));
822 			n = MAX(n, get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
823 			n = MAX(n, get_nrows (meta, MONO_TABLE_FILE));
824 			n = MAX(n, get_nrows (meta, MONO_TABLE_EXPORTEDTYPE));
825 			n = MAX(n, get_nrows (meta, MONO_TABLE_MANIFESTRESOURCE));
826 			n = MAX(n, get_nrows (meta, MONO_TABLE_GENERICPARAM));
827 			n = MAX(n, get_nrows (meta, MONO_TABLE_GENERICPARAMCONSTRAINT));
828 			n = MAX(n, get_nrows (meta, MONO_TABLE_METHODSPEC));
829 			n = MAX(n, get_nrows (meta, MONO_TABLE_DOCUMENT));
830 			n = MAX(n, get_nrows (meta, MONO_TABLE_LOCALSCOPE));
831 			n = MAX(n, get_nrows (meta, MONO_TABLE_LOCALVARIABLE));
832 			n = MAX(n, get_nrows (meta, MONO_TABLE_LOCALCONSTANT));
833 			n = MAX(n, get_nrows (meta, MONO_TABLE_IMPORTSCOPE));
834 
835 			/* 5 bits to encode */
836 			field_size = rtsize(meta, n, 16 - 5);
837 			break;
838 
839 			/*
840 			 * CustomAttributeType: MethodDef, MemberRef.
841 			 */
842 		case MONO_MT_CAT_IDX:
843 			n = MAX (get_nrows (meta, MONO_TABLE_METHOD),
844 					 get_nrows (meta, MONO_TABLE_MEMBERREF));
845 
846 			/* 3 bits to encode */
847 			field_size = rtsize (meta, n, 16-3);
848 			break;
849 
850 			/*
851 			 * HasDeclSecurity: Typedef, MethodDef, Assembly
852 			 */
853 		case MONO_MT_HASDEC_IDX:
854 			n = MAX (get_nrows (meta, MONO_TABLE_TYPEDEF),
855 				 get_nrows (meta, MONO_TABLE_METHOD));
856 			n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLY));
857 
858 			/* 2 bits to encode */
859 			field_size = rtsize (meta, n, 16-2);
860 			break;
861 
862 			/*
863 			 * Implementation: File, AssemblyRef, ExportedType
864 			 */
865 		case MONO_MT_IMPL_IDX:
866 			n = MAX (get_nrows (meta, MONO_TABLE_FILE),
867 				 get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
868 			n = MAX (n, get_nrows (meta, MONO_TABLE_EXPORTEDTYPE));
869 
870 			/* 2 bits to encode tag */
871 			field_size = rtsize (meta, n, 16-2);
872 			break;
873 
874 			/*
875 			 * HasFieldMarshall: FieldDef, ParamDef
876 			 */
877 		case MONO_MT_HFM_IDX:
878 			n = MAX (get_nrows (meta, MONO_TABLE_FIELD),
879 				 get_nrows (meta, MONO_TABLE_PARAM));
880 
881 			/* 1 bit used to encode tag */
882 			field_size = rtsize (meta, n, 16-1);
883 			break;
884 
885 			/*
886 			 * MemberForwarded: FieldDef, MethodDef
887 			 */
888 		case MONO_MT_MF_IDX:
889 			n = MAX (get_nrows (meta, MONO_TABLE_FIELD),
890 				 get_nrows (meta, MONO_TABLE_METHOD));
891 
892 			/* 1 bit used to encode tag */
893 			field_size = rtsize (meta, n, 16-1);
894 			break;
895 
896 			/*
897 			 * TypeDefOrRef: TypeDef, ParamDef, TypeSpec
898 			 * LAMESPEC
899 			 * It is TypeDef, _TypeRef_, TypeSpec, instead.
900 			 */
901 		case MONO_MT_TDOR_IDX:
902 			n = MAX (get_nrows (meta, MONO_TABLE_TYPEDEF),
903 				 get_nrows (meta, MONO_TABLE_TYPEREF));
904 			n = MAX (n, get_nrows (meta, MONO_TABLE_TYPESPEC));
905 
906 			/* 2 bits to encode */
907 			field_size = rtsize (meta, n, 16-2);
908 			break;
909 
910 			/*
911 			 * MemberRefParent: TypeDef, TypeRef, MethodDef, ModuleRef, TypeSpec, MemberRef
912 			 */
913 		case MONO_MT_MRP_IDX:
914 			n = MAX (get_nrows (meta, MONO_TABLE_TYPEDEF),
915 				 get_nrows (meta, MONO_TABLE_TYPEREF));
916 			n = MAX (n, get_nrows (meta, MONO_TABLE_METHOD));
917 			n = MAX (n, get_nrows (meta, MONO_TABLE_MODULEREF));
918 			n = MAX (n, get_nrows (meta, MONO_TABLE_TYPESPEC));
919 
920 			/* 3 bits to encode */
921 			field_size = rtsize (meta, n, 16 - 3);
922 			break;
923 
924 			/*
925 			 * MethodDefOrRef: MethodDef, MemberRef
926 			 */
927 		case MONO_MT_MDOR_IDX:
928 			n = MAX (get_nrows (meta, MONO_TABLE_METHOD),
929 				 get_nrows (meta, MONO_TABLE_MEMBERREF));
930 
931 			/* 1 bit used to encode tag */
932 			field_size = rtsize (meta, n, 16-1);
933 			break;
934 
935 			/*
936 			 * HasSemantics: Property, Event
937 			 */
938 		case MONO_MT_HS_IDX:
939 			n = MAX (get_nrows (meta, MONO_TABLE_PROPERTY),
940 				 get_nrows (meta, MONO_TABLE_EVENT));
941 
942 			/* 1 bit used to encode tag */
943 			field_size = rtsize (meta, n, 16-1);
944 			break;
945 
946 			/*
947 			 * ResolutionScope: Module, ModuleRef, AssemblyRef, TypeRef
948 			 */
949 		case MONO_MT_RS_IDX:
950 			n = MAX (get_nrows (meta, MONO_TABLE_MODULE),
951 				 get_nrows (meta, MONO_TABLE_MODULEREF));
952 			n = MAX (n, get_nrows (meta, MONO_TABLE_ASSEMBLYREF));
953 			n = MAX (n, get_nrows (meta, MONO_TABLE_TYPEREF));
954 
955 			/* 2 bits used to encode tag (ECMA spec claims 3) */
956 			field_size = rtsize (meta, n, 16 - 2);
957 			break;
958 		}
959 
960 		/*
961 		 * encode field size as follows (we just need to
962 		 * distinguish them).
963 		 *
964 		 * 4 -> 3
965 		 * 2 -> 1
966 		 * 1 -> 0
967 		 */
968 		bitfield |= (field_size-1) << shift;
969 		shift += 2;
970 		size += field_size;
971 		/*g_print ("table %02x field %d size %d\n", tableindex, i, field_size);*/
972 	}
973 
974 	*result_bitfield = (i << 24) | bitfield;
975 	return size;
976 }
977 
978 /**
979  * mono_metadata_compute_table_bases:
980  * \param meta metadata context to compute table values
981  *
982  * Computes the table bases for the metadata structure.
983  * This is an internal function used by the image loader code.
984  */
985 void
mono_metadata_compute_table_bases(MonoImage * meta)986 mono_metadata_compute_table_bases (MonoImage *meta)
987 {
988 	int i;
989 	const char *base = meta->tables_base;
990 
991 	for (i = 0; i < MONO_TABLE_NUM; i++) {
992 		MonoTableInfo *table = &meta->tables [i];
993 		if (table->rows == 0)
994 			continue;
995 
996 		table->row_size = mono_metadata_compute_size (meta, i, &table->size_bitfield);
997 		table->base = base;
998 		base += table->rows * table->row_size;
999 	}
1000 }
1001 
1002 /**
1003  * mono_metadata_locate:
1004  * \param meta metadata context
1005  * \param table table code.
1006  * \param idx index of element to retrieve from \p table.
1007  *
1008  * \returns a pointer to the \p idx element in the metadata table
1009  * whose code is \p table.
1010  */
1011 const char *
mono_metadata_locate(MonoImage * meta,int table,int idx)1012 mono_metadata_locate (MonoImage *meta, int table, int idx)
1013 {
1014 	/* idx == 0 refers always to NULL */
1015 	g_return_val_if_fail (idx > 0 && idx <= meta->tables [table].rows, ""); /*FIXME shouldn't we return NULL here?*/
1016 
1017 	return meta->tables [table].base + (meta->tables [table].row_size * (idx - 1));
1018 }
1019 
1020 /**
1021  * mono_metadata_locate_token:
1022  * \param meta metadata context
1023  * \param token metadata token
1024  *
1025  * \returns a pointer to the data in the metadata represented by the
1026  * token \p token .
1027  */
1028 const char *
mono_metadata_locate_token(MonoImage * meta,guint32 token)1029 mono_metadata_locate_token (MonoImage *meta, guint32 token)
1030 {
1031 	return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
1032 }
1033 
1034 /**
1035  * mono_metadata_string_heap:
1036  * \param meta metadata context
1037  * \param index index into the string heap.
1038  * \returns an in-memory pointer to the \p index in the string heap.
1039  */
1040 const char *
mono_metadata_string_heap(MonoImage * meta,guint32 index)1041 mono_metadata_string_heap (MonoImage *meta, guint32 index)
1042 {
1043 	g_assert (index < meta->heap_strings.size);
1044 	g_return_val_if_fail (index < meta->heap_strings.size, "");
1045 	return meta->heap_strings.data + index;
1046 }
1047 
1048 /**
1049  * mono_metadata_user_string:
1050  * \param meta metadata context
1051  * \param index index into the user string heap.
1052  * \returns an in-memory pointer to the \p index in the user string heap (<code>#US</code>).
1053  */
1054 const char *
mono_metadata_user_string(MonoImage * meta,guint32 index)1055 mono_metadata_user_string (MonoImage *meta, guint32 index)
1056 {
1057 	g_assert (index < meta->heap_us.size);
1058 	g_return_val_if_fail (index < meta->heap_us.size, "");
1059 	return meta->heap_us.data + index;
1060 }
1061 
1062 /**
1063  * mono_metadata_blob_heap:
1064  * \param meta metadata context
1065  * \param index index into the blob.
1066  * \returns an in-memory pointer to the \p index in the Blob heap.
1067  */
1068 const char *
mono_metadata_blob_heap(MonoImage * meta,guint32 index)1069 mono_metadata_blob_heap (MonoImage *meta, guint32 index)
1070 {
1071 	g_assert (index < meta->heap_blob.size);
1072 	g_return_val_if_fail (index < meta->heap_blob.size, "");/*FIXME shouldn't we return NULL and check for index == 0?*/
1073 	return meta->heap_blob.data + index;
1074 }
1075 
1076 /**
1077  * mono_metadata_guid_heap:
1078  * \param meta metadata context
1079  * \param index index into the guid heap.
1080  * \returns an in-memory pointer to the \p index in the guid heap.
1081  */
1082 const char *
mono_metadata_guid_heap(MonoImage * meta,guint32 index)1083 mono_metadata_guid_heap (MonoImage *meta, guint32 index)
1084 {
1085 	--index;
1086 	index *= 16; /* adjust for guid size and 1-based index */
1087 	g_return_val_if_fail (index < meta->heap_guid.size, "");
1088 	return meta->heap_guid.data + index;
1089 }
1090 
1091 static const unsigned char *
dword_align(const unsigned char * ptr)1092 dword_align (const unsigned char *ptr)
1093 {
1094 #if SIZEOF_VOID_P == 8
1095 	return (const unsigned char *) (((guint64) (ptr + 3)) & ~3);
1096 #else
1097 	return (const unsigned char *) (((guint32) (ptr + 3)) & ~3);
1098 #endif
1099 }
1100 
1101 /**
1102  * mono_metadata_decode_row:
1103  * \param t table to extract information from.
1104  * \param idx index in table.
1105  * \param res array of \p res_size cols to store the results in
1106  *
1107  * This decompresses the metadata element \p idx in table \p t
1108  * into the \c guint32 \p res array that has \p res_size elements
1109  */
1110 void
mono_metadata_decode_row(const MonoTableInfo * t,int idx,guint32 * res,int res_size)1111 mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size)
1112 {
1113 	guint32 bitfield = t->size_bitfield;
1114 	int i, count = mono_metadata_table_count (bitfield);
1115 	const char *data;
1116 
1117 	g_assert (idx < t->rows);
1118 	g_assert (idx >= 0);
1119 	data = t->base + idx * t->row_size;
1120 
1121 	g_assert (res_size == count);
1122 
1123 	for (i = 0; i < count; i++) {
1124 		int n = mono_metadata_table_size (bitfield, i);
1125 
1126 		switch (n){
1127 		case 1:
1128 			res [i] = *data; break;
1129 		case 2:
1130 			res [i] = read16 (data); break;
1131 		case 4:
1132 			res [i] = read32 (data); break;
1133 		default:
1134 			g_assert_not_reached ();
1135 		}
1136 		data += n;
1137 	}
1138 }
1139 
1140 /**
1141  * mono_metadata_decode_row_col:
1142  * \param t table to extract information from.
1143  * \param idx index for row in table.
1144  * \param col column in the row.
1145  *
1146  * This function returns the value of column \p col from the \p idx
1147  * row in the table \p t .
1148  */
1149 guint32
mono_metadata_decode_row_col(const MonoTableInfo * t,int idx,guint col)1150 mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
1151 {
1152 	guint32 bitfield = t->size_bitfield;
1153 	int i;
1154 	register const char *data;
1155 	register int n;
1156 
1157 	g_assert (idx < t->rows);
1158 	g_assert (col < mono_metadata_table_count (bitfield));
1159 	data = t->base + idx * t->row_size;
1160 
1161 	n = mono_metadata_table_size (bitfield, 0);
1162 	for (i = 0; i < col; ++i) {
1163 		data += n;
1164 		n = mono_metadata_table_size (bitfield, i + 1);
1165 	}
1166 	switch (n) {
1167 	case 1:
1168 		return *data;
1169 	case 2:
1170 		return read16 (data);
1171 	case 4:
1172 		return read32 (data);
1173 	default:
1174 		g_assert_not_reached ();
1175 	}
1176 	return 0;
1177 }
1178 
1179 /**
1180  * mono_metadata_decode_blob_size:
1181  * \param ptr pointer to a blob object
1182  * \param rptr the new position of the pointer
1183  *
1184  * This decodes a compressed size as described by 24.2.4 (#US and #Blob a blob or user string object)
1185  *
1186  * \returns the size of the blob object
1187  */
1188 guint32
mono_metadata_decode_blob_size(const char * xptr,const char ** rptr)1189 mono_metadata_decode_blob_size (const char *xptr, const char **rptr)
1190 {
1191 	const unsigned char *ptr = (const unsigned char *)xptr;
1192 	guint32 size;
1193 
1194 	if ((*ptr & 0x80) == 0){
1195 		size = ptr [0] & 0x7f;
1196 		ptr++;
1197 	} else if ((*ptr & 0x40) == 0){
1198 		size = ((ptr [0] & 0x3f) << 8) + ptr [1];
1199 		ptr += 2;
1200 	} else {
1201 		size = ((ptr [0] & 0x1f) << 24) +
1202 			(ptr [1] << 16) +
1203 			(ptr [2] << 8) +
1204 			ptr [3];
1205 		ptr += 4;
1206 	}
1207 	if (rptr)
1208 		*rptr = (char*)ptr;
1209 	return size;
1210 }
1211 
1212 /**
1213  * mono_metadata_decode_value:
1214  * \param ptr pointer to decode from
1215  * \param rptr the new position of the pointer
1216  *
1217  * This routine decompresses 32-bit values as specified in the "Blob and
1218  * Signature" section (23.2)
1219  *
1220  * \returns the decoded value
1221  */
1222 guint32
mono_metadata_decode_value(const char * _ptr,const char ** rptr)1223 mono_metadata_decode_value (const char *_ptr, const char **rptr)
1224 {
1225 	const unsigned char *ptr = (const unsigned char *) _ptr;
1226 	unsigned char b = *ptr;
1227 	guint32 len;
1228 
1229 	if ((b & 0x80) == 0){
1230 		len = b;
1231 		++ptr;
1232 	} else if ((b & 0x40) == 0){
1233 		len = ((b & 0x3f) << 8 | ptr [1]);
1234 		ptr += 2;
1235 	} else {
1236 		len = ((b & 0x1f) << 24) |
1237 			(ptr [1] << 16) |
1238 			(ptr [2] << 8) |
1239 			ptr [3];
1240 		ptr += 4;
1241 	}
1242 	if (rptr)
1243 		*rptr = (char*)ptr;
1244 
1245 	return len;
1246 }
1247 
1248 /**
1249  * mono_metadata_decode_signed_value:
1250  * \param ptr pointer to decode from
1251  * \param rptr the new position of the pointer
1252  *
1253  * This routine decompresses 32-bit signed values
1254  * (not specified in the spec)
1255  *
1256  * \returns the decoded value
1257  */
1258 gint32
mono_metadata_decode_signed_value(const char * ptr,const char ** rptr)1259 mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
1260 {
1261 	guint32 uval = mono_metadata_decode_value (ptr, rptr);
1262 	gint32 ival = uval >> 1;
1263 	if (!(uval & 1))
1264 		return ival;
1265 	/* ival is a truncated 2's complement negative number.  */
1266 	if (ival < 0x40)
1267 		/* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
1268 		return ival - 0x40;
1269 	if (ival < 0x2000)
1270 		/* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
1271 		return ival - 0x2000;
1272 	if (ival < 0x10000000)
1273 		/* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
1274 		return ival - 0x10000000;
1275 	g_assert (ival < 0x20000000);
1276 	g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival, uval);
1277 	return ival - 0x20000000;
1278 }
1279 
1280 /**
1281  * mono_metadata_translate_token_index:
1282  * Translates the given 1-based index into the \c Method, \c Field, \c Event, or \c Param tables
1283  * using the \c *Ptr tables in uncompressed metadata, if they are available.
1284  *
1285  * FIXME: The caller is not forced to call this function, which is error-prone, since
1286  * forgetting to call it would only show up as a bug on uncompressed metadata.
1287  */
1288 guint32
mono_metadata_translate_token_index(MonoImage * image,int table,guint32 idx)1289 mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
1290 {
1291 	if (!image->uncompressed_metadata)
1292 		return idx;
1293 
1294 	switch (table) {
1295 	case MONO_TABLE_METHOD:
1296 		if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
1297 			return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
1298 		else
1299 			return idx;
1300 	case MONO_TABLE_FIELD:
1301 		if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
1302 			return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
1303 		else
1304 			return idx;
1305 	case MONO_TABLE_EVENT:
1306 		if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
1307 			return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
1308 		else
1309 			return idx;
1310 	case MONO_TABLE_PROPERTY:
1311 		if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
1312 			return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
1313 		else
1314 			return idx;
1315 	case MONO_TABLE_PARAM:
1316 		if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
1317 			return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
1318 		else
1319 			return idx;
1320 	default:
1321 		return idx;
1322 	}
1323 }
1324 
1325 /**
1326  * mono_metadata_decode_table_row:
1327  *
1328  * Same as \c mono_metadata_decode_row, but takes an \p image + \p table ID pair, and takes
1329  * uncompressed metadata into account, so it should be used to access the
1330  * \c Method, \c Field, \c Param and \c Event tables when the access is made from metadata, i.e.
1331  * \p idx is retrieved from a metadata table, like \c MONO_TYPEDEF_FIELD_LIST.
1332  */
1333 void
mono_metadata_decode_table_row(MonoImage * image,int table,int idx,guint32 * res,int res_size)1334 mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
1335 {
1336 	if (image->uncompressed_metadata)
1337 		idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1338 
1339 	mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
1340 }
1341 
1342 /**
1343  * mono_metadata_decode_table_row_col:
1344  *
1345  * Same as \c mono_metadata_decode_row_col, but takes an \p image + \p table ID pair, and takes
1346  * uncompressed metadata into account, so it should be used to access the
1347  * \c Method, \c Field, \c Param and \c Event tables.
1348  */
mono_metadata_decode_table_row_col(MonoImage * image,int table,int idx,guint col)1349 guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
1350 {
1351 	if (image->uncompressed_metadata)
1352 		idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
1353 
1354 	return mono_metadata_decode_row_col (&image->tables [table], idx, col);
1355 }
1356 
1357 /**
1358  * mono_metadata_parse_typedef_or_ref:
1359  * \param m a metadata context.
1360  * \param ptr a pointer to an encoded TypedefOrRef in \p m
1361  * \param rptr pointer updated to match the end of the decoded stream
1362  * \returns a token valid in the \p m metadata decoded from
1363  * the compressed representation.
1364  */
1365 guint32
mono_metadata_parse_typedef_or_ref(MonoImage * m,const char * ptr,const char ** rptr)1366 mono_metadata_parse_typedef_or_ref (MonoImage *m, const char *ptr, const char **rptr)
1367 {
1368 	guint32 token;
1369 	token = mono_metadata_decode_value (ptr, &ptr);
1370 	if (rptr)
1371 		*rptr = ptr;
1372 	return mono_metadata_token_from_dor (token);
1373 }
1374 
1375 /**
1376  * mono_metadata_parse_custom_mod:
1377  * \param m a metadata context.
1378  * \param dest storage where the info about the custom modifier is stored (may be NULL)
1379  * \param ptr a pointer to (possibly) the start of a custom modifier list
1380  * \param rptr pointer updated to match the end of the decoded stream
1381  *
1382  * Checks if \p ptr points to a type custom modifier compressed representation.
1383  *
1384  * \returns TRUE if a custom modifier was found, FALSE if not.
1385  */
1386 int
mono_metadata_parse_custom_mod(MonoImage * m,MonoCustomMod * dest,const char * ptr,const char ** rptr)1387 mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
1388 {
1389 	MonoCustomMod local;
1390 	if ((*ptr == MONO_TYPE_CMOD_OPT) || (*ptr == MONO_TYPE_CMOD_REQD)) {
1391 		if (!dest)
1392 			dest = &local;
1393 		dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
1394 		dest->token = mono_metadata_parse_typedef_or_ref (m, ptr + 1, rptr);
1395 		return TRUE;
1396 	}
1397 	return FALSE;
1398 }
1399 
1400 /*
1401  * mono_metadata_parse_array_internal:
1402  * @m: a metadata context.
1403  * @transient: whenever to allocate data from the heap
1404  * @ptr: a pointer to an encoded array description.
1405  * @rptr: pointer updated to match the end of the decoded stream
1406  *
1407  * Decodes the compressed array description found in the metadata @m at @ptr.
1408  *
1409  * Returns: a #MonoArrayType structure describing the array type
1410  * and dimensions. Memory is allocated from the heap or from the image mempool, depending
1411  * on the value of @transient.
1412  *
1413  * LOCKING: Acquires the loader lock
1414  */
1415 static MonoArrayType *
mono_metadata_parse_array_internal(MonoImage * m,MonoGenericContainer * container,gboolean transient,const char * ptr,const char ** rptr,MonoError * error)1416 mono_metadata_parse_array_internal (MonoImage *m, MonoGenericContainer *container,
1417 									gboolean transient, const char *ptr, const char **rptr, MonoError *error)
1418 {
1419 	int i;
1420 	MonoArrayType *array;
1421 	MonoType *etype;
1422 
1423 	etype = mono_metadata_parse_type_checked (m, container, 0, FALSE, ptr, &ptr, error); //FIXME this doesn't respect @transient
1424 	if (!etype)
1425 		return NULL;
1426 
1427 	array = transient ? (MonoArrayType *)g_malloc0 (sizeof (MonoArrayType)) : (MonoArrayType *)mono_image_alloc0 (m, sizeof (MonoArrayType));
1428 	array->eklass = mono_class_from_mono_type (etype);
1429 	array->rank = mono_metadata_decode_value (ptr, &ptr);
1430 
1431 	array->numsizes = mono_metadata_decode_value (ptr, &ptr);
1432 	if (array->numsizes)
1433 		array->sizes = transient ? (int *)g_malloc0 (sizeof (int) * array->numsizes) : (int *)mono_image_alloc0 (m, sizeof (int) * array->numsizes);
1434 	for (i = 0; i < array->numsizes; ++i)
1435 		array->sizes [i] = mono_metadata_decode_value (ptr, &ptr);
1436 
1437 	array->numlobounds = mono_metadata_decode_value (ptr, &ptr);
1438 	if (array->numlobounds)
1439 		array->lobounds = transient ? (int *)g_malloc0 (sizeof (int) * array->numlobounds) : (int *)mono_image_alloc0 (m, sizeof (int) * array->numlobounds);
1440 	for (i = 0; i < array->numlobounds; ++i)
1441 		array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr);
1442 
1443 	if (rptr)
1444 		*rptr = ptr;
1445 	return array;
1446 }
1447 
1448 /**
1449  * mono_metadata_parse_array:
1450  */
1451 MonoArrayType *
mono_metadata_parse_array(MonoImage * m,const char * ptr,const char ** rptr)1452 mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
1453 {
1454 	MonoError error;
1455 	MonoArrayType *ret = mono_metadata_parse_array_internal (m, NULL, FALSE, ptr, rptr, &error);
1456 	mono_error_cleanup (&error);
1457 
1458 	return ret;
1459 }
1460 
1461 /**
1462  * mono_metadata_free_array:
1463  * \param array array description
1464  *
1465  * Frees the array description returned from \c mono_metadata_parse_array.
1466  */
1467 void
mono_metadata_free_array(MonoArrayType * array)1468 mono_metadata_free_array (MonoArrayType *array)
1469 {
1470 	g_free (array->sizes);
1471 	g_free (array->lobounds);
1472 	g_free (array);
1473 }
1474 
1475 /*
1476  * need to add common field and param attributes combinations:
1477  * [out] param
1478  * public static
1479  * public static literal
1480  * private
1481  * private static
1482  * private static literal
1483  */
1484 static const MonoType
1485 builtin_types[] = {
1486 	/* data, attrs, type,              nmods, byref, pinned */
1487 	{{NULL}, 0,     MONO_TYPE_VOID,    0,     0,     0},
1488 	{{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     0,     0},
1489 	{{NULL}, 0,     MONO_TYPE_BOOLEAN, 0,     1,     0},
1490 	{{NULL}, 0,     MONO_TYPE_CHAR,    0,     0,     0},
1491 	{{NULL}, 0,     MONO_TYPE_CHAR,    0,     1,     0},
1492 	{{NULL}, 0,     MONO_TYPE_I1,      0,     0,     0},
1493 	{{NULL}, 0,     MONO_TYPE_I1,      0,     1,     0},
1494 	{{NULL}, 0,     MONO_TYPE_U1,      0,     0,     0},
1495 	{{NULL}, 0,     MONO_TYPE_U1,      0,     1,     0},
1496 	{{NULL}, 0,     MONO_TYPE_I2,      0,     0,     0},
1497 	{{NULL}, 0,     MONO_TYPE_I2,      0,     1,     0},
1498 	{{NULL}, 0,     MONO_TYPE_U2,      0,     0,     0},
1499 	{{NULL}, 0,     MONO_TYPE_U2,      0,     1,     0},
1500 	{{NULL}, 0,     MONO_TYPE_I4,      0,     0,     0},
1501 	{{NULL}, 0,     MONO_TYPE_I4,      0,     1,     0},
1502 	{{NULL}, 0,     MONO_TYPE_U4,      0,     0,     0},
1503 	{{NULL}, 0,     MONO_TYPE_U4,      0,     1,     0},
1504 	{{NULL}, 0,     MONO_TYPE_I8,      0,     0,     0},
1505 	{{NULL}, 0,     MONO_TYPE_I8,      0,     1,     0},
1506 	{{NULL}, 0,     MONO_TYPE_U8,      0,     0,     0},
1507 	{{NULL}, 0,     MONO_TYPE_U8,      0,     1,     0},
1508 	{{NULL}, 0,     MONO_TYPE_R4,      0,     0,     0},
1509 	{{NULL}, 0,     MONO_TYPE_R4,      0,     1,     0},
1510 	{{NULL}, 0,     MONO_TYPE_R8,      0,     0,     0},
1511 	{{NULL}, 0,     MONO_TYPE_R8,      0,     1,     0},
1512 	{{NULL}, 0,     MONO_TYPE_STRING,  0,     0,     0},
1513 	{{NULL}, 0,     MONO_TYPE_STRING,  0,     1,     0},
1514 	{{NULL}, 0,     MONO_TYPE_OBJECT,  0,     0,     0},
1515 	{{NULL}, 0,     MONO_TYPE_OBJECT,  0,     1,     0},
1516 	{{NULL}, 0,     MONO_TYPE_TYPEDBYREF,  0,     0,     0},
1517 	{{NULL}, 0,     MONO_TYPE_I,       0,     0,     0},
1518 	{{NULL}, 0,     MONO_TYPE_I,       0,     1,     0},
1519 	{{NULL}, 0,     MONO_TYPE_U,       0,     0,     0},
1520 	{{NULL}, 0,     MONO_TYPE_U,       0,     1,     0},
1521 };
1522 
1523 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
1524 
1525 static GHashTable *type_cache = NULL;
1526 static gint32 next_generic_inst_id = 0;
1527 
1528 /* Protected by image_sets_mutex */
1529 static MonoImageSet *mscorlib_image_set;
1530 /* Protected by image_sets_mutex */
1531 static GPtrArray *image_sets;
1532 static mono_mutex_t image_sets_mutex;
1533 
1534 static guint mono_generic_class_hash (gconstpointer data);
1535 
1536 /*
1537  * MonoTypes with modifies are never cached, so we never check or use that field.
1538  */
1539 static guint
mono_type_hash(gconstpointer data)1540 mono_type_hash (gconstpointer data)
1541 {
1542 	const MonoType *type = (const MonoType *) data;
1543 	if (type->type == MONO_TYPE_GENERICINST)
1544 		return mono_generic_class_hash (type->data.generic_class);
1545 	else
1546 		return type->type | (type->byref << 8) | (type->attrs << 9);
1547 }
1548 
1549 static gint
mono_type_equal(gconstpointer ka,gconstpointer kb)1550 mono_type_equal (gconstpointer ka, gconstpointer kb)
1551 {
1552 	const MonoType *a = (const MonoType *) ka;
1553 	const MonoType *b = (const MonoType *) kb;
1554 
1555 	if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned)
1556 		return 0;
1557 	/* need other checks */
1558 	return 1;
1559 }
1560 
1561 guint
mono_metadata_generic_inst_hash(gconstpointer data)1562 mono_metadata_generic_inst_hash (gconstpointer data)
1563 {
1564 	const MonoGenericInst *ginst = (const MonoGenericInst *) data;
1565 	guint hash = 0;
1566 	int i;
1567 
1568 	for (i = 0; i < ginst->type_argc; ++i) {
1569 		hash *= 13;
1570 		hash += mono_metadata_type_hash (ginst->type_argv [i]);
1571 	}
1572 
1573 	return hash ^ (ginst->is_open << 8);
1574 }
1575 
1576 static gboolean
mono_generic_inst_equal_full(const MonoGenericInst * a,const MonoGenericInst * b,gboolean signature_only)1577 mono_generic_inst_equal_full (const MonoGenericInst *a, const MonoGenericInst *b, gboolean signature_only)
1578 {
1579 	int i;
1580 
1581 	// An optimization: if the ids of two insts are the same, we know they are the same inst and don't check contents.
1582 	// Furthermore, because we perform early de-duping, if the ids differ, we know the contents differ.
1583 #ifndef MONO_SMALL_CONFIG // Optimization does not work in MONO_SMALL_CONFIG: There are no IDs
1584 	if (a->id && b->id) { // "id 0" means "object has no id"-- de-duping hasn't been performed yet, must check contents.
1585 		if (a->id == b->id)
1586 			return TRUE;
1587 		// In signature-comparison mode id equality implies object equality, but this is not true for inequality.
1588 		// Two separate objects could have signature-equavalent contents.
1589 		if (!signature_only)
1590 			return FALSE;
1591 	}
1592 #endif
1593 
1594 	if (a->is_open != b->is_open || a->type_argc != b->type_argc)
1595 		return FALSE;
1596 	for (i = 0; i < a->type_argc; ++i) {
1597 		if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], signature_only))
1598 			return FALSE;
1599 	}
1600 	return TRUE;
1601 }
1602 
1603 gboolean
mono_metadata_generic_inst_equal(gconstpointer ka,gconstpointer kb)1604 mono_metadata_generic_inst_equal (gconstpointer ka, gconstpointer kb)
1605 {
1606 	const MonoGenericInst *a = (const MonoGenericInst *) ka;
1607 	const MonoGenericInst *b = (const MonoGenericInst *) kb;
1608 
1609 	return mono_generic_inst_equal_full (a, b, FALSE);
1610 }
1611 
1612 static guint
mono_generic_class_hash(gconstpointer data)1613 mono_generic_class_hash (gconstpointer data)
1614 {
1615 	const MonoGenericClass *gclass = (const MonoGenericClass *) data;
1616 	guint hash = mono_metadata_type_hash (&gclass->container_class->byval_arg);
1617 
1618 	hash *= 13;
1619 	hash += gclass->is_tb_open;
1620 	hash += mono_metadata_generic_context_hash (&gclass->context);
1621 
1622 	return hash;
1623 }
1624 
1625 static gboolean
mono_generic_class_equal(gconstpointer ka,gconstpointer kb)1626 mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
1627 {
1628 	const MonoGenericClass *a = (const MonoGenericClass *) ka;
1629 	const MonoGenericClass *b = (const MonoGenericClass *) kb;
1630 
1631 	return _mono_metadata_generic_class_equal (a, b, FALSE);
1632 }
1633 
1634 /**
1635  * mono_metadata_init:
1636  *
1637  * Initialize the global variables of this module.
1638  * This is a Mono runtime internal function.
1639  */
1640 void
mono_metadata_init(void)1641 mono_metadata_init (void)
1642 {
1643 	int i;
1644 
1645 	/* We guard against double initialization due to how pedump in verification mode works.
1646 	Until runtime initialization is properly factored to work with what it needs we need workarounds like this.
1647 	FIXME: https://bugzilla.xamarin.com/show_bug.cgi?id=58793
1648 	*/
1649 	static gboolean inited;
1650 
1651 	if (inited)
1652 		return;
1653 	inited = TRUE;
1654 
1655 	type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
1656 
1657 	for (i = 0; i < NBUILTIN_TYPES (); ++i)
1658 		g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
1659 
1660 	mono_os_mutex_init_recursive (&image_sets_mutex);
1661 
1662 	mono_counters_register ("ImgSet Cache Hit", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_cache_hit);
1663 	mono_counters_register ("ImgSet Cache Miss", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_cache_miss);
1664 	mono_counters_register ("ImgSet Count", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &img_set_count);
1665 }
1666 
1667 /**
1668  * mono_metadata_cleanup:
1669  *
1670  * Free all resources used by this module.
1671  * This is a Mono runtime internal function.
1672  */
1673 void
mono_metadata_cleanup(void)1674 mono_metadata_cleanup (void)
1675 {
1676 	g_hash_table_destroy (type_cache);
1677 	type_cache = NULL;
1678 	g_ptr_array_free (image_sets, TRUE);
1679 	image_sets = NULL;
1680 	mono_os_mutex_destroy (&image_sets_mutex);
1681 }
1682 
1683 /**
1684  * mono_metadata_parse_type:
1685  * \param m metadata context
1686  * \param mode kind of type that may be found at \p ptr
1687  * \param opt_attrs optional attributes to store in the returned type
1688  * \param ptr pointer to the type representation
1689  * \param rptr pointer updated to match the end of the decoded stream
1690  * \param transient whenever to allocate the result from the heap or from a mempool
1691  *
1692  * Decode a compressed type description found at \p ptr in \p m .
1693  * \p mode can be one of \c MONO_PARSE_MOD_TYPE, \c MONO_PARSE_PARAM, \c MONO_PARSE_RET,
1694  * \c MONO_PARSE_FIELD, \c MONO_PARSE_LOCAL, \c MONO_PARSE_TYPE.
1695  * This function can be used to decode type descriptions in method signatures,
1696  * field signatures, locals signatures etc.
1697  *
1698  * To parse a generic type, \c generic_container points to the current class'es
1699  * (the \c generic_container field in the <code>MonoClass</code>) or the current generic method's
1700  * (stored in <code>image->property_hash</code>) generic container.
1701  * When we encounter a \c MONO_TYPE_VAR or \c MONO_TYPE_MVAR, it's looked up in
1702  * this \c MonoGenericContainer.
1703  *
1704  * LOCKING: Acquires the loader lock.
1705  *
1706  * \returns a \c MonoType structure representing the decoded type.
1707  */
1708 static MonoType*
mono_metadata_parse_type_internal(MonoImage * m,MonoGenericContainer * container,short opt_attrs,gboolean transient,const char * ptr,const char ** rptr,MonoError * error)1709 mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container,
1710 								   short opt_attrs, gboolean transient, const char *ptr, const char **rptr, MonoError *error)
1711 {
1712 	MonoType *type, *cached;
1713 	MonoType stype;
1714 	gboolean byref = FALSE;
1715 	gboolean pinned = FALSE;
1716 	const char *tmp_ptr;
1717 	int count = 0; // Number of mod arguments
1718 	gboolean found;
1719 
1720 	error_init (error);
1721 
1722 	/*
1723 	 * According to the spec, custom modifiers should come before the byref
1724 	 * flag, but the IL produced by ilasm from the following signature:
1725 	 *   object modopt(...) &
1726 	 * starts with a byref flag, followed by the modifiers. (bug #49802)
1727 	 * Also, this type seems to be different from 'object & modopt(...)'. Maybe
1728 	 * it would be better to treat byref as real type constructor instead of
1729 	 * a modifier...
1730 	 * Also, pinned should come before anything else, but some MSV++ produced
1731 	 * assemblies violate this (#bug 61990).
1732 	 */
1733 
1734 	/* Count the modifiers first */
1735 	tmp_ptr = ptr;
1736 	found = TRUE;
1737 	while (found) {
1738 		switch (*tmp_ptr) {
1739 		case MONO_TYPE_PINNED:
1740 		case MONO_TYPE_BYREF:
1741 			++tmp_ptr;
1742 			break;
1743 		case MONO_TYPE_CMOD_REQD:
1744 		case MONO_TYPE_CMOD_OPT:
1745 			count ++;
1746 			mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
1747 			break;
1748 		default:
1749 			found = FALSE;
1750 		}
1751 	}
1752 
1753 	if (count) { // There are mods, so the MonoType will be of nonstandard size.
1754 		int size;
1755 
1756 		size = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
1757 		type = transient ? (MonoType *)g_malloc0 (size) : (MonoType *)mono_image_alloc0 (m, size);
1758 		type->num_mods = count;
1759 		if (count > 64) {
1760 			mono_error_set_bad_image (error, m, "Invalid type with more than 64 modifiers");
1761 			return NULL;
1762 		}
1763 	} else {     // The type is of standard size, so we can allocate it on the stack.
1764 		type = &stype;
1765 		memset (type, 0, MONO_SIZEOF_TYPE);
1766 	}
1767 
1768 	/* Iterate again, but now parse pinned, byref and custom modifiers */
1769 	found = TRUE;
1770 	count = 0;
1771 	while (found) {
1772 		switch (*ptr) {
1773 		case MONO_TYPE_PINNED:
1774 			pinned = TRUE;
1775 			++ptr;
1776 			break;
1777 		case MONO_TYPE_BYREF:
1778 			byref = TRUE;
1779 			++ptr;
1780 			break;
1781 		case MONO_TYPE_CMOD_REQD:
1782 		case MONO_TYPE_CMOD_OPT:
1783 			mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
1784 			count ++;
1785 			break;
1786 		default:
1787 			found = FALSE;
1788 		}
1789 	}
1790 
1791 	type->attrs = opt_attrs;
1792 	type->byref = byref;
1793 	type->pinned = pinned ? 1 : 0;
1794 
1795 	if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr, error))
1796 		return NULL;
1797 
1798 	if (rptr)
1799 		*rptr = ptr;
1800 
1801 	// Possibly we can return an already-allocated type instead of the one we decoded
1802 	if (!type->num_mods && !transient) {
1803 		/* no need to free type here, because it is on the stack */
1804 		if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
1805 			MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
1806 
1807 			/* Consider the case:
1808 
1809 			     class Foo<T> { class Bar {} }
1810 			     class Test : Foo<Test>.Bar {}
1811 
1812 			   When Foo<Test> is being expanded, 'Test' isn't yet initialized.  It's actually in
1813 			   a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
1814 
1815 			   We ensure that the MonoClass is in a state that we can canonicalize to:
1816 
1817 			     klass->byval_arg.data.klass == klass
1818 			     klass->this_arg.data.klass == klass
1819 
1820 			   If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
1821 
1822 			   LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
1823 			            of a MonoClass which currently holds the loader lock.  'type' is local.
1824 			*/
1825 			if (ret->data.klass == type->data.klass) {
1826 				return ret;
1827 			}
1828 		}
1829 		/* No need to use locking since nobody is modifying the hash table */
1830 		if ((cached = (MonoType *)g_hash_table_lookup (type_cache, type))) {
1831 			return cached;
1832 		}
1833 	}
1834 
1835 	/* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
1836 
1837 	if (type == &stype) { // Type was allocated on the stack, so we need to copy it to safety
1838 		type = transient ? (MonoType *)g_malloc (MONO_SIZEOF_TYPE) : (MonoType *)mono_image_alloc (m, MONO_SIZEOF_TYPE);
1839 		memcpy (type, &stype, MONO_SIZEOF_TYPE);
1840 	}
1841 	return type;
1842 }
1843 
1844 
1845 MonoType*
mono_metadata_parse_type_checked(MonoImage * m,MonoGenericContainer * container,short opt_attrs,gboolean transient,const char * ptr,const char ** rptr,MonoError * error)1846 mono_metadata_parse_type_checked (MonoImage *m, MonoGenericContainer *container,
1847 							   short opt_attrs, gboolean transient, const char *ptr, const char **rptr, MonoError *error)
1848 {
1849 	return mono_metadata_parse_type_internal (m, container, opt_attrs, transient, ptr, rptr, error);
1850 }
1851 
1852 /*
1853  * LOCKING: Acquires the loader lock.
1854  */
1855 MonoType*
mono_metadata_parse_type(MonoImage * m,MonoParseTypeMode mode,short opt_attrs,const char * ptr,const char ** rptr)1856 mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
1857 			  const char *ptr, const char **rptr)
1858 {
1859 	MonoError error;
1860 	MonoType * type = mono_metadata_parse_type_internal (m, NULL, opt_attrs, FALSE, ptr, rptr, &error);
1861 	mono_error_cleanup (&error);
1862 	return type;
1863 }
1864 
1865 gboolean
mono_metadata_method_has_param_attrs(MonoImage * m,int def)1866 mono_metadata_method_has_param_attrs (MonoImage *m, int def)
1867 {
1868 	MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1869 	MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1870 	guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1871 
1872 	if (def < methodt->rows)
1873 		lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1874 	else
1875 		lastp = m->tables [MONO_TABLE_PARAM].rows + 1;
1876 
1877 	for (i = param_index; i < lastp; ++i) {
1878 		guint32 flags = mono_metadata_decode_row_col (paramt, i - 1, MONO_PARAM_FLAGS);
1879 		if (flags)
1880 			return TRUE;
1881 	}
1882 
1883 	return FALSE;
1884 }
1885 
1886 /*
1887  * mono_metadata_get_param_attrs:
1888  *
1889  * @m The image to loader parameter attributes from
1890  * @def method def token (one based)
1891  * @param_count number of params to decode including the return value
1892  *
1893  *   Return the parameter attributes for the method whose MethodDef index is DEF. The
1894  * returned memory needs to be freed by the caller. If all the param attributes are
1895  * 0, then NULL is returned.
1896  */
1897 int*
mono_metadata_get_param_attrs(MonoImage * m,int def,int param_count)1898 mono_metadata_get_param_attrs (MonoImage *m, int def, int param_count)
1899 {
1900 	MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
1901 	MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
1902 	guint32 cols [MONO_PARAM_SIZE];
1903 	guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
1904 	int *pattrs = NULL;
1905 
1906 	if (def < methodt->rows)
1907 		lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
1908 	else
1909 		lastp = paramt->rows + 1;
1910 
1911 	for (i = param_index; i < lastp; ++i) {
1912 		mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
1913 		if (cols [MONO_PARAM_FLAGS]) {
1914 			if (!pattrs)
1915 				pattrs = g_new0 (int, param_count);
1916 			/* at runtime we just ignore this kind of malformed file:
1917 			* the verifier can signal the error to the user
1918 			*/
1919 			if (cols [MONO_PARAM_SEQUENCE] >= param_count)
1920 				continue;
1921 			pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
1922 		}
1923 	}
1924 
1925 	return pattrs;
1926 }
1927 
1928 
1929 /**
1930  * mono_metadata_parse_signature:
1931  * \param image metadata context
1932  * \param token metadata token
1933  *
1934  * Decode a method signature stored in the \c StandAloneSig table
1935  *
1936  * \returns a \c MonoMethodSignature describing the signature.
1937  */
1938 MonoMethodSignature*
mono_metadata_parse_signature(MonoImage * image,guint32 token)1939 mono_metadata_parse_signature (MonoImage *image, guint32 token)
1940 {
1941 	MonoError error;
1942 	MonoMethodSignature *ret;
1943 	ret = mono_metadata_parse_signature_checked (image, token, &error);
1944 	mono_error_cleanup (&error);
1945 	return ret;
1946 }
1947 
1948 /*
1949  * mono_metadata_parse_signature_checked:
1950  * @image: metadata context
1951  * @token: metadata token
1952  * @error: set on error
1953  *
1954  * Decode a method signature stored in the STANDALONESIG table
1955  *
1956  * Returns: a MonoMethodSignature describing the signature. On failure
1957  * returns NULL and sets @error.
1958  */
1959 MonoMethodSignature*
mono_metadata_parse_signature_checked(MonoImage * image,guint32 token,MonoError * error)1960 mono_metadata_parse_signature_checked (MonoImage *image, guint32 token, MonoError *error)
1961 {
1962 
1963 	error_init (error);
1964 	MonoTableInfo *tables = image->tables;
1965 	guint32 idx = mono_metadata_token_index (token);
1966 	guint32 sig;
1967 	const char *ptr;
1968 
1969 	if (image_is_dynamic (image)) {
1970 		return (MonoMethodSignature *)mono_lookup_dynamic_token (image, token, NULL, error);
1971 	}
1972 
1973 	g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
1974 
1975 	sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
1976 
1977 	ptr = mono_metadata_blob_heap (image, sig);
1978 	mono_metadata_decode_blob_size (ptr, &ptr);
1979 
1980 	return mono_metadata_parse_method_signature_full (image, NULL, 0, ptr, NULL, error);
1981 }
1982 
1983 /**
1984  * mono_metadata_signature_alloc:
1985  * \param image metadata context
1986  * \param nparams number of parameters in the signature
1987  *
1988  * Allocate a \c MonoMethodSignature structure with the specified number of params.
1989  * The return type and the params types need to be filled later.
1990  * This is a Mono runtime internal function.
1991  *
1992  * LOCKING: Assumes the loader lock is held.
1993  *
1994  * \returns the new \c MonoMethodSignature structure.
1995  */
1996 MonoMethodSignature*
mono_metadata_signature_alloc(MonoImage * m,guint32 nparams)1997 mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
1998 {
1999 	MonoMethodSignature *sig;
2000 
2001 	sig = (MonoMethodSignature *)mono_image_alloc0 (m, MONO_SIZEOF_METHOD_SIGNATURE + ((gint32)nparams) * sizeof (MonoType*));
2002 	sig->param_count = nparams;
2003 	sig->sentinelpos = -1;
2004 
2005 	return sig;
2006 }
2007 
2008 static MonoMethodSignature*
mono_metadata_signature_dup_internal_with_padding(MonoImage * image,MonoMemPool * mp,MonoMethodSignature * sig,size_t padding)2009 mono_metadata_signature_dup_internal_with_padding (MonoImage *image, MonoMemPool *mp, MonoMethodSignature *sig, size_t padding)
2010 {
2011 	int sigsize, sig_header_size;
2012 	MonoMethodSignature *ret;
2013 	sigsize = sig_header_size = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *) + padding;
2014 	if (sig->ret)
2015 		sigsize += MONO_SIZEOF_TYPE;
2016 
2017 	if (image) {
2018 		ret = (MonoMethodSignature *)mono_image_alloc (image, sigsize);
2019 	} else if (mp) {
2020 		ret = (MonoMethodSignature *)mono_mempool_alloc (mp, sigsize);
2021 	} else {
2022 		ret = (MonoMethodSignature *)g_malloc (sigsize);
2023 	}
2024 
2025 	memcpy (ret, sig, sig_header_size - padding);
2026 
2027 	// Copy return value because of ownership semantics.
2028 	if (sig->ret) {
2029 		// Danger! Do not alter padding use without changing the dup_add_this below
2030 		intptr_t end_of_header = (intptr_t)( (char*)(ret) + sig_header_size);
2031 		ret->ret = (MonoType *)end_of_header;
2032 		memcpy (ret->ret, sig->ret, MONO_SIZEOF_TYPE);
2033 	}
2034 
2035 	return ret;
2036 }
2037 
2038 static MonoMethodSignature*
mono_metadata_signature_dup_internal(MonoImage * image,MonoMemPool * mp,MonoMethodSignature * sig)2039 mono_metadata_signature_dup_internal (MonoImage *image, MonoMemPool *mp, MonoMethodSignature *sig)
2040 {
2041 	return mono_metadata_signature_dup_internal_with_padding (image, mp, sig, 0);
2042 }
2043 /*
2044  * signature_dup_add_this:
2045  *
2046  *  Make a copy of @sig, adding an explicit this argument.
2047  */
2048 MonoMethodSignature*
mono_metadata_signature_dup_add_this(MonoImage * image,MonoMethodSignature * sig,MonoClass * klass)2049 mono_metadata_signature_dup_add_this (MonoImage *image, MonoMethodSignature *sig, MonoClass *klass)
2050 {
2051 	MonoMethodSignature *ret;
2052 	ret = mono_metadata_signature_dup_internal_with_padding (image, NULL, sig, sizeof (MonoType *));
2053 
2054 	ret->param_count = sig->param_count + 1;
2055 	ret->hasthis = FALSE;
2056 
2057 	for (int i = sig->param_count - 1; i >= 0; i --)
2058 		ret->params [i + 1] = sig->params [i];
2059 	ret->params [0] = klass->valuetype ? &klass->this_arg : &klass->byval_arg;
2060 
2061 	for (int i = sig->param_count - 1; i >= 0; i --)
2062 		g_assert(ret->params [i + 1]->type == sig->params [i]->type && ret->params [i+1]->type != MONO_TYPE_END);
2063 	g_assert (ret->ret->type == sig->ret->type && ret->ret->type != MONO_TYPE_END);
2064 
2065 	return ret;
2066 }
2067 
2068 
2069 
2070 MonoMethodSignature*
mono_metadata_signature_dup_full(MonoImage * image,MonoMethodSignature * sig)2071 mono_metadata_signature_dup_full (MonoImage *image, MonoMethodSignature *sig)
2072 {
2073 	MonoMethodSignature *ret = mono_metadata_signature_dup_internal (image, NULL, sig);
2074 
2075 	for (int i = 0 ; i < sig->param_count; i ++)
2076 		g_assert(ret->params [i]->type == sig->params [i]->type);
2077 	g_assert (ret->ret->type == sig->ret->type);
2078 
2079 	return ret;
2080 }
2081 
2082 /*The mempool is accessed without synchronization*/
2083 MonoMethodSignature*
mono_metadata_signature_dup_mempool(MonoMemPool * mp,MonoMethodSignature * sig)2084 mono_metadata_signature_dup_mempool (MonoMemPool *mp, MonoMethodSignature *sig)
2085 {
2086 	return mono_metadata_signature_dup_internal (NULL, mp, sig);
2087 }
2088 
2089 /**
2090  * mono_metadata_signature_dup:
2091  * \param sig method signature
2092  *
2093  * Duplicate an existing \c MonoMethodSignature so it can be modified.
2094  * This is a Mono runtime internal function.
2095  *
2096  * \returns the new \c MonoMethodSignature structure.
2097  */
2098 MonoMethodSignature*
mono_metadata_signature_dup(MonoMethodSignature * sig)2099 mono_metadata_signature_dup (MonoMethodSignature *sig)
2100 {
2101 	return mono_metadata_signature_dup_full (NULL, sig);
2102 }
2103 
2104 /*
2105  * mono_metadata_signature_size:
2106  *
2107  *   Return the amount of memory allocated to SIG.
2108  */
2109 guint32
mono_metadata_signature_size(MonoMethodSignature * sig)2110 mono_metadata_signature_size (MonoMethodSignature *sig)
2111 {
2112 	return MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
2113 }
2114 
2115 /*
2116  * mono_metadata_parse_method_signature:
2117  * @m: metadata context
2118  * @generic_container: generics container
2119  * @def: the MethodDef index or 0 for Ref signatures.
2120  * @ptr: pointer to the signature metadata representation
2121  * @rptr: pointer updated to match the end of the decoded stream
2122  *
2123  * Decode a method signature stored at @ptr.
2124  * This is a Mono runtime internal function.
2125  *
2126  * LOCKING: Assumes the loader lock is held.
2127  *
2128  * Returns: a MonoMethodSignature describing the signature.
2129  */
2130 MonoMethodSignature *
mono_metadata_parse_method_signature_full(MonoImage * m,MonoGenericContainer * container,int def,const char * ptr,const char ** rptr,MonoError * error)2131 mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container,
2132 					   int def, const char *ptr, const char **rptr, MonoError *error)
2133 {
2134 	MonoMethodSignature *method;
2135 	int i, *pattrs = NULL;
2136 	guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
2137 	guint32 gen_param_count = 0;
2138 	gboolean is_open = FALSE;
2139 
2140 	error_init (error);
2141 
2142 	if (*ptr & 0x10)
2143 		gen_param_count = 1;
2144 	if (*ptr & 0x20)
2145 		hasthis = 1;
2146 	if (*ptr & 0x40)
2147 		explicit_this = 1;
2148 	call_convention = *ptr & 0x0F;
2149 	ptr++;
2150 	if (gen_param_count)
2151 		gen_param_count = mono_metadata_decode_value (ptr, &ptr);
2152 	param_count = mono_metadata_decode_value (ptr, &ptr);
2153 
2154 	if (def)
2155 		pattrs = mono_metadata_get_param_attrs (m, def, param_count + 1); /*Must be + 1 since signature's param count doesn't account for the return value */
2156 
2157 	method = mono_metadata_signature_alloc (m, param_count);
2158 	method->hasthis = hasthis;
2159 	method->explicit_this = explicit_this;
2160 	method->call_convention = call_convention;
2161 	method->generic_param_count = gen_param_count;
2162 
2163 	if (call_convention != 0xa) {
2164 		method->ret = mono_metadata_parse_type_checked (m, container, pattrs ? pattrs [0] : 0, FALSE, ptr, &ptr, error);
2165 		if (!method->ret) {
2166 			mono_metadata_free_method_signature (method);
2167 			g_free (pattrs);
2168 			return NULL;
2169 		}
2170 		is_open = mono_class_is_open_constructed_type (method->ret);
2171 	}
2172 
2173 	for (i = 0; i < method->param_count; ++i) {
2174 		if (*ptr == MONO_TYPE_SENTINEL) {
2175 			if (method->call_convention != MONO_CALL_VARARG || def) {
2176 				mono_error_set_bad_image (error, m, "Found sentinel for methoddef or no vararg");
2177 				g_free (pattrs);
2178 				return NULL;
2179 			}
2180 			if (method->sentinelpos >= 0) {
2181 				mono_error_set_bad_image (error, m, "Found sentinel twice in the same signature.");
2182 				g_free (pattrs);
2183 				return NULL;
2184 			}
2185 			method->sentinelpos = i;
2186 			ptr++;
2187 		}
2188 		method->params [i] = mono_metadata_parse_type_checked (m, container, pattrs ? pattrs [i+1] : 0, FALSE, ptr, &ptr, error);
2189 		if (!method->params [i]) {
2190 			mono_metadata_free_method_signature (method);
2191 			g_free (pattrs);
2192 			return NULL;
2193 		}
2194 		if (!is_open)
2195 			is_open = mono_class_is_open_constructed_type (method->params [i]);
2196 	}
2197 
2198 	/* The sentinel could be missing if the caller does not pass any additional arguments */
2199 	if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0)
2200 		method->sentinelpos = method->param_count;
2201 
2202 	method->has_type_parameters = is_open;
2203 
2204 	if (def && (method->call_convention == MONO_CALL_VARARG))
2205 		method->sentinelpos = method->param_count;
2206 
2207 	g_free (pattrs);
2208 
2209 	if (rptr)
2210 		*rptr = ptr;
2211 	/*
2212 	 * Add signature to a cache and increase ref count...
2213 	 */
2214 
2215 	return method;
2216 }
2217 
2218 /**
2219  * mono_metadata_parse_method_signature:
2220  * \param m metadata context
2221  * \param def the \c MethodDef index or 0 for \c Ref signatures.
2222  * \param ptr pointer to the signature metadata representation
2223  * \param rptr pointer updated to match the end of the decoded stream
2224  *
2225  * Decode a method signature stored at \p ptr.
2226  * This is a Mono runtime internal function.
2227  *
2228  * LOCKING: Assumes the loader lock is held.
2229  *
2230  * \returns a \c MonoMethodSignature describing the signature.
2231  */
2232 MonoMethodSignature *
mono_metadata_parse_method_signature(MonoImage * m,int def,const char * ptr,const char ** rptr)2233 mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
2234 {
2235 	/*
2236 	 * This function MUST NOT be called by runtime code as it does error handling incorrectly.
2237 	 * Use mono_metadata_parse_method_signature_full instead.
2238 	 * It's ok to asser on failure as we no longer use it.
2239 	 */
2240 	MonoError error;
2241 	MonoMethodSignature *ret;
2242 	ret = mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr, &error);
2243 	g_assert (mono_error_ok (&error));
2244 
2245 	return ret;
2246 }
2247 
2248 /**
2249  * mono_metadata_free_method_signature:
2250  * \param sig signature to destroy
2251  *
2252  * Free the memory allocated in the signature \p sig.
2253  * This method needs to be robust and work also on partially-built
2254  * signatures, so it does extra checks.
2255  */
2256 void
mono_metadata_free_method_signature(MonoMethodSignature * sig)2257 mono_metadata_free_method_signature (MonoMethodSignature *sig)
2258 {
2259 	/* Everything is allocated from mempools */
2260 	/*
2261 	int i;
2262 	if (sig->ret)
2263 		mono_metadata_free_type (sig->ret);
2264 	for (i = 0; i < sig->param_count; ++i) {
2265 		if (sig->params [i])
2266 			mono_metadata_free_type (sig->params [i]);
2267 	}
2268 	*/
2269 }
2270 
2271 void
mono_metadata_free_inflated_signature(MonoMethodSignature * sig)2272 mono_metadata_free_inflated_signature (MonoMethodSignature *sig)
2273 {
2274 	int i;
2275 
2276 	/* Allocated in inflate_generic_signature () */
2277 	if (sig->ret)
2278 		mono_metadata_free_type (sig->ret);
2279 	for (i = 0; i < sig->param_count; ++i) {
2280 		if (sig->params [i])
2281 			mono_metadata_free_type (sig->params [i]);
2282 	}
2283 	g_free (sig);
2284 }
2285 
2286 static gboolean
inflated_method_equal(gconstpointer a,gconstpointer b)2287 inflated_method_equal (gconstpointer a, gconstpointer b)
2288 {
2289 	const MonoMethodInflated *ma = (const MonoMethodInflated *)a;
2290 	const MonoMethodInflated *mb = (const MonoMethodInflated *)b;
2291 	if (ma->declaring != mb->declaring)
2292 		return FALSE;
2293 	return mono_metadata_generic_context_equal (&ma->context, &mb->context);
2294 }
2295 
2296 static guint
inflated_method_hash(gconstpointer a)2297 inflated_method_hash (gconstpointer a)
2298 {
2299 	const MonoMethodInflated *ma = (const MonoMethodInflated *)a;
2300 	return (mono_metadata_generic_context_hash (&ma->context) ^ mono_aligned_addr_hash (ma->declaring));
2301 }
2302 
2303 static gboolean
inflated_signature_equal(gconstpointer a,gconstpointer b)2304 inflated_signature_equal (gconstpointer a, gconstpointer b)
2305 {
2306 	const MonoInflatedMethodSignature *sig1 = (const MonoInflatedMethodSignature *)a;
2307 	const MonoInflatedMethodSignature *sig2 = (const MonoInflatedMethodSignature *)b;
2308 
2309 	/* sig->sig is assumed to be canonized */
2310 	if (sig1->sig != sig2->sig)
2311 		return FALSE;
2312 	/* The generic instances are canonized */
2313 	return mono_metadata_generic_context_equal (&sig1->context, &sig2->context);
2314 }
2315 
2316 static guint
inflated_signature_hash(gconstpointer a)2317 inflated_signature_hash (gconstpointer a)
2318 {
2319 	const MonoInflatedMethodSignature *sig = (const MonoInflatedMethodSignature *)a;
2320 
2321 	/* sig->sig is assumed to be canonized */
2322 	return mono_metadata_generic_context_hash (&sig->context) ^ mono_aligned_addr_hash (sig->sig);
2323 }
2324 
2325 /*static void
2326 dump_ginst (MonoGenericInst *ginst)
2327 {
2328 	int i;
2329 	char *name;
2330 
2331 	g_print ("Ginst: <");
2332 	for (i = 0; i < ginst->type_argc; ++i) {
2333 		if (i != 0)
2334 			g_print (", ");
2335 		name = mono_type_get_name (ginst->type_argv [i]);
2336 		g_print ("%s", name);
2337 		g_free (name);
2338 	}
2339 	g_print (">");
2340 }*/
2341 
2342 static gboolean type_in_image (MonoType *type, MonoImage *image);
2343 
2344 static gboolean
signature_in_image(MonoMethodSignature * sig,MonoImage * image)2345 signature_in_image (MonoMethodSignature *sig, MonoImage *image)
2346 {
2347 	gpointer iter = NULL;
2348 	MonoType *p;
2349 
2350 	while ((p = mono_signature_get_params (sig, &iter)) != NULL)
2351 		if (type_in_image (p, image))
2352 			return TRUE;
2353 
2354 	return type_in_image (mono_signature_get_return_type (sig), image);
2355 }
2356 
2357 static gboolean
ginst_in_image(MonoGenericInst * ginst,MonoImage * image)2358 ginst_in_image (MonoGenericInst *ginst, MonoImage *image)
2359 {
2360 	int i;
2361 
2362 	for (i = 0; i < ginst->type_argc; ++i) {
2363 		if (type_in_image (ginst->type_argv [i], image))
2364 			return TRUE;
2365 	}
2366 
2367 	return FALSE;
2368 }
2369 
2370 static gboolean
gclass_in_image(MonoGenericClass * gclass,MonoImage * image)2371 gclass_in_image (MonoGenericClass *gclass, MonoImage *image)
2372 {
2373 	return gclass->container_class->image == image ||
2374 		ginst_in_image (gclass->context.class_inst, image);
2375 }
2376 
2377 static gboolean
type_in_image(MonoType * type,MonoImage * image)2378 type_in_image (MonoType *type, MonoImage *image)
2379 {
2380 retry:
2381 	switch (type->type) {
2382 	case MONO_TYPE_GENERICINST:
2383 		return gclass_in_image (type->data.generic_class, image);
2384 	case MONO_TYPE_PTR:
2385 		type = type->data.type;
2386 		goto retry;
2387 	case MONO_TYPE_SZARRAY:
2388 		type = &type->data.klass->byval_arg;
2389 		goto retry;
2390 	case MONO_TYPE_ARRAY:
2391 		type = &type->data.array->eklass->byval_arg;
2392 		goto retry;
2393 	case MONO_TYPE_FNPTR:
2394 		return signature_in_image (type->data.method, image);
2395 	case MONO_TYPE_VAR:
2396 	case MONO_TYPE_MVAR:
2397 		return image == get_image_for_generic_param (type->data.generic_param);
2398 	default:
2399 		/* At this point, we should've avoided all potential allocations in mono_class_from_mono_type () */
2400 		return image == mono_class_from_mono_type (type)->image;
2401 	}
2402 }
2403 
2404 static inline void
image_sets_lock(void)2405 image_sets_lock (void)
2406 {
2407 	mono_os_mutex_lock (&image_sets_mutex);
2408 }
2409 
2410 static inline void
image_sets_unlock(void)2411 image_sets_unlock (void)
2412 {
2413 	mono_os_mutex_unlock (&image_sets_mutex);
2414 }
2415 
2416 static int
compare_pointers(const void * a,const void * b)2417 compare_pointers (const void *a, const void *b)
2418 {
2419 	return (size_t)a - (size_t)b;
2420 }
2421 
2422 //1103, 1327, 1597
2423 #define HASH_TABLE_SIZE 1103
2424 static MonoImageSet *img_set_cache [HASH_TABLE_SIZE];
2425 
2426 static guint32
mix_hash(uintptr_t source)2427 mix_hash (uintptr_t source)
2428 {
2429 	unsigned int hash = source;
2430 
2431 	// Actual hash
2432 	hash = (((hash * 215497) >> 16) ^ ((hash * 1823231) + hash));
2433 
2434 	// Mix in highest bits on 64-bit systems only
2435 	if (sizeof (source) > 4)
2436 		hash = hash ^ (source >> 32);
2437 
2438 	return hash;
2439 }
2440 
2441 static guint32
hash_images(MonoImage ** images,int nimages)2442 hash_images (MonoImage **images, int nimages)
2443 {
2444 	guint32 res = 0;
2445 	int i;
2446 	for (i = 0; i < nimages; ++i)
2447 		res += mix_hash ((size_t)images [i]);
2448 
2449 	return res;
2450 }
2451 
2452 static gboolean
compare_img_set(MonoImageSet * set,MonoImage ** images,int nimages)2453 compare_img_set (MonoImageSet *set, MonoImage **images, int nimages)
2454 {
2455 	int j, k;
2456 
2457 	if (set->nimages != nimages)
2458 		return FALSE;
2459 
2460 	for (j = 0; j < nimages; ++j) {
2461 		for (k = 0; k < nimages; ++k)
2462 			if (set->images [k] == images [j])
2463 				break; // Break on match
2464 
2465 		// If we iterated all the way through set->images, images[j] was *not* found.
2466 		if (k == nimages)
2467 			break; // Break on "image not found"
2468 	}
2469 
2470 	// If we iterated all the way through images without breaking, all items in images were found in set->images
2471 	return j == nimages;
2472 }
2473 
2474 
2475 static MonoImageSet*
img_set_cache_get(MonoImage ** images,int nimages)2476 img_set_cache_get (MonoImage **images, int nimages)
2477 {
2478 	guint32 hash_code = hash_images (images, nimages);
2479 	int index = hash_code % HASH_TABLE_SIZE;
2480 	MonoImageSet *img = img_set_cache [index];
2481 	if (!img || !compare_img_set (img, images, nimages)) {
2482 		UnlockedIncrement (&img_set_cache_miss);
2483 		return NULL;
2484 	}
2485 	UnlockedIncrement (&img_set_cache_hit);
2486 	return img;
2487 }
2488 
2489 static void
img_set_cache_add(MonoImageSet * set)2490 img_set_cache_add (MonoImageSet *set)
2491 {
2492 	guint32 hash_code = hash_images (set->images, set->nimages);
2493 	int index = hash_code % HASH_TABLE_SIZE;
2494 	img_set_cache [index] = set;
2495 }
2496 
2497 static void
img_set_cache_remove(MonoImageSet * is)2498 img_set_cache_remove (MonoImageSet *is)
2499 {
2500 	guint32 hash_code = hash_images (is->images, is->nimages);
2501 	int index = hash_code % HASH_TABLE_SIZE;
2502 	if (img_set_cache [index] == is)
2503 		img_set_cache [index] = NULL;
2504 }
2505 /*
2506  * get_image_set:
2507  *
2508  *   Return a MonoImageSet representing the set of images in IMAGES.
2509  */
2510 static MonoImageSet*
get_image_set(MonoImage ** images,int nimages)2511 get_image_set (MonoImage **images, int nimages)
2512 {
2513 	int i, j, k;
2514 	MonoImageSet *set;
2515 	GSList *l;
2516 
2517 	/* Common case: Image set contains corlib only. If we've seen that case before, we cached the set. */
2518 	if (nimages == 1 && images [0] == mono_defaults.corlib && mscorlib_image_set)
2519 		return mscorlib_image_set;
2520 
2521 	/* Happens with empty generic instances */
2522 	// FIXME: Is corlib the correct thing to return here? If so, why? This may be an artifact of generic instances previously defaulting to allocating from corlib.
2523 	if (nimages == 0)
2524 		return mscorlib_image_set;
2525 
2526 	set = img_set_cache_get (images, nimages);
2527 	if (set)
2528 		return set;
2529 
2530 	image_sets_lock ();
2531 
2532 	if (!image_sets)
2533 		image_sets = g_ptr_array_new ();
2534 
2535 	// Before we go on, we should check to see whether a MonoImageSet with these images already exists.
2536 	// We can search the referred-by imagesets of any one of our images to do this. Arbitrarily pick one here:
2537 	if (images [0] == mono_defaults.corlib && nimages > 1)
2538 		l = images [1]->image_sets; // Prefer not to search the imagesets of corlib-- that will be a long list.
2539 	else
2540 		l = images [0]->image_sets;
2541 
2542 	set = NULL;
2543 	while (l) // Iterate over selected list, looking for an imageset with members equal to our target one
2544 	{
2545 		set = (MonoImageSet *)l->data;
2546 
2547 		if (set->nimages == nimages) { // Member count differs, this can't be it
2548 			// Compare all members to all members-- order might be different
2549 			for (j = 0; j < nimages; ++j) {
2550 				for (k = 0; k < nimages; ++k)
2551 					if (set->images [k] == images [j])
2552 						break; // Break on match
2553 
2554 				// If we iterated all the way through set->images, images[j] was *not* found.
2555 				if (k == nimages)
2556 					break; // Break on "image not found"
2557 			}
2558 
2559 			// If we iterated all the way through images without breaking, all items in images were found in set->images
2560 			if (j == nimages) {
2561 				// Break on "found a set with equal members".
2562 				// This happens in case of a hash collision with a previously cached set.
2563 				break;
2564 			}
2565 		}
2566 
2567 		l = l->next;
2568 	}
2569 
2570 	// If we iterated all the way through l without breaking, the imageset does not already exist and we should create it
2571 	if (!l) {
2572 		set = g_new0 (MonoImageSet, 1);
2573 		set->nimages = nimages;
2574 		set->images = g_new0 (MonoImage*, nimages);
2575 		mono_os_mutex_init_recursive (&set->lock);
2576 		for (i = 0; i < nimages; ++i)
2577 			set->images [i] = images [i];
2578 		set->gclass_cache = mono_conc_hashtable_new_full (mono_generic_class_hash, mono_generic_class_equal, NULL, (GDestroyNotify)free_generic_class);
2579 		set->ginst_cache = g_hash_table_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst);
2580 		set->gmethod_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method);
2581 		set->gsignature_cache = g_hash_table_new_full (inflated_signature_hash, inflated_signature_equal, NULL, (GDestroyNotify)free_inflated_signature);
2582 
2583 		set->szarray_cache = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, NULL);
2584 		set->array_cache = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, NULL);
2585 
2586 		for (i = 0; i < nimages; ++i)
2587 			set->images [i]->image_sets = g_slist_prepend (set->images [i]->image_sets, set);
2588 
2589 		g_ptr_array_add (image_sets, set);
2590 		UnlockedIncrement (&img_set_count); /* locked by image_sets_lock () */
2591 	}
2592 
2593 	/* Cache the set. If there was a cache collision, the previously cached value will be replaced. */
2594 	img_set_cache_add (set);
2595 
2596 	if (nimages == 1 && images [0] == mono_defaults.corlib) {
2597 		mono_memory_barrier ();
2598 		mscorlib_image_set = set;
2599 	}
2600 
2601 	image_sets_unlock ();
2602 
2603 	return set;
2604 }
2605 
2606 static void
delete_image_set(MonoImageSet * set)2607 delete_image_set (MonoImageSet *set)
2608 {
2609 	int i;
2610 
2611 	mono_conc_hashtable_destroy (set->gclass_cache);
2612 	g_hash_table_destroy (set->ginst_cache);
2613 	g_hash_table_destroy (set->gmethod_cache);
2614 	g_hash_table_destroy (set->gsignature_cache);
2615 
2616 	g_hash_table_destroy (set->szarray_cache);
2617 	g_hash_table_destroy (set->array_cache);
2618 	if (set->ptr_cache)
2619 		g_hash_table_destroy (set->ptr_cache);
2620 
2621 	mono_wrapper_caches_free (&set->wrapper_caches);
2622 
2623 	image_sets_lock ();
2624 
2625 	for (i = 0; i < set->nimages; ++i)
2626 		set->images [i]->image_sets = g_slist_remove (set->images [i]->image_sets, set);
2627 
2628 	g_ptr_array_remove (image_sets, set);
2629 
2630 	image_sets_unlock ();
2631 
2632 	img_set_cache_remove (set);
2633 
2634 	if (set->mempool)
2635 		mono_mempool_destroy (set->mempool);
2636 	g_free (set->images);
2637 	mono_os_mutex_destroy (&set->lock);
2638 	g_free (set);
2639 }
2640 
2641 void
mono_image_set_lock(MonoImageSet * set)2642 mono_image_set_lock (MonoImageSet *set)
2643 {
2644 	mono_os_mutex_lock (&set->lock);
2645 }
2646 
2647 void
mono_image_set_unlock(MonoImageSet * set)2648 mono_image_set_unlock (MonoImageSet *set)
2649 {
2650 	mono_os_mutex_unlock (&set->lock);
2651 }
2652 
2653 gpointer
mono_image_set_alloc(MonoImageSet * set,guint size)2654 mono_image_set_alloc (MonoImageSet *set, guint size)
2655 {
2656 	gpointer res;
2657 
2658 	mono_image_set_lock (set);
2659 	if (!set->mempool)
2660 		set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE);
2661 	res = mono_mempool_alloc (set->mempool, size);
2662 	mono_image_set_unlock (set);
2663 
2664 	return res;
2665 }
2666 
2667 gpointer
mono_image_set_alloc0(MonoImageSet * set,guint size)2668 mono_image_set_alloc0 (MonoImageSet *set, guint size)
2669 {
2670 	gpointer res;
2671 
2672 	mono_image_set_lock (set);
2673 	if (!set->mempool)
2674 		set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE);
2675 	res = mono_mempool_alloc0 (set->mempool, size);
2676 	mono_image_set_unlock (set);
2677 
2678 	return res;
2679 }
2680 
2681 char*
mono_image_set_strdup(MonoImageSet * set,const char * s)2682 mono_image_set_strdup (MonoImageSet *set, const char *s)
2683 {
2684 	char *res;
2685 
2686 	mono_image_set_lock (set);
2687 	if (!set->mempool)
2688 		set->mempool = mono_mempool_new_size (INITIAL_IMAGE_SET_SIZE);
2689 	res = mono_mempool_strdup (set->mempool, s);
2690 	mono_image_set_unlock (set);
2691 
2692 	return res;
2693 }
2694 
2695 // Get a descriptive string for a MonoImageSet
2696 // Callers are obligated to free buffer with g_free after use
2697 char *
mono_image_set_description(MonoImageSet * set)2698 mono_image_set_description (MonoImageSet *set)
2699 {
2700 	GString *result = g_string_new (NULL);
2701 	int img;
2702 	g_string_append (result, "[");
2703 	for (img = 0; img < set->nimages; img++)
2704 	{
2705 		if (img > 0)
2706 			g_string_append (result, ", ");
2707 		g_string_append (result, set->images[img]->name);
2708 	}
2709 	g_string_append (result, "]");
2710 	return g_string_free (result, FALSE);
2711 }
2712 
2713 /*
2714  * Structure used by the collect_..._images functions to store the image list.
2715  */
2716 typedef struct {
2717 	MonoImage *image_buf [64];
2718 	MonoImage **images;
2719 	int nimages, images_len;
2720 } CollectData;
2721 
2722 static void
collect_data_init(CollectData * data)2723 collect_data_init (CollectData *data)
2724 {
2725 	data->images = data->image_buf;
2726 	data->images_len = 64;
2727 	data->nimages = 0;
2728 }
2729 
2730 static void
collect_data_free(CollectData * data)2731 collect_data_free (CollectData *data)
2732 {
2733 	if (data->images != data->image_buf)
2734 		g_free (data->images);
2735 }
2736 
2737 static void
enlarge_data(CollectData * data)2738 enlarge_data (CollectData *data)
2739 {
2740 	int new_len = data->images_len < 16 ? 16 : data->images_len * 2;
2741 	MonoImage **d = g_new (MonoImage *, new_len);
2742 
2743 	// FIXME: test this
2744 	g_assert_not_reached ();
2745 	memcpy (d, data->images, data->images_len);
2746 	if (data->images != data->image_buf)
2747 		g_free (data->images);
2748 	data->images = d;
2749 	data->images_len = new_len;
2750 }
2751 
2752 static inline void
add_image(MonoImage * image,CollectData * data)2753 add_image (MonoImage *image, CollectData *data)
2754 {
2755 	int i;
2756 
2757 	/* The arrays are small, so use a linear search instead of a hash table */
2758 	for (i = 0; i < data->nimages; ++i)
2759 		if (data->images [i] == image)
2760 			return;
2761 
2762 	if (data->nimages == data->images_len)
2763 		enlarge_data (data);
2764 
2765 	data->images [data->nimages ++] = image;
2766 }
2767 
2768 static void
2769 collect_type_images (MonoType *type, CollectData *data);
2770 
2771 static void
collect_ginst_images(MonoGenericInst * ginst,CollectData * data)2772 collect_ginst_images (MonoGenericInst *ginst, CollectData *data)
2773 {
2774 	int i;
2775 
2776 	for (i = 0; i < ginst->type_argc; ++i) {
2777 		collect_type_images (ginst->type_argv [i], data);
2778 	}
2779 }
2780 
2781 static void
collect_gclass_images(MonoGenericClass * gclass,CollectData * data)2782 collect_gclass_images (MonoGenericClass *gclass, CollectData *data)
2783 {
2784 	add_image (gclass->container_class->image, data);
2785 	if (gclass->context.class_inst)
2786 		collect_ginst_images (gclass->context.class_inst, data);
2787 }
2788 
2789 static void
collect_signature_images(MonoMethodSignature * sig,CollectData * data)2790 collect_signature_images (MonoMethodSignature *sig, CollectData *data)
2791 {
2792 	gpointer iter = NULL;
2793 	MonoType *p;
2794 
2795 	collect_type_images (mono_signature_get_return_type (sig), data);
2796 	while ((p = mono_signature_get_params (sig, &iter)) != NULL)
2797 		collect_type_images (p, data);
2798 }
2799 
2800 static void
collect_inflated_signature_images(MonoInflatedMethodSignature * sig,CollectData * data)2801 collect_inflated_signature_images (MonoInflatedMethodSignature *sig, CollectData *data)
2802 {
2803 	collect_signature_images (sig->sig, data);
2804 	if (sig->context.class_inst)
2805 		collect_ginst_images (sig->context.class_inst, data);
2806 	if (sig->context.method_inst)
2807 		collect_ginst_images (sig->context.method_inst, data);
2808 }
2809 
2810 static void
collect_method_images(MonoMethodInflated * method,CollectData * data)2811 collect_method_images (MonoMethodInflated *method, CollectData *data)
2812 {
2813 	MonoMethod *m = method->declaring;
2814 
2815 	add_image (method->declaring->klass->image, data);
2816 	if (method->context.class_inst)
2817 		collect_ginst_images (method->context.class_inst, data);
2818 	if (method->context.method_inst)
2819 		collect_ginst_images (method->context.method_inst, data);
2820 	/*
2821 	 * Dynamic assemblies have no references, so the images they depend on can be unloaded before them.
2822 	 */
2823 	if (image_is_dynamic (m->klass->image))
2824 		collect_signature_images (mono_method_signature (m), data);
2825 }
2826 
2827 static void
collect_type_images(MonoType * type,CollectData * data)2828 collect_type_images (MonoType *type, CollectData *data)
2829 {
2830 retry:
2831 	switch (type->type) {
2832 	case MONO_TYPE_GENERICINST:
2833 		collect_gclass_images (type->data.generic_class, data);
2834 		break;
2835 	case MONO_TYPE_PTR:
2836 		type = type->data.type;
2837 		goto retry;
2838 	case MONO_TYPE_SZARRAY:
2839 		type = &type->data.klass->byval_arg;
2840 		goto retry;
2841 	case MONO_TYPE_ARRAY:
2842 		type = &type->data.array->eklass->byval_arg;
2843 		goto retry;
2844 	case MONO_TYPE_FNPTR:
2845 		//return signature_in_image (type->data.method, image);
2846 		g_assert_not_reached ();
2847 	case MONO_TYPE_VAR:
2848 	case MONO_TYPE_MVAR:
2849 	{
2850 		MonoImage *image = get_image_for_generic_param (type->data.generic_param);
2851 		add_image (image, data);
2852 		break;
2853 	}
2854 	case MONO_TYPE_CLASS:
2855 	case MONO_TYPE_VALUETYPE:
2856 		add_image (mono_class_from_mono_type (type)->image, data);
2857 		break;
2858 	default:
2859 		add_image (mono_defaults.corlib, data);
2860 	}
2861 }
2862 
2863 typedef struct {
2864 	MonoImage *image;
2865 	GSList *list;
2866 } CleanForImageUserData;
2867 
2868 static gboolean
steal_gclass_in_image(gpointer key,gpointer value,gpointer data)2869 steal_gclass_in_image (gpointer key, gpointer value, gpointer data)
2870 {
2871 	MonoGenericClass *gclass = (MonoGenericClass *)key;
2872 	CleanForImageUserData *user_data = (CleanForImageUserData *)data;
2873 
2874 	g_assert (gclass_in_image (gclass, user_data->image));
2875 
2876 	user_data->list = g_slist_prepend (user_data->list, gclass);
2877 	return TRUE;
2878 }
2879 
2880 static gboolean
steal_ginst_in_image(gpointer key,gpointer value,gpointer data)2881 steal_ginst_in_image (gpointer key, gpointer value, gpointer data)
2882 {
2883 	MonoGenericInst *ginst = (MonoGenericInst *)key;
2884 	CleanForImageUserData *user_data = (CleanForImageUserData *)data;
2885 
2886 	// This doesn't work during corlib compilation
2887 	//g_assert (ginst_in_image (ginst, user_data->image));
2888 
2889 	user_data->list = g_slist_prepend (user_data->list, ginst);
2890 	return TRUE;
2891 }
2892 
2893 static gboolean
inflated_method_in_image(gpointer key,gpointer value,gpointer data)2894 inflated_method_in_image (gpointer key, gpointer value, gpointer data)
2895 {
2896 	MonoImage *image = (MonoImage *)data;
2897 	MonoMethodInflated *method = (MonoMethodInflated *)key;
2898 
2899 	// FIXME:
2900 	// https://bugzilla.novell.com/show_bug.cgi?id=458168
2901 	g_assert (method->declaring->klass->image == image ||
2902 		(method->context.class_inst && ginst_in_image (method->context.class_inst, image)) ||
2903 			  (method->context.method_inst && ginst_in_image (method->context.method_inst, image)) || (((MonoMethod*)method)->signature && signature_in_image (mono_method_signature ((MonoMethod*)method), image)));
2904 
2905 	return TRUE;
2906 }
2907 
2908 static gboolean
inflated_signature_in_image(gpointer key,gpointer value,gpointer data)2909 inflated_signature_in_image (gpointer key, gpointer value, gpointer data)
2910 {
2911 	MonoImage *image = (MonoImage *)data;
2912 	MonoInflatedMethodSignature *sig = (MonoInflatedMethodSignature *)key;
2913 
2914 	return signature_in_image (sig->sig, image) ||
2915 		(sig->context.class_inst && ginst_in_image (sig->context.class_inst, image)) ||
2916 		(sig->context.method_inst && ginst_in_image (sig->context.method_inst, image));
2917 }
2918 
2919 static gboolean
class_in_image(gpointer key,gpointer value,gpointer data)2920 class_in_image (gpointer key, gpointer value, gpointer data)
2921 {
2922 	MonoImage *image = (MonoImage *)data;
2923 	MonoClass *klass = (MonoClass *)key;
2924 
2925 	g_assert (type_in_image (&klass->byval_arg, image));
2926 
2927 	return TRUE;
2928 }
2929 
2930 static void
check_gmethod(gpointer key,gpointer value,gpointer data)2931 check_gmethod (gpointer key, gpointer value, gpointer data)
2932 {
2933 	MonoMethodInflated *method = (MonoMethodInflated *)key;
2934 	MonoImage *image = (MonoImage *)data;
2935 
2936 	if (method->context.class_inst)
2937 		g_assert (!ginst_in_image (method->context.class_inst, image));
2938 	if (method->context.method_inst)
2939 		g_assert (!ginst_in_image (method->context.method_inst, image));
2940 	if (((MonoMethod*)method)->signature)
2941 		g_assert (!signature_in_image (mono_method_signature ((MonoMethod*)method), image));
2942 }
2943 
2944 /*
2945  * check_image_sets:
2946  *
2947  *   Run a consistency check on the image set data structures.
2948  */
2949 static G_GNUC_UNUSED void
check_image_sets(MonoImage * image)2950 check_image_sets (MonoImage *image)
2951 {
2952 	int i;
2953 	GSList *l = image->image_sets;
2954 
2955 	if (!image_sets)
2956 		return;
2957 
2958 	for (i = 0; i < image_sets->len; ++i) {
2959 		MonoImageSet *set = (MonoImageSet *)g_ptr_array_index (image_sets, i);
2960 
2961 		if (!g_slist_find (l, set)) {
2962 			g_hash_table_foreach (set->gmethod_cache, check_gmethod, image);
2963 		}
2964 	}
2965 }
2966 
2967 void
mono_metadata_clean_for_image(MonoImage * image)2968 mono_metadata_clean_for_image (MonoImage *image)
2969 {
2970 	CleanForImageUserData ginst_data, gclass_data;
2971 	GSList *l, *set_list;
2972 
2973 	//check_image_sets (image);
2974 
2975 	/*
2976 	 * The data structures could reference each other so we delete them in two phases.
2977 	 * This is required because of the hashing functions in gclass/ginst_cache.
2978 	 */
2979 	ginst_data.image = gclass_data.image = image;
2980 	ginst_data.list = gclass_data.list = NULL;
2981 
2982 	/* Collect the items to delete */
2983 	/* delete_image_set () modifies the lists so make a copy */
2984 	for (l = image->image_sets; l; l = l->next) {
2985 		MonoImageSet *set = (MonoImageSet *)l->data;
2986 
2987 		mono_image_set_lock (set);
2988 		mono_conc_hashtable_foreach_steal (set->gclass_cache, steal_gclass_in_image, &gclass_data);
2989 		g_hash_table_foreach_steal (set->ginst_cache, steal_ginst_in_image, &ginst_data);
2990 		g_hash_table_foreach_remove (set->gmethod_cache, inflated_method_in_image, image);
2991 		g_hash_table_foreach_remove (set->gsignature_cache, inflated_signature_in_image, image);
2992 
2993 		g_hash_table_foreach_steal (set->szarray_cache, class_in_image, image);
2994 		g_hash_table_foreach_steal (set->array_cache, class_in_image, image);
2995 		if (set->ptr_cache)
2996 			g_hash_table_foreach_steal (set->ptr_cache, class_in_image, image);
2997 		mono_image_set_unlock (set);
2998 	}
2999 
3000 	/* Delete the removed items */
3001 	for (l = ginst_data.list; l; l = l->next)
3002 		free_generic_inst ((MonoGenericInst *)l->data);
3003 	for (l = gclass_data.list; l; l = l->next)
3004 		free_generic_class ((MonoGenericClass *)l->data);
3005 	g_slist_free (ginst_data.list);
3006 	g_slist_free (gclass_data.list);
3007 	/* delete_image_set () modifies the lists so make a copy */
3008 	set_list = g_slist_copy (image->image_sets);
3009 	for (l = set_list; l; l = l->next) {
3010 		MonoImageSet *set = (MonoImageSet *)l->data;
3011 
3012 		delete_image_set (set);
3013 	}
3014 	g_slist_free (set_list);
3015 }
3016 
3017 static void
free_inflated_method(MonoMethodInflated * imethod)3018 free_inflated_method (MonoMethodInflated *imethod)
3019 {
3020 	MonoMethod *method = (MonoMethod*)imethod;
3021 
3022 	if (method->signature)
3023 		mono_metadata_free_inflated_signature (method->signature);
3024 
3025 	if (method->wrapper_type)
3026 		g_free (((MonoMethodWrapper*)method)->method_data);
3027 
3028 	g_free (method);
3029 }
3030 
3031 static void
free_generic_inst(MonoGenericInst * ginst)3032 free_generic_inst (MonoGenericInst *ginst)
3033 {
3034 	int i;
3035 
3036 	/* The ginst itself is allocated from the image set mempool */
3037 	for (i = 0; i < ginst->type_argc; ++i)
3038 		mono_metadata_free_type (ginst->type_argv [i]);
3039 }
3040 
3041 static void
free_generic_class(MonoGenericClass * gclass)3042 free_generic_class (MonoGenericClass *gclass)
3043 {
3044 	/* The gclass itself is allocated from the image set mempool */
3045 	if (gclass->cached_class && gclass->cached_class->interface_id)
3046 		mono_unload_interface_id (gclass->cached_class);
3047 }
3048 
3049 static void
free_inflated_signature(MonoInflatedMethodSignature * sig)3050 free_inflated_signature (MonoInflatedMethodSignature *sig)
3051 {
3052 	mono_metadata_free_inflated_signature (sig->sig);
3053 	g_free (sig);
3054 }
3055 
3056 /*
3057  * mono_metadata_get_inflated_signature:
3058  *
3059  *   Given an inflated signature and a generic context, return a canonical copy of the
3060  * signature. The returned signature might be equal to SIG or it might be a cached copy.
3061  */
3062 MonoMethodSignature *
mono_metadata_get_inflated_signature(MonoMethodSignature * sig,MonoGenericContext * context)3063 mono_metadata_get_inflated_signature (MonoMethodSignature *sig, MonoGenericContext *context)
3064 {
3065 	MonoInflatedMethodSignature helper;
3066 	MonoInflatedMethodSignature *res;
3067 	CollectData data;
3068 	MonoImageSet *set;
3069 
3070 	helper.sig = sig;
3071 	helper.context.class_inst = context->class_inst;
3072 	helper.context.method_inst = context->method_inst;
3073 
3074 	collect_data_init (&data);
3075 
3076 	collect_inflated_signature_images (&helper, &data);
3077 
3078 	set = get_image_set (data.images, data.nimages);
3079 
3080 	collect_data_free (&data);
3081 
3082 	mono_image_set_lock (set);
3083 
3084 	res = (MonoInflatedMethodSignature *)g_hash_table_lookup (set->gsignature_cache, &helper);
3085 	if (!res) {
3086 		res = g_new0 (MonoInflatedMethodSignature, 1);
3087 		res->sig = sig;
3088 		res->context.class_inst = context->class_inst;
3089 		res->context.method_inst = context->method_inst;
3090 		g_hash_table_insert (set->gsignature_cache, res, res);
3091 	}
3092 
3093 	mono_image_set_unlock (set);
3094 
3095 	return res->sig;
3096 }
3097 
3098 MonoImageSet *
mono_metadata_get_image_set_for_class(MonoClass * klass)3099 mono_metadata_get_image_set_for_class (MonoClass *klass)
3100 {
3101 	MonoImageSet *set;
3102 	CollectData image_set_data;
3103 
3104 	collect_data_init (&image_set_data);
3105 	collect_type_images (&klass->byval_arg, &image_set_data);
3106 	set = get_image_set (image_set_data.images, image_set_data.nimages);
3107 	collect_data_free (&image_set_data);
3108 
3109 	return set;
3110 }
3111 
3112 MonoImageSet *
mono_metadata_get_image_set_for_method(MonoMethodInflated * method)3113 mono_metadata_get_image_set_for_method (MonoMethodInflated *method)
3114 {
3115 	MonoImageSet *set;
3116 	CollectData image_set_data;
3117 
3118 	collect_data_init (&image_set_data);
3119 	collect_method_images (method, &image_set_data);
3120 	set = get_image_set (image_set_data.images, image_set_data.nimages);
3121 	collect_data_free (&image_set_data);
3122 
3123 	return set;
3124 }
3125 
3126 static gboolean
type_is_gtd(MonoType * type)3127 type_is_gtd (MonoType *type)
3128 {
3129 	switch (type->type) {
3130 	case MONO_TYPE_CLASS:
3131 	case MONO_TYPE_VALUETYPE:
3132 		return mono_class_is_gtd (type->data.klass);
3133 	default:
3134 		return FALSE;
3135 	}
3136 }
3137 
3138 /*
3139  * mono_metadata_get_generic_inst:
3140  *
3141  * Given a list of types, return a MonoGenericInst that represents that list.
3142  * The returned MonoGenericInst has its own copy of the list of types.  The list
3143  * passed in the argument can be freed, modified or disposed of.
3144  *
3145  */
3146 MonoGenericInst *
mono_metadata_get_generic_inst(int type_argc,MonoType ** type_argv)3147 mono_metadata_get_generic_inst (int type_argc, MonoType **type_argv)
3148 {
3149 	MonoGenericInst *ginst;
3150 	gboolean is_open;
3151 	int i;
3152 	int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
3153 
3154 	for (i = 0; i < type_argc; ++i)
3155 		if (mono_class_is_open_constructed_type (type_argv [i]))
3156 			break;
3157 	is_open = (i < type_argc);
3158 
3159 	ginst = (MonoGenericInst *)g_alloca (size);
3160 	memset (ginst, 0, sizeof (MonoGenericInst));
3161 	ginst->is_open = is_open;
3162 	ginst->type_argc = type_argc;
3163 	memcpy (ginst->type_argv, type_argv, type_argc * sizeof (MonoType *));
3164 
3165 	for (i = 0; i < type_argc; ++i) {
3166 		MonoType *t = ginst->type_argv [i];
3167 		if (type_is_gtd (t)) {
3168 			ginst->type_argv [i] = mono_class_gtd_get_canonical_inst (t->data.klass);
3169 		}
3170 	}
3171 
3172 	return mono_metadata_get_canonical_generic_inst (ginst);
3173 }
3174 
3175 
3176 /**
3177  * mono_metadata_get_canonical_generic_inst:
3178  * \param candidate an arbitrary generic instantiation
3179  *
3180  * \returns the canonical generic instantiation that represents the given
3181  * candidate by identifying the image set for the candidate instantiation and
3182  * finding the instance in the image set or adding a copy of the given instance
3183  * to the image set.
3184  *
3185  * The returned MonoGenericInst has its own copy of the list of types.  The list
3186  * passed in the argument can be freed, modified or disposed of.
3187  *
3188  */
3189 MonoGenericInst *
mono_metadata_get_canonical_generic_inst(MonoGenericInst * candidate)3190 mono_metadata_get_canonical_generic_inst (MonoGenericInst *candidate)
3191 {
3192 	CollectData data;
3193 	int type_argc = candidate->type_argc;
3194 	gboolean is_open = candidate->is_open;
3195 	MonoImageSet *set;
3196 
3197 	collect_data_init (&data);
3198 
3199 	collect_ginst_images (candidate, &data);
3200 
3201 	set = get_image_set (data.images, data.nimages);
3202 
3203 	collect_data_free (&data);
3204 
3205 	mono_image_set_lock (set);
3206 
3207 	MonoGenericInst *ginst = (MonoGenericInst *)g_hash_table_lookup (set->ginst_cache, candidate);
3208 	if (!ginst) {
3209 		int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
3210 		ginst = (MonoGenericInst *)mono_image_set_alloc0 (set, size);
3211 #ifndef MONO_SMALL_CONFIG
3212 		ginst->id = mono_atomic_inc_i32 (&next_generic_inst_id);
3213 #endif
3214 		ginst->is_open = is_open;
3215 		ginst->type_argc = type_argc;
3216 
3217 		for (int i = 0; i < type_argc; ++i)
3218 			ginst->type_argv [i] = mono_metadata_type_dup (NULL, candidate->type_argv [i]);
3219 
3220 		g_hash_table_insert (set->ginst_cache, ginst, ginst);
3221 	}
3222 
3223 	mono_image_set_unlock (set);
3224 	return ginst;
3225 }
3226 
3227 static gboolean
mono_metadata_is_type_builder_generic_type_definition(MonoClass * container_class,MonoGenericInst * inst,gboolean is_dynamic)3228 mono_metadata_is_type_builder_generic_type_definition (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
3229 {
3230 	MonoGenericContainer *container = mono_class_get_generic_container (container_class);
3231 
3232 	if (!is_dynamic || container_class->wastypebuilder || container->type_argc != inst->type_argc)
3233 		return FALSE;
3234 	return inst == container->context.class_inst;
3235 }
3236 
3237 /*
3238  * mono_metadata_lookup_generic_class:
3239  *
3240  * Returns a MonoGenericClass with the given properties.
3241  *
3242  */
3243 MonoGenericClass *
mono_metadata_lookup_generic_class(MonoClass * container_class,MonoGenericInst * inst,gboolean is_dynamic)3244 mono_metadata_lookup_generic_class (MonoClass *container_class, MonoGenericInst *inst, gboolean is_dynamic)
3245 {
3246 	MonoGenericClass *gclass;
3247 	MonoGenericClass helper;
3248 	gboolean is_tb_open = mono_metadata_is_type_builder_generic_type_definition (container_class, inst, is_dynamic);
3249 	MonoImageSet *set;
3250 	CollectData data;
3251 
3252 	g_assert (mono_class_get_generic_container (container_class)->type_argc == inst->type_argc);
3253 
3254 	memset (&helper, 0, sizeof(helper)); // act like g_new0
3255 	helper.container_class = container_class;
3256 	helper.context.class_inst = inst;
3257 	helper.is_dynamic = is_dynamic; /* We use this in a hash lookup, which does not attempt to downcast the pointer */
3258 	helper.is_tb_open = is_tb_open;
3259 
3260 	collect_data_init (&data);
3261 
3262 	collect_gclass_images (&helper, &data);
3263 
3264 	set = get_image_set (data.images, data.nimages);
3265 
3266 	collect_data_free (&data);
3267 
3268 	gclass = (MonoGenericClass *)mono_conc_hashtable_lookup (set->gclass_cache, &helper);
3269 
3270 	/* A tripwire just to keep us honest */
3271 	g_assert (!helper.cached_class);
3272 
3273 	if (gclass)
3274 		return gclass;
3275 
3276 	gclass = mono_image_set_new0 (set, MonoGenericClass, 1);
3277 	if (is_dynamic)
3278 		gclass->is_dynamic = 1;
3279 
3280 	gclass->is_tb_open = is_tb_open;
3281 	gclass->container_class = container_class;
3282 	gclass->context.class_inst = inst;
3283 	gclass->context.method_inst = NULL;
3284 	gclass->owner = set;
3285 	if (inst == mono_class_get_generic_container (container_class)->context.class_inst && !is_tb_open)
3286 		gclass->cached_class = container_class;
3287 
3288 	mono_image_set_lock (set);
3289 
3290 	MonoGenericClass *gclass2 = mono_conc_hashtable_insert (set->gclass_cache, gclass, gclass);
3291 	if (!gclass2)
3292 		gclass2 = gclass;
3293 
3294 	// g_hash_table_insert (set->gclass_cache, gclass, gclass);
3295 
3296 	mono_image_set_unlock (set);
3297 
3298 	return gclass2;
3299 }
3300 
3301 /*
3302  * mono_metadata_inflate_generic_inst:
3303  *
3304  * Instantiate the generic instance @ginst with the context @context.
3305  * Check @error for success.
3306  *
3307  */
3308 MonoGenericInst *
mono_metadata_inflate_generic_inst(MonoGenericInst * ginst,MonoGenericContext * context,MonoError * error)3309 mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context, MonoError *error)
3310 {
3311 	MonoType **type_argv;
3312 	MonoGenericInst *nginst = NULL;
3313 	int i, count = 0;
3314 
3315 	error_init (error);
3316 
3317 	if (!ginst->is_open)
3318 		return ginst;
3319 
3320 	type_argv = g_new0 (MonoType*, ginst->type_argc);
3321 
3322 	for (i = 0; i < ginst->type_argc; i++) {
3323 		type_argv [i] = mono_class_inflate_generic_type_checked (ginst->type_argv [i], context, error);
3324 		if (!mono_error_ok (error))
3325 			goto cleanup;
3326 		++count;
3327 	}
3328 
3329 	nginst = mono_metadata_get_generic_inst (ginst->type_argc, type_argv);
3330 
3331 cleanup:
3332 	for (i = 0; i < count; i++)
3333 		mono_metadata_free_type (type_argv [i]);
3334 	g_free (type_argv);
3335 
3336 	return nginst;
3337 }
3338 
3339 MonoGenericInst *
mono_metadata_parse_generic_inst(MonoImage * m,MonoGenericContainer * container,int count,const char * ptr,const char ** rptr,MonoError * error)3340 mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container,
3341 				  int count, const char *ptr, const char **rptr, MonoError *error)
3342 {
3343 	MonoType **type_argv;
3344 	MonoGenericInst *ginst;
3345 	int i;
3346 
3347 	error_init (error);
3348 	type_argv = g_new0 (MonoType*, count);
3349 
3350 	for (i = 0; i < count; i++) {
3351 		MonoType *t = mono_metadata_parse_type_checked (m, container, 0, FALSE, ptr, &ptr, error);
3352 		if (!t) {
3353 			g_free (type_argv);
3354 			return NULL;
3355 		}
3356 		type_argv [i] = t;
3357 	}
3358 
3359 	if (rptr)
3360 		*rptr = ptr;
3361 
3362 	ginst = mono_metadata_get_generic_inst (count, type_argv);
3363 
3364 	g_free (type_argv);
3365 
3366 	return ginst;
3367 }
3368 
3369 static gboolean
do_mono_metadata_parse_generic_class(MonoType * type,MonoImage * m,MonoGenericContainer * container,const char * ptr,const char ** rptr,MonoError * error)3370 do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
3371 				      const char *ptr, const char **rptr, MonoError *error)
3372 {
3373 	MonoGenericInst *inst;
3374 	MonoClass *gklass;
3375 	MonoType *gtype;
3376 	int count;
3377 
3378 	error_init (error);
3379 
3380 	// XXX how about transient?
3381 	gtype = mono_metadata_parse_type_checked (m, NULL, 0, FALSE, ptr, &ptr, error);
3382 	if (gtype == NULL)
3383 		return FALSE;
3384 
3385 	gklass = mono_class_from_mono_type (gtype);
3386 	if (!mono_class_is_gtd (gklass)) {
3387 		mono_error_set_bad_image (error, m, "Generic instance with non-generic definition");
3388 		return FALSE;
3389 	}
3390 
3391 	count = mono_metadata_decode_value (ptr, &ptr);
3392 	inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr, error);
3393 	if (inst == NULL)
3394 		return FALSE;
3395 
3396 	if (rptr)
3397 		*rptr = ptr;
3398 
3399 	type->data.generic_class = mono_metadata_lookup_generic_class (gklass, inst, FALSE);
3400 	return TRUE;
3401 }
3402 
3403 /*
3404  * select_container:
3405  * @gc: The generic container to normalize
3406  * @type: The kind of generic parameters the resulting generic-container should contain
3407  */
3408 
3409 static MonoGenericContainer *
select_container(MonoGenericContainer * gc,MonoTypeEnum type)3410 select_container (MonoGenericContainer *gc, MonoTypeEnum type)
3411 {
3412 	gboolean is_var = (type == MONO_TYPE_VAR);
3413 	if (!gc)
3414 		return NULL;
3415 
3416 	g_assert (is_var || type == MONO_TYPE_MVAR);
3417 
3418 	if (is_var) {
3419 		if (gc->is_method || gc->parent)
3420 			/*
3421 			 * The current MonoGenericContainer is a generic method -> its `parent'
3422 			 * points to the containing class'es container.
3423 			 */
3424 			return gc->parent;
3425 	}
3426 
3427 	return gc;
3428 }
3429 
3430 MonoGenericContainer *
get_anonymous_container_for_image(MonoImage * image,gboolean is_mvar)3431 get_anonymous_container_for_image (MonoImage *image, gboolean is_mvar)
3432 {
3433 	MonoGenericContainer **container_pointer;
3434 	if (is_mvar)
3435 		container_pointer = &image->anonymous_generic_method_container;
3436 	else
3437 		container_pointer = &image->anonymous_generic_class_container;
3438 	MonoGenericContainer *result = *container_pointer;
3439 
3440 	// This container has never been created; make it now.
3441 	if (!result)
3442 	{
3443 		// Note this is never deallocated anywhere-- it exists for the lifetime of the image it's allocated from
3444 		result = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
3445 		result->owner.image = image;
3446 		result->is_anonymous = TRUE;
3447 		result->is_small_param = TRUE;
3448 		result->is_method = is_mvar;
3449 
3450 		// If another thread already made a container, use that and leak this new one.
3451 		// (Technically it would currently be safe to just assign instead of CASing.)
3452 		MonoGenericContainer *exchange = (MonoGenericContainer *)mono_atomic_cas_ptr ((volatile gpointer *)container_pointer, result, NULL);
3453 		if (exchange)
3454 			result = exchange;
3455 	}
3456 	return result;
3457 }
3458 
3459 /*
3460  * mono_metadata_parse_generic_param:
3461  * @generic_container: Our MonoClass's or MonoMethod's MonoGenericContainer;
3462  *                     see mono_metadata_parse_type_checked() for details.
3463  * Internal routine to parse a generic type parameter.
3464  * LOCKING: Acquires the loader lock
3465  */
3466 static MonoGenericParam *
mono_metadata_parse_generic_param(MonoImage * m,MonoGenericContainer * generic_container,MonoTypeEnum type,const char * ptr,const char ** rptr,MonoError * error)3467 mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
3468 				   MonoTypeEnum type, const char *ptr, const char **rptr, MonoError *error)
3469 {
3470 	int index = mono_metadata_decode_value (ptr, &ptr);
3471 	if (rptr)
3472 		*rptr = ptr;
3473 
3474 	error_init (error);
3475 
3476 	generic_container = select_container (generic_container, type);
3477 	if (!generic_container) {
3478 		gboolean is_mvar = FALSE;
3479 		switch (type)
3480 		{
3481 			case MONO_TYPE_VAR:
3482 				break;
3483 			case MONO_TYPE_MVAR:
3484 				is_mvar = TRUE;
3485 				break;
3486 			default:
3487 				g_error ("Cerating generic param object with invalid MonoType"); // This is not a generic param
3488 		}
3489 
3490 		/* Create dummy MonoGenericParam */
3491 		MonoGenericParam *param;
3492 
3493 		param = (MonoGenericParam *)mono_image_alloc0 (m, sizeof (MonoGenericParam));
3494 		param->num = index;
3495 		param->owner = get_anonymous_container_for_image (m, is_mvar);
3496 
3497 		return param;
3498 	}
3499 
3500 	if (index >= generic_container->type_argc) {
3501 		mono_error_set_bad_image (error, m, "Invalid generic %s parameter index %d, max index is %d",
3502 			generic_container->is_method ? "method" : "type",
3503 			index, generic_container->type_argc);
3504 		return NULL;
3505 	}
3506 
3507 	//This can't return NULL
3508 	return mono_generic_container_get_param (generic_container, index);
3509 }
3510 
3511 /*
3512  * mono_metadata_get_shared_type:
3513  *
3514  *   Return a shared instance of TYPE, if available, NULL otherwise.
3515  * Shared MonoType instances help save memory. Their contents should not be modified
3516  * by the caller. They do not need to be freed as their lifetime is bound by either
3517  * the lifetime of the runtime (builtin types), or the lifetime of the MonoClass
3518  * instance they are embedded in. If they are freed, they should be freed using
3519  * mono_metadata_free_type () instead of g_free ().
3520  */
3521 MonoType*
mono_metadata_get_shared_type(MonoType * type)3522 mono_metadata_get_shared_type (MonoType *type)
3523 {
3524 	MonoType *cached;
3525 
3526 	/* No need to use locking since nobody is modifying the hash table */
3527 	if ((cached = (MonoType *)g_hash_table_lookup (type_cache, type)))
3528 		return cached;
3529 
3530 	switch (type->type){
3531 	case MONO_TYPE_CLASS:
3532 	case MONO_TYPE_VALUETYPE:
3533 		if (type == &type->data.klass->byval_arg)
3534 			return type;
3535 		if (type == &type->data.klass->this_arg)
3536 			return type;
3537 		break;
3538 	default:
3539 		break;
3540 	}
3541 
3542 	return NULL;
3543 }
3544 
3545 static gboolean
compare_type_literals(MonoImage * image,int class_type,int type_type,MonoError * error)3546 compare_type_literals (MonoImage *image, int class_type, int type_type, MonoError *error)
3547 {
3548 	error_init (error);
3549 
3550 	/* byval_arg.type can be zero if we're decoding a type that references a class been loading.
3551 	 * See mcs/test/gtest-440. and #650936.
3552 	 * FIXME This better be moved to the metadata verifier as it can catch more cases.
3553 	 */
3554 	if (!class_type)
3555 		return TRUE;
3556 	/* NET 1.1 assemblies might encode string and object in a denormalized way.
3557 	 * See #675464.
3558 	 */
3559 	if (class_type == type_type)
3560 		return TRUE;
3561 
3562 	if (type_type == MONO_TYPE_CLASS) {
3563 		if (class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT)
3564 			return TRUE;
3565 		//XXX stringify this argument
3566 		mono_error_set_bad_image (error, image, "Expected reference type but got type kind %d", class_type);
3567 		return FALSE;
3568 	}
3569 
3570 	g_assert (type_type == MONO_TYPE_VALUETYPE);
3571 	switch (class_type) {
3572 	case MONO_TYPE_BOOLEAN:
3573 	case MONO_TYPE_CHAR:
3574 	case MONO_TYPE_I1:
3575 	case MONO_TYPE_U1:
3576 	case MONO_TYPE_I2:
3577 	case MONO_TYPE_U2:
3578 	case MONO_TYPE_I4:
3579 	case MONO_TYPE_U4:
3580 	case MONO_TYPE_I8:
3581 	case MONO_TYPE_U8:
3582 	case MONO_TYPE_R4:
3583 	case MONO_TYPE_R8:
3584 	case MONO_TYPE_I:
3585 	case MONO_TYPE_U:
3586 	case MONO_TYPE_CLASS:
3587 		return TRUE;
3588 	default:
3589 		//XXX stringify this argument
3590 		mono_error_set_bad_image (error, image, "Expected value type but got type kind %d", class_type);
3591 		return FALSE;
3592 	}
3593 }
3594 
3595 static gboolean
verify_var_type_and_container(MonoImage * image,int var_type,MonoGenericContainer * container,MonoError * error)3596 verify_var_type_and_container (MonoImage *image, int var_type, MonoGenericContainer *container, MonoError *error)
3597 {
3598 	error_init (error);
3599 	if (var_type == MONO_TYPE_MVAR) {
3600 		if (!container->is_method) { //MVAR and a method container
3601 			mono_error_set_bad_image (error, image, "MVAR parsed in a context without a method container");
3602 			return FALSE;
3603 		}
3604 	} else {
3605 		if (!(!container->is_method || //VAR and class container
3606 			(container->is_method && container->parent))) { //VAR and method container with parent
3607 			mono_error_set_bad_image (error, image, "VAR parsed in a context without a class container");
3608 			return FALSE;
3609 		}
3610 	}
3611 	return TRUE;
3612 }
3613 
3614 /*
3615  * do_mono_metadata_parse_type:
3616  * @type: MonoType to be filled in with the return value
3617  * @m: image context
3618  * @generic_context: generics_context
3619  * @transient: whenever to allocate data from the heap
3620  * @ptr: pointer to the encoded type
3621  * @rptr: pointer where the end of the encoded type is saved
3622  *
3623  * Internal routine used to "fill" the contents of @type from an
3624  * allocated pointer.  This is done this way to avoid doing too
3625  * many mini-allocations (particularly for the MonoFieldType which
3626  * most of the time is just a MonoType, but sometimes might be augmented).
3627  *
3628  * This routine is used by mono_metadata_parse_type and
3629  * mono_metadata_parse_field_type
3630  *
3631  * This extracts a Type as specified in Partition II (22.2.12)
3632  *
3633  * Returns: FALSE if the type could not be loaded
3634  */
3635 static gboolean
do_mono_metadata_parse_type(MonoType * type,MonoImage * m,MonoGenericContainer * container,gboolean transient,const char * ptr,const char ** rptr,MonoError * error)3636 do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
3637 							 gboolean transient, const char *ptr, const char **rptr, MonoError *error)
3638 {
3639 	error_init (error);
3640 
3641 	type->type = (MonoTypeEnum)mono_metadata_decode_value (ptr, &ptr);
3642 
3643 	switch (type->type){
3644 	case MONO_TYPE_VOID:
3645 	case MONO_TYPE_BOOLEAN:
3646 	case MONO_TYPE_CHAR:
3647 	case MONO_TYPE_I1:
3648 	case MONO_TYPE_U1:
3649 	case MONO_TYPE_I2:
3650 	case MONO_TYPE_U2:
3651 	case MONO_TYPE_I4:
3652 	case MONO_TYPE_U4:
3653 	case MONO_TYPE_I8:
3654 	case MONO_TYPE_U8:
3655 	case MONO_TYPE_R4:
3656 	case MONO_TYPE_R8:
3657 	case MONO_TYPE_I:
3658 	case MONO_TYPE_U:
3659 	case MONO_TYPE_STRING:
3660 	case MONO_TYPE_OBJECT:
3661 	case MONO_TYPE_TYPEDBYREF:
3662 		break;
3663 	case MONO_TYPE_VALUETYPE:
3664 	case MONO_TYPE_CLASS: {
3665 		guint32 token;
3666 		MonoClass *klass;
3667 		token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
3668 		klass = mono_class_get_checked (m, token, error);
3669 		type->data.klass = klass;
3670 		if (!klass)
3671 			return FALSE;
3672 
3673 		if (!compare_type_literals (m, klass->byval_arg.type, type->type, error))
3674 			return FALSE;
3675 
3676 		break;
3677 	}
3678 	case MONO_TYPE_SZARRAY: {
3679 		MonoType *etype = mono_metadata_parse_type_checked (m, container, 0, transient, ptr, &ptr, error);
3680 		if (!etype)
3681 			return FALSE;
3682 
3683 		type->data.klass = mono_class_from_mono_type (etype);
3684 
3685 		if (transient)
3686 			mono_metadata_free_type (etype);
3687 
3688 		g_assert (type->data.klass); //This was previously a check for NULL, but mcfmt should never fail. It can return a borken MonoClass, but should return at least something.
3689 		break;
3690 	}
3691 	case MONO_TYPE_PTR: {
3692 		type->data.type = mono_metadata_parse_type_checked (m, container, 0, transient, ptr, &ptr, error);
3693 		if (!type->data.type)
3694 			return FALSE;
3695 		break;
3696 	}
3697 	case MONO_TYPE_FNPTR: {
3698 		type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr, error);
3699 		if (!type->data.method)
3700 			return FALSE;
3701 		break;
3702 	}
3703 	case MONO_TYPE_ARRAY: {
3704 		type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr, error);
3705 		if (!type->data.array)
3706 			return FALSE;
3707 		break;
3708 	}
3709 	case MONO_TYPE_MVAR:
3710 	case MONO_TYPE_VAR: {
3711 		if (container && !verify_var_type_and_container (m, type->type, container, error))
3712 			return FALSE;
3713 
3714 		type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr, error);
3715 		if (!type->data.generic_param)
3716 			return FALSE;
3717 
3718 		break;
3719 	}
3720 	case MONO_TYPE_GENERICINST: {
3721 		if (!do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr, error))
3722 			return FALSE;
3723 		break;
3724 	}
3725 	default:
3726 		mono_error_set_bad_image (error, m, "type 0x%02x not handled in do_mono_metadata_parse_type on image %s", type->type, m->name);
3727 		return FALSE;
3728 	}
3729 
3730 	if (rptr)
3731 		*rptr = ptr;
3732 	return TRUE;
3733 }
3734 
3735 /**
3736  * mono_metadata_free_type:
3737  * \param type type to free
3738  *
3739  * Free the memory allocated for type \p type which is allocated on the heap.
3740  */
3741 void
mono_metadata_free_type(MonoType * type)3742 mono_metadata_free_type (MonoType *type)
3743 {
3744 	if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
3745 		return;
3746 
3747 	switch (type->type){
3748 	case MONO_TYPE_OBJECT:
3749 	case MONO_TYPE_STRING:
3750 		if (!type->data.klass)
3751 			break;
3752 		/* fall through */
3753 	case MONO_TYPE_CLASS:
3754 	case MONO_TYPE_VALUETYPE:
3755 		if (type == &type->data.klass->byval_arg || type == &type->data.klass->this_arg)
3756 			return;
3757 		break;
3758 	case MONO_TYPE_PTR:
3759 		mono_metadata_free_type (type->data.type);
3760 		break;
3761 	case MONO_TYPE_FNPTR:
3762 		mono_metadata_free_method_signature (type->data.method);
3763 		break;
3764 	case MONO_TYPE_ARRAY:
3765 		mono_metadata_free_array (type->data.array);
3766 		break;
3767 	default:
3768 		break;
3769 	}
3770 
3771 	g_free (type);
3772 }
3773 
3774 #if 0
3775 static void
3776 hex_dump (const char *buffer, int base, int count)
3777 {
3778 	int show_header = 1;
3779 	int i;
3780 
3781 	if (count < 0){
3782 		count = -count;
3783 		show_header = 0;
3784 	}
3785 
3786 	for (i = 0; i < count; i++){
3787 		if (show_header)
3788 			if ((i % 16) == 0)
3789 				printf ("\n0x%08x: ", (unsigned char) base + i);
3790 
3791 		printf ("%02x ", (unsigned char) (buffer [i]));
3792 	}
3793 	fflush (stdout);
3794 }
3795 #endif
3796 
3797 /**
3798  * @ptr: Points to the beginning of the Section Data (25.3)
3799  */
3800 static MonoExceptionClause*
parse_section_data(MonoImage * m,int * num_clauses,const unsigned char * ptr,MonoError * error)3801 parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr, MonoError *error)
3802 {
3803 	unsigned char sect_data_flags;
3804 	int is_fat;
3805 	guint32 sect_data_len;
3806 	MonoExceptionClause* clauses = NULL;
3807 
3808 	error_init (error);
3809 
3810 	while (1) {
3811 		/* align on 32-bit boundary */
3812 		ptr = dword_align (ptr);
3813 		sect_data_flags = *ptr;
3814 		ptr++;
3815 
3816 		is_fat = sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT;
3817 		if (is_fat) {
3818 			sect_data_len = (ptr [2] << 16) | (ptr [1] << 8) | ptr [0];
3819 			ptr += 3;
3820 		} else {
3821 			sect_data_len = ptr [0];
3822 			++ptr;
3823 		}
3824 
3825 		if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
3826 			const unsigned char *p = dword_align (ptr);
3827 			int i;
3828 			*num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
3829 			/* we could just store a pointer if we don't need to byteswap */
3830 			clauses = (MonoExceptionClause *)g_malloc0 (sizeof (MonoExceptionClause) * (*num_clauses));
3831 			for (i = 0; i < *num_clauses; ++i) {
3832 				MonoExceptionClause *ec = &clauses [i];
3833 				guint32 tof_value;
3834 				if (is_fat) {
3835 					ec->flags = read32 (p);
3836 					ec->try_offset = read32 (p + 4);
3837 					ec->try_len = read32 (p + 8);
3838 					ec->handler_offset = read32 (p + 12);
3839 					ec->handler_len = read32 (p + 16);
3840 					tof_value = read32 (p + 20);
3841 					p += 24;
3842 				} else {
3843 					ec->flags = read16 (p);
3844 					ec->try_offset = read16 (p + 2);
3845 					ec->try_len = *(p + 4);
3846 					ec->handler_offset = read16 (p + 5);
3847 					ec->handler_len = *(p + 7);
3848 					tof_value = read32 (p + 8);
3849 					p += 12;
3850 				}
3851 				if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
3852 					ec->data.filter_offset = tof_value;
3853 				} else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) {
3854 					ec->data.catch_class = NULL;
3855 					if (tof_value) {
3856 						ec->data.catch_class = mono_class_get_checked (m, tof_value, error);
3857 						if (!is_ok (error)) {
3858 							g_free (clauses);
3859 							return NULL;
3860 						}
3861 					}
3862 				} else {
3863 					ec->data.catch_class = NULL;
3864 				}
3865 				/* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
3866 			}
3867 
3868 		}
3869 		if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS)
3870 			ptr += sect_data_len - 4; /* LAMESPEC: it seems the size includes the header */
3871 		else
3872 			return clauses;
3873 	}
3874 }
3875 
3876 /*
3877  * mono_method_get_header_summary:
3878  * @method: The method to get the header.
3879  * @summary: Where to store the header
3880  *
3881  *
3882  * Returns: TRUE if the header was properly decoded.
3883  */
3884 gboolean
mono_method_get_header_summary(MonoMethod * method,MonoMethodHeaderSummary * summary)3885 mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *summary)
3886 {
3887 	int idx;
3888 	guint32 rva;
3889 	MonoImage* img;
3890 	const char *ptr;
3891 	unsigned char flags, format;
3892 	guint16 fat_flags;
3893 
3894 	/*Only the GMD has a pointer to the metadata.*/
3895 	while (method->is_inflated)
3896 		method = ((MonoMethodInflated*)method)->declaring;
3897 
3898 	summary->code_size = 0;
3899 	summary->has_clauses = FALSE;
3900 
3901 	/*FIXME extract this into a MACRO and share it with mono_method_get_header*/
3902 	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))
3903 		return FALSE;
3904 
3905 	if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) {
3906 		MonoMethodHeader *header =  ((MonoMethodWrapper *)method)->header;
3907 		if (!header)
3908 			return FALSE;
3909 		summary->code_size = header->code_size;
3910 		summary->has_clauses = header->num_clauses > 0;
3911 		return TRUE;
3912 	}
3913 
3914 
3915 	idx = mono_metadata_token_index (method->token);
3916 	img = method->klass->image;
3917 	rva = mono_metadata_decode_row_col (&img->tables [MONO_TABLE_METHOD], idx - 1, MONO_METHOD_RVA);
3918 
3919 	/*We must run the verifier since we'll be decoding it.*/
3920 	if (!mono_verifier_verify_method_header (img, rva, NULL))
3921 		return FALSE;
3922 
3923 	ptr = mono_image_rva_map (img, rva);
3924 	if (!ptr)
3925 		return FALSE;
3926 
3927 	flags = *(const unsigned char *)ptr;
3928 	format = flags & METHOD_HEADER_FORMAT_MASK;
3929 
3930 	switch (format) {
3931 	case METHOD_HEADER_TINY_FORMAT:
3932 		ptr++;
3933 		summary->code_size = flags >> 2;
3934 		break;
3935 	case METHOD_HEADER_FAT_FORMAT:
3936 		fat_flags = read16 (ptr);
3937 		ptr += 4;
3938 		summary->code_size = read32 (ptr);
3939 		if (fat_flags & METHOD_HEADER_MORE_SECTS)
3940 			summary->has_clauses = TRUE;
3941 		break;
3942 	default:
3943 		return FALSE;
3944 	}
3945 	return TRUE;
3946 }
3947 
3948 /*
3949  * mono_metadata_parse_mh_full:
3950  * @m: metadata context
3951  * @generic_context: generics context
3952  * @ptr: pointer to the method header.
3953  *
3954  * Decode the method header at @ptr, including pointer to the IL code,
3955  * info about local variables and optional exception tables.
3956  * This is a Mono runtime internal function.
3957  *
3958  * LOCKING: Acquires the loader lock.
3959  *
3960  * Returns: a transient MonoMethodHeader allocated from the heap.
3961  */
3962 MonoMethodHeader *
mono_metadata_parse_mh_full(MonoImage * m,MonoGenericContainer * container,const char * ptr,MonoError * error)3963 mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr, MonoError *error)
3964 {
3965 	MonoMethodHeader *mh = NULL;
3966 	unsigned char flags = *(const unsigned char *) ptr;
3967 	unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
3968 	guint16 fat_flags;
3969 	guint32 local_var_sig_tok, max_stack, code_size, init_locals;
3970 	const unsigned char *code;
3971 	MonoExceptionClause* clauses = NULL;
3972 	int num_clauses = 0;
3973 	MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
3974 	guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
3975 
3976 	error_init (error);
3977 
3978 	if (!ptr) {
3979 		mono_error_set_bad_image (error, m, "Method header with null pointer");
3980 		return NULL;
3981 	}
3982 
3983 	switch (format) {
3984 	case METHOD_HEADER_TINY_FORMAT:
3985 		mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER);
3986 		ptr++;
3987 		mh->max_stack = 8;
3988 		mh->is_transient = TRUE;
3989 		local_var_sig_tok = 0;
3990 		mh->code_size = flags >> 2;
3991 		mh->code = (unsigned char*)ptr;
3992 		return mh;
3993 	case METHOD_HEADER_FAT_FORMAT:
3994 		fat_flags = read16 (ptr);
3995 		ptr += 2;
3996 		max_stack = read16 (ptr);
3997 		ptr += 2;
3998 		code_size = read32 (ptr);
3999 		ptr += 4;
4000 		local_var_sig_tok = read32 (ptr);
4001 		ptr += 4;
4002 
4003 		if (fat_flags & METHOD_HEADER_INIT_LOCALS)
4004 			init_locals = 1;
4005 		else
4006 			init_locals = 0;
4007 
4008 		code = (unsigned char*)ptr;
4009 
4010 		if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
4011 			break;
4012 
4013 		/*
4014 		 * There are more sections
4015 		 */
4016 		ptr = (char*)code + code_size;
4017 		break;
4018 	default:
4019 		mono_error_set_bad_image (error, m, "Invalid method header format %d", format);
4020 		return NULL;
4021 	}
4022 
4023 	if (local_var_sig_tok) {
4024 		int idx = (local_var_sig_tok & 0xffffff)-1;
4025 		if (idx >= t->rows || idx < 0) {
4026 			mono_error_set_bad_image (error, m, "Invalid method header local vars signature token 0x%8x", idx);
4027 			goto fail;
4028 		}
4029 		mono_metadata_decode_row (t, idx, cols, 1);
4030 
4031 		if (!mono_verifier_verify_standalone_signature (m, cols [MONO_STAND_ALONE_SIGNATURE], NULL)) {
4032 			mono_error_set_bad_image (error, m, "Method header locals signature 0x%8x verification failed", idx);
4033 			goto fail;
4034 		}
4035 	}
4036 	if (fat_flags & METHOD_HEADER_MORE_SECTS) {
4037 		clauses = parse_section_data (m, &num_clauses, (const unsigned char*)ptr, error);
4038 		goto_if_nok (error, fail);
4039 	}
4040 	if (local_var_sig_tok) {
4041 		const char *locals_ptr;
4042 		int len=0, i;
4043 
4044 		locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
4045 		mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
4046 		if (*locals_ptr != 0x07)
4047 			g_warning ("wrong signature for locals blob");
4048 		locals_ptr++;
4049 		len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
4050 		mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + len * sizeof (MonoType*) + num_clauses * sizeof (MonoExceptionClause));
4051 		mh->num_locals = len;
4052 		for (i = 0; i < len; ++i) {
4053 			mh->locals [i] = mono_metadata_parse_type_internal (m, container, 0, TRUE, locals_ptr, &locals_ptr, error);
4054 			goto_if_nok (error, fail);
4055 		}
4056 	} else {
4057 		mh = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause));
4058 	}
4059 	mh->code = code;
4060 	mh->code_size = code_size;
4061 	mh->max_stack = max_stack;
4062 	mh->is_transient = TRUE;
4063 	mh->init_locals = init_locals;
4064 	if (clauses) {
4065 		MonoExceptionClause* clausesp = (MonoExceptionClause*)&mh->locals [mh->num_locals];
4066 		memcpy (clausesp, clauses, num_clauses * sizeof (MonoExceptionClause));
4067 		g_free (clauses);
4068 		mh->clauses = clausesp;
4069 		mh->num_clauses = num_clauses;
4070 	}
4071 	return mh;
4072 fail:
4073 	g_free (clauses);
4074 	g_free (mh);
4075 	return NULL;
4076 
4077 }
4078 
4079 /**
4080  * mono_metadata_parse_mh:
4081  * \param generic_context generics context
4082  * \param ptr pointer to the method header.
4083  *
4084  * Decode the method header at \p ptr, including pointer to the IL code,
4085  * info about local variables and optional exception tables.
4086  *
4087  * \returns a transient \c MonoMethodHeader allocated from the heap.
4088  */
4089 MonoMethodHeader *
mono_metadata_parse_mh(MonoImage * m,const char * ptr)4090 mono_metadata_parse_mh (MonoImage *m, const char *ptr)
4091 {
4092 	MonoError error;
4093 	MonoMethodHeader *header = mono_metadata_parse_mh_full (m, NULL, ptr, &error);
4094 	mono_error_cleanup (&error);
4095 	return header;
4096 }
4097 
4098 /**
4099  * mono_metadata_free_mh:
4100  * \param mh a method header
4101  *
4102  * Free the memory allocated for the method header.
4103  */
4104 void
mono_metadata_free_mh(MonoMethodHeader * mh)4105 mono_metadata_free_mh (MonoMethodHeader *mh)
4106 {
4107 	int i;
4108 
4109 	/* If it is not transient it means it's part of a wrapper method,
4110 	 * or a SRE-generated method, so the lifetime in that case is
4111 	 * dictated by the method's own lifetime
4112 	 */
4113 	if (mh->is_transient) {
4114 		for (i = 0; i < mh->num_locals; ++i)
4115 			mono_metadata_free_type (mh->locals [i]);
4116 		g_free (mh);
4117 	}
4118 }
4119 
4120 /**
4121  * mono_method_header_get_code:
4122  * \param header a \c MonoMethodHeader pointer
4123  * \param code_size memory location for returning the code size
4124  * \param max_stack memory location for returning the max stack
4125  *
4126  * Method header accessor to retreive info about the IL code properties:
4127  * a pointer to the IL code itself, the size of the code and the max number
4128  * of stack slots used by the code.
4129  *
4130  * \returns pointer to the IL code represented by the method header.
4131  */
4132 const unsigned char*
mono_method_header_get_code(MonoMethodHeader * header,guint32 * code_size,guint32 * max_stack)4133 mono_method_header_get_code (MonoMethodHeader *header, guint32* code_size, guint32* max_stack)
4134 {
4135 	if (code_size)
4136 		*code_size = header->code_size;
4137 	if (max_stack)
4138 		*max_stack = header->max_stack;
4139 	return header->code;
4140 }
4141 
4142 /**
4143  * mono_method_header_get_locals:
4144  * \param header a \c MonoMethodHeader pointer
4145  * \param num_locals memory location for returning the number of local variables
4146  * \param init_locals memory location for returning the init_locals flag
4147  *
4148  * Method header accessor to retreive info about the local variables:
4149  * an array of local types, the number of locals and whether the locals
4150  * are supposed to be initialized to 0 on method entry
4151  *
4152  * \returns pointer to an array of types of the local variables
4153  */
4154 MonoType**
mono_method_header_get_locals(MonoMethodHeader * header,guint32 * num_locals,gboolean * init_locals)4155 mono_method_header_get_locals (MonoMethodHeader *header, guint32* num_locals, gboolean *init_locals)
4156 {
4157 	if (num_locals)
4158 		*num_locals = header->num_locals;
4159 	if (init_locals)
4160 		*init_locals = header->init_locals;
4161 	return header->locals;
4162 }
4163 
4164 /*
4165  * mono_method_header_get_num_clauses:
4166  * @header: a MonoMethodHeader pointer
4167  *
4168  * Method header accessor to retreive the number of exception clauses.
4169  *
4170  * Returns: the number of exception clauses present
4171  */
4172 int
mono_method_header_get_num_clauses(MonoMethodHeader * header)4173 mono_method_header_get_num_clauses (MonoMethodHeader *header)
4174 {
4175 	return header->num_clauses;
4176 }
4177 
4178 /**
4179  * mono_method_header_get_clauses:
4180  * \param header a \c MonoMethodHeader pointer
4181  * \param method \c MonoMethod the header belongs to
4182  * \param iter pointer to a iterator
4183  * \param clause pointer to a \c MonoExceptionClause structure which will be filled with the info
4184  *
4185  * Get the info about the exception clauses in the method. Set \c *iter to NULL to
4186  * initiate the iteration, then call the method repeatedly until it returns FALSE.
4187  * At each iteration, the structure pointed to by clause if filled with the
4188  * exception clause information.
4189  *
4190  * \returns TRUE if clause was filled with info, FALSE if there are no more exception
4191  * clauses.
4192  */
4193 int
mono_method_header_get_clauses(MonoMethodHeader * header,MonoMethod * method,gpointer * iter,MonoExceptionClause * clause)4194 mono_method_header_get_clauses (MonoMethodHeader *header, MonoMethod *method, gpointer *iter, MonoExceptionClause *clause)
4195 {
4196 	MonoExceptionClause *sc;
4197 	/* later we'll be able to use this interface to parse the clause info on demand,
4198 	 * without allocating anything.
4199 	 */
4200 	if (!iter || !header->num_clauses)
4201 		return FALSE;
4202 	if (!*iter) {
4203 		*iter = sc = header->clauses;
4204 		*clause = *sc;
4205 		return TRUE;
4206 	}
4207 	sc = (MonoExceptionClause *)*iter;
4208 	sc++;
4209 	if (sc < header->clauses + header->num_clauses) {
4210 		*iter = sc;
4211 		*clause = *sc;
4212 		return TRUE;
4213 	}
4214 	return FALSE;
4215 }
4216 
4217 /**
4218  * mono_metadata_parse_field_type:
4219  * \param m metadata context to extract information from
4220  * \param ptr pointer to the field signature
4221  * \param rptr pointer updated to match the end of the decoded stream
4222  *
4223  * Parses the field signature, and returns the type information for it.
4224  *
4225  * \returns The \c MonoType that was extracted from \p ptr .
4226  */
4227 MonoType *
mono_metadata_parse_field_type(MonoImage * m,short field_flags,const char * ptr,const char ** rptr)4228 mono_metadata_parse_field_type (MonoImage *m, short field_flags, const char *ptr, const char **rptr)
4229 {
4230 	MonoError error;
4231 	MonoType * type = mono_metadata_parse_type_internal (m, NULL, field_flags, FALSE, ptr, rptr, &error);
4232 	mono_error_cleanup (&error);
4233 	return type;
4234 }
4235 
4236 /**
4237  * mono_metadata_parse_param:
4238  * \param m metadata context to extract information from
4239  * \param ptr pointer to the param signature
4240  * \param rptr pointer updated to match the end of the decoded stream
4241  *
4242  * Parses the param signature, and returns the type information for it.
4243  *
4244  * \returns The \c MonoType that was extracted from \p ptr .
4245  */
4246 MonoType *
mono_metadata_parse_param(MonoImage * m,const char * ptr,const char ** rptr)4247 mono_metadata_parse_param (MonoImage *m, const char *ptr, const char **rptr)
4248 {
4249 	MonoError error;
4250 	MonoType * type = mono_metadata_parse_type_internal (m, NULL, 0, FALSE, ptr, rptr, &error);
4251 	mono_error_cleanup (&error);
4252 	return type;
4253 }
4254 
4255 /**
4256  * mono_metadata_token_from_dor:
4257  * \param dor_token A \c TypeDefOrRef coded index
4258  *
4259  * \p dor_token is a \c TypeDefOrRef coded index: it contains either
4260  * a \c TypeDef, \c TypeRef or \c TypeSpec in the lower bits, and the upper
4261  * bits contain an index into the table.
4262  *
4263  * \returns an expanded token
4264  */
4265 guint32
mono_metadata_token_from_dor(guint32 dor_index)4266 mono_metadata_token_from_dor (guint32 dor_index)
4267 {
4268 	guint32 table, idx;
4269 
4270 	table = dor_index & 0x03;
4271 	idx = dor_index >> 2;
4272 
4273 	switch (table){
4274 	case 0: /* TypeDef */
4275 		return MONO_TOKEN_TYPE_DEF | idx;
4276 	case 1: /* TypeRef */
4277 		return MONO_TOKEN_TYPE_REF | idx;
4278 	case 2: /* TypeSpec */
4279 		return MONO_TOKEN_TYPE_SPEC | idx;
4280 	default:
4281 		g_assert_not_reached ();
4282 	}
4283 
4284 	return 0;
4285 }
4286 
4287 /*
4288  * We use this to pass context information to the row locator
4289  */
4290 typedef struct {
4291 	int idx;			/* The index that we are trying to locate */
4292 	int col_idx;		/* The index in the row where idx may be stored */
4293 	MonoTableInfo *t;	/* pointer to the table */
4294 	guint32 result;
4295 } locator_t;
4296 
4297 /*
4298  * How the row locator works.
4299  *
4300  *   Table A
4301  *   ___|___
4302  *   ___|___         Table B
4303  *   ___|___------>  _______
4304  *   ___|___         _______
4305  *
4306  * A column in the rows of table A references an index in table B.
4307  * For example A may be the TYPEDEF table and B the METHODDEF table.
4308  *
4309  * Given an index in table B we want to get the row in table A
4310  * where the column n references our index in B.
4311  *
4312  * In the locator_t structure:
4313  * 	t is table A
4314  * 	col_idx is the column number
4315  * 	index is the index in table B
4316  * 	result will be the index in table A
4317  *
4318  * Examples:
4319  * Table A		Table B		column (in table A)
4320  * TYPEDEF		METHODDEF   MONO_TYPEDEF_METHOD_LIST
4321  * TYPEDEF		FIELD		MONO_TYPEDEF_FIELD_LIST
4322  * PROPERTYMAP	PROPERTY	MONO_PROPERTY_MAP_PROPERTY_LIST
4323  * INTERFIMPL	TYPEDEF   	MONO_INTERFACEIMPL_CLASS
4324  * METHODSEM	PROPERTY	ASSOCIATION (encoded index)
4325  *
4326  * Note that we still don't support encoded indexes.
4327  *
4328  */
4329 static int
typedef_locator(const void * a,const void * b)4330 typedef_locator (const void *a, const void *b)
4331 {
4332 	locator_t *loc = (locator_t *) a;
4333 	const char *bb = (const char *) b;
4334 	int typedef_index = (bb - loc->t->base) / loc->t->row_size;
4335 	guint32 col, col_next;
4336 
4337 	col = mono_metadata_decode_row_col (loc->t, typedef_index, loc->col_idx);
4338 
4339 	if (loc->idx < col)
4340 		return -1;
4341 
4342 	/*
4343 	 * Need to check that the next row is valid.
4344 	 */
4345 	if (typedef_index + 1 < loc->t->rows) {
4346 		col_next = mono_metadata_decode_row_col (loc->t, typedef_index + 1, loc->col_idx);
4347 		if (loc->idx >= col_next)
4348 			return 1;
4349 
4350 		if (col == col_next)
4351 			return 1;
4352 	}
4353 
4354 	loc->result = typedef_index;
4355 
4356 	return 0;
4357 }
4358 
4359 static int
table_locator(const void * a,const void * b)4360 table_locator (const void *a, const void *b)
4361 {
4362 	locator_t *loc = (locator_t *) a;
4363 	const char *bb = (const char *) b;
4364 	guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
4365 	guint32 col;
4366 
4367 	col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
4368 
4369 	if (loc->idx == col) {
4370 		loc->result = table_index;
4371 		return 0;
4372 	}
4373 	if (loc->idx < col)
4374 		return -1;
4375 	else
4376 		return 1;
4377 }
4378 
4379 static int
declsec_locator(const void * a,const void * b)4380 declsec_locator (const void *a, const void *b)
4381 {
4382 	locator_t *loc = (locator_t *) a;
4383 	const char *bb = (const char *) b;
4384 	guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
4385 	guint32 col;
4386 
4387 	col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
4388 
4389 	if (loc->idx == col) {
4390 		loc->result = table_index;
4391 		return 0;
4392 	}
4393 	if (loc->idx < col)
4394 		return -1;
4395 	else
4396 		return 1;
4397 }
4398 
4399 /**
4400  * search_ptr_table:
4401  *
4402  *  Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
4403  * which contains IDX.
4404  */
4405 static guint32
search_ptr_table(MonoImage * image,int table,int idx)4406 search_ptr_table (MonoImage *image, int table, int idx)
4407 {
4408 	MonoTableInfo *ptrdef = &image->tables [table];
4409 	int i;
4410 
4411 	/* Use a linear search to find our index in the table */
4412 	for (i = 0; i < ptrdef->rows; i ++)
4413 		/* All the Ptr tables have the same structure */
4414 		if (mono_metadata_decode_row_col (ptrdef, i, 0) == idx)
4415 			break;
4416 
4417 	if (i < ptrdef->rows)
4418 		return i + 1;
4419 	else
4420 		return idx;
4421 }
4422 
4423 /**
4424  * mono_metadata_typedef_from_field:
4425  * \param meta metadata context
4426  * \param index FieldDef token
4427  *
4428  * \returns the 1-based index into the \c TypeDef table of the type that
4429  * declared the field described by \p index, or 0 if not found.
4430  */
4431 guint32
mono_metadata_typedef_from_field(MonoImage * meta,guint32 index)4432 mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
4433 {
4434 	MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
4435 	locator_t loc;
4436 
4437 	if (!tdef->base)
4438 		return 0;
4439 
4440 	loc.idx = mono_metadata_token_index (index);
4441 	loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
4442 	loc.t = tdef;
4443 
4444 	if (meta->uncompressed_metadata)
4445 		loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
4446 
4447 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
4448 		return 0;
4449 
4450 	/* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4451 	return loc.result + 1;
4452 }
4453 
4454 /**
4455  * mono_metadata_typedef_from_method:
4456  * \param meta metadata context
4457  * \param index \c MethodDef token
4458  * \returns the 1-based index into the \c TypeDef table of the type that
4459  * declared the method described by \p index.  0 if not found.
4460  */
4461 guint32
mono_metadata_typedef_from_method(MonoImage * meta,guint32 index)4462 mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
4463 {
4464 	MonoTableInfo *tdef = &meta->tables [MONO_TABLE_TYPEDEF];
4465 	locator_t loc;
4466 
4467 	if (!tdef->base)
4468 		return 0;
4469 
4470 	loc.idx = mono_metadata_token_index (index);
4471 	loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
4472 	loc.t = tdef;
4473 
4474 	if (meta->uncompressed_metadata)
4475 		loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx);
4476 
4477 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
4478 		return 0;
4479 
4480 	/* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4481 	return loc.result + 1;
4482 }
4483 
4484 /*
4485  * mono_metadata_interfaces_from_typedef_full:
4486  * @meta: metadata context
4487  * @index: typedef token
4488  * @interfaces: Out parameter used to store the interface array
4489  * @count: Out parameter used to store the number of interfaces
4490  * @heap_alloc_result: if TRUE the result array will be g_malloc'd
4491  * @context: The generic context
4492  *
4493  * The array of interfaces that the @index typedef token implements is returned in
4494  * @interfaces. The number of elements in the array is returned in @count.
4495  *
4496 
4497  * Returns: TRUE on success, FALSE on failure.
4498  */
4499 gboolean
mono_metadata_interfaces_from_typedef_full(MonoImage * meta,guint32 index,MonoClass *** interfaces,guint * count,gboolean heap_alloc_result,MonoGenericContext * context,MonoError * error)4500 mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context, MonoError *error)
4501 {
4502 	MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
4503 	locator_t loc;
4504 	guint32 start, pos;
4505 	guint32 cols [MONO_INTERFACEIMPL_SIZE];
4506 	MonoClass **result;
4507 
4508 	*interfaces = NULL;
4509 	*count = 0;
4510 
4511 	error_init (error);
4512 
4513 	if (!tdef->base)
4514 		return TRUE;
4515 
4516 	loc.idx = mono_metadata_token_index (index);
4517 	loc.col_idx = MONO_INTERFACEIMPL_CLASS;
4518 	loc.t = tdef;
4519 
4520 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4521 		return TRUE;
4522 
4523 	start = loc.result;
4524 	/*
4525 	 * We may end up in the middle of the rows...
4526 	 */
4527 	while (start > 0) {
4528 		if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_INTERFACEIMPL_CLASS))
4529 			start--;
4530 		else
4531 			break;
4532 	}
4533 	pos = start;
4534 	while (pos < tdef->rows) {
4535 		mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
4536 		if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
4537 			break;
4538 		++pos;
4539 	}
4540 
4541 	if (heap_alloc_result)
4542 		result = g_new0 (MonoClass*, pos - start);
4543 	else
4544 		result = (MonoClass **)mono_image_alloc0 (meta, sizeof (MonoClass*) * (pos - start));
4545 
4546 	pos = start;
4547 	while (pos < tdef->rows) {
4548 		MonoClass *iface;
4549 
4550 		mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
4551 		if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
4552 			break;
4553 		iface = mono_class_get_and_inflate_typespec_checked (
4554 			meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context, error);
4555 		if (iface == NULL)
4556 			return FALSE;
4557 		result [pos - start] = iface;
4558 		++pos;
4559 	}
4560 	*count = pos - start;
4561 	*interfaces = result;
4562 	return TRUE;
4563 }
4564 
4565 /**
4566  * mono_metadata_interfaces_from_typedef:
4567  * \param meta metadata context
4568  * \param index typedef token
4569  * \param count Out parameter used to store the number of interfaces
4570  *
4571  * The array of interfaces that the \p index typedef token implements is returned in
4572  * \p interfaces. The number of elements in the array is returned in \p count. The returned
4573  * array is allocated with \c g_malloc and the caller must free it.
4574  *
4575  * LOCKING: Acquires the loader lock .
4576  *
4577  * \returns the interface array on success, NULL on failure.
4578  */
4579 MonoClass**
mono_metadata_interfaces_from_typedef(MonoImage * meta,guint32 index,guint * count)4580 mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
4581 {
4582 	MonoError error;
4583 	MonoClass **interfaces = NULL;
4584 	gboolean rv;
4585 
4586 	rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, TRUE, NULL, &error);
4587 	g_assert (mono_error_ok (&error)); /* FIXME dont swallow the error */
4588 	if (rv)
4589 		return interfaces;
4590 	else
4591 		return NULL;
4592 }
4593 
4594 /**
4595  * mono_metadata_nested_in_typedef:
4596  * \param meta metadata context
4597  * \param index typedef token
4598  * \returns the 1-based index into the TypeDef table of the type
4599  * where the type described by \p index is nested.
4600  * Returns 0 if \p index describes a non-nested type.
4601  */
4602 guint32
mono_metadata_nested_in_typedef(MonoImage * meta,guint32 index)4603 mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
4604 {
4605 	MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
4606 	locator_t loc;
4607 
4608 	if (!tdef->base)
4609 		return 0;
4610 
4611 	loc.idx = mono_metadata_token_index (index);
4612 	loc.col_idx = MONO_NESTED_CLASS_NESTED;
4613 	loc.t = tdef;
4614 
4615 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4616 		return 0;
4617 
4618 	/* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4619 	return mono_metadata_decode_row_col (tdef, loc.result, MONO_NESTED_CLASS_ENCLOSING) | MONO_TOKEN_TYPE_DEF;
4620 }
4621 
4622 /**
4623  * mono_metadata_nesting_typedef:
4624  * \param meta metadata context
4625  * \param index typedef token
4626  * \returns the 1-based index into the \c TypeDef table of the first type
4627  * that is nested inside the type described by \p index. The search starts at
4628  * \p start_index. Returns 0 if no such type is found.
4629  */
4630 guint32
mono_metadata_nesting_typedef(MonoImage * meta,guint32 index,guint32 start_index)4631 mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
4632 {
4633 	MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
4634 	guint32 start;
4635 	guint32 class_index = mono_metadata_token_index (index);
4636 
4637 	if (!tdef->base)
4638 		return 0;
4639 
4640 	start = start_index;
4641 
4642 	while (start <= tdef->rows) {
4643 		if (class_index == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
4644 			break;
4645 		else
4646 			start++;
4647 	}
4648 
4649 	if (start > tdef->rows)
4650 		return 0;
4651 	else
4652 		return start;
4653 }
4654 
4655 /**
4656  * mono_metadata_packing_from_typedef:
4657  * \param meta metadata context
4658  * \param index token representing a type
4659  * \returns the info stored in the \c ClassLayout table for the given typedef token
4660  * into the \p packing and \p size pointers.
4661  * Returns 0 if the info is not found.
4662  */
4663 guint32
mono_metadata_packing_from_typedef(MonoImage * meta,guint32 index,guint32 * packing,guint32 * size)4664 mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *packing, guint32 *size)
4665 {
4666 	MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CLASSLAYOUT];
4667 	locator_t loc;
4668 	guint32 cols [MONO_CLASS_LAYOUT_SIZE];
4669 
4670 	if (!tdef->base)
4671 		return 0;
4672 
4673 	loc.idx = mono_metadata_token_index (index);
4674 	loc.col_idx = MONO_CLASS_LAYOUT_PARENT;
4675 	loc.t = tdef;
4676 
4677 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4678 		return 0;
4679 
4680 	mono_metadata_decode_row (tdef, loc.result, cols, MONO_CLASS_LAYOUT_SIZE);
4681 	if (packing)
4682 		*packing = cols [MONO_CLASS_LAYOUT_PACKING_SIZE];
4683 	if (size)
4684 		*size = cols [MONO_CLASS_LAYOUT_CLASS_SIZE];
4685 
4686 	/* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4687 	return loc.result + 1;
4688 }
4689 
4690 /**
4691  * mono_metadata_custom_attrs_from_index:
4692  * \param meta metadata context
4693  * \param index token representing the parent
4694  * \returns: the 1-based index into the \c CustomAttribute table of the first
4695  * attribute which belongs to the metadata object described by \p index.
4696  * Returns 0 if no such attribute is found.
4697  */
4698 guint32
mono_metadata_custom_attrs_from_index(MonoImage * meta,guint32 index)4699 mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
4700 {
4701 	MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4702 	locator_t loc;
4703 
4704 	if (!tdef->base)
4705 		return 0;
4706 
4707 	loc.idx = index;
4708 	loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
4709 	loc.t = tdef;
4710 
4711 	/* FIXME: Index translation */
4712 
4713 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4714 		return 0;
4715 
4716 	/* Find the first entry by searching backwards */
4717 	while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_CUSTOM_ATTR_PARENT) == index))
4718 		loc.result --;
4719 
4720 	/* loc_result is 0..1, needs to be mapped to table index (that is +1) */
4721 	return loc.result + 1;
4722 }
4723 
4724 /**
4725  * mono_metadata_declsec_from_index:
4726  * \param meta metadata context
4727  * \param index token representing the parent
4728  * \returns the 0-based index into the \c DeclarativeSecurity table of the first
4729  * attribute which belongs to the metadata object described by \p index.
4730  * Returns \c -1 if no such attribute is found.
4731  */
4732 guint32
mono_metadata_declsec_from_index(MonoImage * meta,guint32 index)4733 mono_metadata_declsec_from_index (MonoImage *meta, guint32 index)
4734 {
4735 	MonoTableInfo *tdef = &meta->tables [MONO_TABLE_DECLSECURITY];
4736 	locator_t loc;
4737 
4738 	if (!tdef->base)
4739 		return -1;
4740 
4741 	loc.idx = index;
4742 	loc.col_idx = MONO_DECL_SECURITY_PARENT;
4743 	loc.t = tdef;
4744 
4745 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
4746 		return -1;
4747 
4748 	/* Find the first entry by searching backwards */
4749 	while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_DECL_SECURITY_PARENT) == index))
4750 		loc.result --;
4751 
4752 	return loc.result;
4753 }
4754 
4755 /*
4756  * mono_metadata_localscope_from_methoddef:
4757  * @meta: metadata context
4758  * @index: methoddef index
4759  *
4760  * Returns: the 1-based index into the LocalScope table of the first
4761  * scope which belongs to the method described by @index.
4762  * Returns 0 if no such row is found.
4763  */
4764 guint32
mono_metadata_localscope_from_methoddef(MonoImage * meta,guint32 index)4765 mono_metadata_localscope_from_methoddef (MonoImage *meta, guint32 index)
4766 {
4767 	MonoTableInfo *tdef = &meta->tables [MONO_TABLE_LOCALSCOPE];
4768 	locator_t loc;
4769 
4770 	if (!tdef->base)
4771 		return 0;
4772 
4773 	loc.idx = index;
4774 	loc.col_idx = MONO_LOCALSCOPE_METHOD;
4775 	loc.t = tdef;
4776 
4777 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
4778 		return 0;
4779 
4780 	/* Find the first entry by searching backwards */
4781 	while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_LOCALSCOPE_METHOD) == index))
4782 		loc.result --;
4783 
4784 	return loc.result + 1;
4785 }
4786 
4787 #ifdef DEBUG
4788 static void
mono_backtrace(int limit)4789 mono_backtrace (int limit)
4790 {
4791 	void *array[limit];
4792 	char **names;
4793 	int i;
4794 	backtrace (array, limit);
4795 	names = backtrace_symbols (array, limit);
4796 	for (i =0; i < limit; ++i) {
4797 		g_print ("\t%s\n", names [i]);
4798 	}
4799 	g_free (names);
4800 }
4801 #endif
4802 
4803 static int i8_align;
4804 
4805 /*
4806  * mono_type_set_alignment:
4807  *
4808  *   Set the alignment used by runtime to layout fields etc. of type TYPE to ALIGN.
4809  * This should only be used in AOT mode since the resulting layout will not match the
4810  * host abi layout.
4811  */
4812 void
mono_type_set_alignment(MonoTypeEnum type,int align)4813 mono_type_set_alignment (MonoTypeEnum type, int align)
4814 {
4815 	/* Support only a few types whose alignment is abi dependent */
4816 	switch (type) {
4817 	case MONO_TYPE_I8:
4818 		i8_align = align;
4819 		break;
4820 	default:
4821 		g_assert_not_reached ();
4822 		break;
4823 	}
4824 }
4825 
4826 /**
4827  * mono_type_size:
4828  * \param t the type to return the size of
4829  * \returns The number of bytes required to hold an instance of this
4830  * type in memory
4831  */
4832 int
mono_type_size(MonoType * t,int * align)4833 mono_type_size (MonoType *t, int *align)
4834 {
4835 	MonoTypeEnum simple_type;
4836 
4837 	if (!t) {
4838 		*align = 1;
4839 		return 0;
4840 	}
4841 	if (t->byref) {
4842 		*align = MONO_ABI_ALIGNOF (gpointer);
4843 		return MONO_ABI_SIZEOF (gpointer);
4844 	}
4845 
4846 	simple_type = t->type;
4847  again:
4848 	switch (simple_type) {
4849 	case MONO_TYPE_VOID:
4850 		*align = 1;
4851 		return 0;
4852 	case MONO_TYPE_BOOLEAN:
4853 		*align = MONO_ABI_ALIGNOF (gint8);
4854 		return 1;
4855 	case MONO_TYPE_I1:
4856 	case MONO_TYPE_U1:
4857 		*align = MONO_ABI_ALIGNOF (gint8);
4858 		return 1;
4859 	case MONO_TYPE_CHAR:
4860 	case MONO_TYPE_I2:
4861 	case MONO_TYPE_U2:
4862 		*align = MONO_ABI_ALIGNOF (gint16);
4863 		return 2;
4864 	case MONO_TYPE_I4:
4865 	case MONO_TYPE_U4:
4866 		*align = MONO_ABI_ALIGNOF (gint32);
4867 		return 4;
4868 	case MONO_TYPE_R4:
4869 		*align = MONO_ABI_ALIGNOF (float);
4870 		return 4;
4871 	case MONO_TYPE_I8:
4872 	case MONO_TYPE_U8:
4873 		*align = MONO_ABI_ALIGNOF (gint64);
4874 		return 8;
4875 	case MONO_TYPE_R8:
4876 		*align = MONO_ABI_ALIGNOF (double);
4877 		return 8;
4878 	case MONO_TYPE_I:
4879 	case MONO_TYPE_U:
4880 		*align = MONO_ABI_ALIGNOF (gpointer);
4881 		return MONO_ABI_SIZEOF (gpointer);
4882 	case MONO_TYPE_VALUETYPE: {
4883 		if (t->data.klass->enumtype)
4884 			return mono_type_size (mono_class_enum_basetype (t->data.klass), align);
4885 		else
4886 			return mono_class_value_size (t->data.klass, (guint32*)align);
4887 	}
4888 	case MONO_TYPE_STRING:
4889 	case MONO_TYPE_OBJECT:
4890 	case MONO_TYPE_CLASS:
4891 	case MONO_TYPE_SZARRAY:
4892 	case MONO_TYPE_PTR:
4893 	case MONO_TYPE_FNPTR:
4894 	case MONO_TYPE_ARRAY:
4895 		*align = MONO_ABI_ALIGNOF (gpointer);
4896 		return MONO_ABI_SIZEOF (gpointer);
4897 	case MONO_TYPE_TYPEDBYREF:
4898 		return mono_class_value_size (mono_defaults.typed_reference_class, (guint32*)align);
4899 	case MONO_TYPE_GENERICINST: {
4900 		MonoGenericClass *gclass = t->data.generic_class;
4901 		MonoClass *container_class = gclass->container_class;
4902 
4903 		// g_assert (!gclass->inst->is_open);
4904 
4905 		if (container_class->valuetype) {
4906 			if (container_class->enumtype)
4907 				return mono_type_size (mono_class_enum_basetype (container_class), align);
4908 			else
4909 				return mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
4910 		} else {
4911 			*align = MONO_ABI_ALIGNOF (gpointer);
4912 			return MONO_ABI_SIZEOF (gpointer);
4913 		}
4914 	}
4915 	case MONO_TYPE_VAR:
4916 	case MONO_TYPE_MVAR:
4917 		if (!t->data.generic_param->gshared_constraint || t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE) {
4918 			*align = MONO_ABI_ALIGNOF (gpointer);
4919 			return MONO_ABI_SIZEOF (gpointer);
4920 		} else {
4921 			/* The gparam can only match types given by gshared_constraint */
4922 			return mono_type_size (t->data.generic_param->gshared_constraint, align);
4923 			goto again;
4924 		}
4925 	default:
4926 		g_error ("mono_type_size: type 0x%02x unknown", t->type);
4927 	}
4928 	return 0;
4929 }
4930 
4931 /**
4932  * mono_type_stack_size:
4933  * \param t the type to return the size it uses on the stack
4934  * \returns The number of bytes required to hold an instance of this
4935  * type on the runtime stack
4936  */
4937 int
mono_type_stack_size(MonoType * t,int * align)4938 mono_type_stack_size (MonoType *t, int *align)
4939 {
4940 	return mono_type_stack_size_internal (t, align, FALSE);
4941 }
4942 
4943 int
mono_type_stack_size_internal(MonoType * t,int * align,gboolean allow_open)4944 mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
4945 {
4946 	int tmp;
4947 	MonoTypeEnum simple_type;
4948 #if SIZEOF_VOID_P == SIZEOF_REGISTER
4949 	int stack_slot_size = MONO_ABI_SIZEOF (gpointer);
4950 	int stack_slot_align = MONO_ABI_ALIGNOF (gpointer);
4951 #elif SIZEOF_VOID_P < SIZEOF_REGISTER
4952 	int stack_slot_size = SIZEOF_REGISTER;
4953 	int stack_slot_align = SIZEOF_REGISTER;
4954 #endif
4955 
4956 	g_assert (t != NULL);
4957 
4958 	if (!align)
4959 		align = &tmp;
4960 
4961 	if (t->byref) {
4962 		*align = stack_slot_align;
4963 		return stack_slot_size;
4964 	}
4965 
4966 	simple_type = t->type;
4967 	switch (simple_type) {
4968 	case MONO_TYPE_BOOLEAN:
4969 	case MONO_TYPE_CHAR:
4970 	case MONO_TYPE_I1:
4971 	case MONO_TYPE_U1:
4972 	case MONO_TYPE_I2:
4973 	case MONO_TYPE_U2:
4974 	case MONO_TYPE_I4:
4975 	case MONO_TYPE_U4:
4976 	case MONO_TYPE_I:
4977 	case MONO_TYPE_U:
4978 	case MONO_TYPE_STRING:
4979 	case MONO_TYPE_OBJECT:
4980 	case MONO_TYPE_CLASS:
4981 	case MONO_TYPE_SZARRAY:
4982 	case MONO_TYPE_PTR:
4983 	case MONO_TYPE_FNPTR:
4984 	case MONO_TYPE_ARRAY:
4985 		*align = stack_slot_align;
4986 		return stack_slot_size;
4987 	case MONO_TYPE_VAR:
4988 	case MONO_TYPE_MVAR:
4989 		g_assert (allow_open);
4990 		if (!t->data.generic_param->gshared_constraint || t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE) {
4991 			*align = stack_slot_align;
4992 			return stack_slot_size;
4993 		} else {
4994 			/* The gparam can only match types given by gshared_constraint */
4995 			return mono_type_stack_size_internal (t->data.generic_param->gshared_constraint, align, allow_open);
4996 		}
4997 	case MONO_TYPE_TYPEDBYREF:
4998 		*align = stack_slot_align;
4999 		return stack_slot_size * 3;
5000 	case MONO_TYPE_R4:
5001 		*align = MONO_ABI_ALIGNOF (float);
5002 		return sizeof (float);
5003 	case MONO_TYPE_I8:
5004 	case MONO_TYPE_U8:
5005 		*align = MONO_ABI_ALIGNOF (gint64);
5006 		return sizeof (gint64);
5007 	case MONO_TYPE_R8:
5008 		*align = MONO_ABI_ALIGNOF (double);
5009 		return sizeof (double);
5010 	case MONO_TYPE_VALUETYPE: {
5011 		guint32 size;
5012 
5013 		if (t->data.klass->enumtype)
5014 			return mono_type_stack_size_internal (mono_class_enum_basetype (t->data.klass), align, allow_open);
5015 		else {
5016 			size = mono_class_value_size (t->data.klass, (guint32*)align);
5017 
5018 			*align = *align + stack_slot_align - 1;
5019 			*align &= ~(stack_slot_align - 1);
5020 
5021 			size += stack_slot_size - 1;
5022 			size &= ~(stack_slot_size - 1);
5023 
5024 			return size;
5025 		}
5026 	}
5027 	case MONO_TYPE_GENERICINST: {
5028 		MonoGenericClass *gclass = t->data.generic_class;
5029 		MonoClass *container_class = gclass->container_class;
5030 
5031 		if (!allow_open)
5032 			g_assert (!gclass->context.class_inst->is_open);
5033 
5034 		if (container_class->valuetype) {
5035 			if (container_class->enumtype)
5036 				return mono_type_stack_size_internal (mono_class_enum_basetype (container_class), align, allow_open);
5037 			else {
5038 				guint32 size = mono_class_value_size (mono_class_from_mono_type (t), (guint32*)align);
5039 
5040 				*align = *align + stack_slot_align - 1;
5041 				*align &= ~(stack_slot_align - 1);
5042 
5043 				size += stack_slot_size - 1;
5044 				size &= ~(stack_slot_size - 1);
5045 
5046 				return size;
5047 			}
5048 		} else {
5049 			*align = stack_slot_align;
5050 			return stack_slot_size;
5051 		}
5052 	}
5053 	default:
5054 		g_error ("type 0x%02x unknown", t->type);
5055 	}
5056 	return 0;
5057 }
5058 
5059 gboolean
mono_type_generic_inst_is_valuetype(MonoType * type)5060 mono_type_generic_inst_is_valuetype (MonoType *type)
5061 {
5062 	g_assert (type->type == MONO_TYPE_GENERICINST);
5063 	return type->data.generic_class->container_class->valuetype;
5064 }
5065 
5066 /**
5067  * mono_metadata_generic_class_is_valuetype:
5068  */
5069 gboolean
mono_metadata_generic_class_is_valuetype(MonoGenericClass * gclass)5070 mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
5071 {
5072 	return gclass->container_class->valuetype;
5073 }
5074 
5075 static gboolean
_mono_metadata_generic_class_equal(const MonoGenericClass * g1,const MonoGenericClass * g2,gboolean signature_only)5076 _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
5077 {
5078 	MonoGenericInst *i1 = g1->context.class_inst;
5079 	MonoGenericInst *i2 = g2->context.class_inst;
5080 
5081 	if (g1->is_dynamic != g2->is_dynamic)
5082 		return FALSE;
5083 	if (!mono_metadata_class_equal (g1->container_class, g2->container_class, signature_only))
5084 		return FALSE;
5085 	if (!mono_generic_inst_equal_full (i1, i2, signature_only))
5086 		return FALSE;
5087 	return g1->is_tb_open == g2->is_tb_open;
5088 }
5089 
5090 static gboolean
_mono_metadata_generic_class_container_equal(const MonoGenericClass * g1,MonoClass * c2,gboolean signature_only)5091 _mono_metadata_generic_class_container_equal (const MonoGenericClass *g1, MonoClass *c2, gboolean signature_only)
5092 {
5093 	MonoGenericInst *i1 = g1->context.class_inst;
5094 	MonoGenericInst *i2 = mono_class_get_generic_container (c2)->context.class_inst;
5095 
5096 	if (!mono_metadata_class_equal (g1->container_class, c2, signature_only))
5097 		return FALSE;
5098 	if (!mono_generic_inst_equal_full (i1, i2, signature_only))
5099 		return FALSE;
5100 	return !g1->is_tb_open;
5101 }
5102 
5103 guint
mono_metadata_generic_context_hash(const MonoGenericContext * context)5104 mono_metadata_generic_context_hash (const MonoGenericContext *context)
5105 {
5106 	/* FIXME: check if this seed is good enough */
5107 	guint hash = 0xc01dfee7;
5108 	if (context->class_inst)
5109 		hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->class_inst);
5110 	if (context->method_inst)
5111 		hash = ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (context->method_inst);
5112 	return hash;
5113 }
5114 
5115 gboolean
mono_metadata_generic_context_equal(const MonoGenericContext * g1,const MonoGenericContext * g2)5116 mono_metadata_generic_context_equal (const MonoGenericContext *g1, const MonoGenericContext *g2)
5117 {
5118 	return g1->class_inst == g2->class_inst && g1->method_inst == g2->method_inst;
5119 }
5120 
5121 /*
5122  * mono_metadata_str_hash:
5123  *
5124  *   This should be used instead of g_str_hash for computing hash codes visible
5125  * outside this module, since g_str_hash () is not guaranteed to be stable
5126  * (its not the same in eglib for example).
5127  */
5128 guint
mono_metadata_str_hash(gconstpointer v1)5129 mono_metadata_str_hash (gconstpointer v1)
5130 {
5131 	/* Same as g_str_hash () in glib */
5132 	char *p = (char *) v1;
5133 	guint hash = *p;
5134 
5135 	while (*p++) {
5136 		if (*p)
5137 			hash = (hash << 5) - hash + *p;
5138 	}
5139 
5140 	return hash;
5141 }
5142 
5143 /**
5144  * mono_metadata_type_hash:
5145  * \param t1 a type
5146  * Computes a hash value for \p t1 to be used in \c GHashTable.
5147  * The returned hash is guaranteed to be the same across executions.
5148  */
5149 guint
mono_metadata_type_hash(MonoType * t1)5150 mono_metadata_type_hash (MonoType *t1)
5151 {
5152 	guint hash = t1->type;
5153 
5154 	hash |= t1->byref << 6; /* do not collide with t1->type values */
5155 	switch (t1->type) {
5156 	case MONO_TYPE_VALUETYPE:
5157 	case MONO_TYPE_CLASS:
5158 	case MONO_TYPE_SZARRAY: {
5159 		MonoClass *klass = t1->data.klass;
5160 		/*
5161 		 * Dynamic classes must not be hashed on their type since it can change
5162 		 * during runtime. For example, if we hash a reference type that is
5163 		 * later made into a valuetype.
5164 		 *
5165 		 * This is specially problematic with generic instances since they are
5166 		 * inserted in a bunch of hash tables before been finished.
5167 		 */
5168 		if (image_is_dynamic (klass->image))
5169 			return (t1->byref << 6) | mono_metadata_str_hash (klass->name);
5170 		return ((hash << 5) - hash) ^ mono_metadata_str_hash (klass->name);
5171 	}
5172 	case MONO_TYPE_PTR:
5173 		return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
5174 	case MONO_TYPE_ARRAY:
5175 		return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
5176 	case MONO_TYPE_GENERICINST:
5177 		return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
5178 	case MONO_TYPE_VAR:
5179 	case MONO_TYPE_MVAR:
5180 		return ((hash << 5) - hash) ^ mono_metadata_generic_param_hash (t1->data.generic_param);
5181 	default:
5182 		return hash;
5183 	}
5184 }
5185 
5186 guint
mono_metadata_generic_param_hash(MonoGenericParam * p)5187 mono_metadata_generic_param_hash (MonoGenericParam *p)
5188 {
5189 	guint hash;
5190 	MonoGenericParamInfo *info;
5191 
5192 	hash = (mono_generic_param_num (p) << 2);
5193 	if (p->gshared_constraint)
5194 		hash = ((hash << 5) - hash) ^ mono_metadata_type_hash (p->gshared_constraint);
5195 	info = mono_generic_param_info (p);
5196 	/* Can't hash on the owner klass/method, since those might not be set when this is called */
5197 	if (info)
5198 		hash = ((hash << 5) - hash) ^ info->token;
5199 	return hash;
5200 }
5201 
5202 static gboolean
mono_metadata_generic_param_equal_internal(MonoGenericParam * p1,MonoGenericParam * p2,gboolean signature_only)5203 mono_metadata_generic_param_equal_internal (MonoGenericParam *p1, MonoGenericParam *p2, gboolean signature_only)
5204 {
5205 	if (p1 == p2)
5206 		return TRUE;
5207 	if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
5208 		return FALSE;
5209 	if (p1->gshared_constraint && p2->gshared_constraint) {
5210 		if (!mono_metadata_type_equal (p1->gshared_constraint, p2->gshared_constraint))
5211 			return FALSE;
5212 	} else {
5213 		if (p1->gshared_constraint != p2->gshared_constraint)
5214 			return FALSE;
5215 	}
5216 
5217 	/*
5218 	 * We have to compare the image as well because if we didn't,
5219 	 * the generic_inst_cache lookup wouldn't care about the image
5220 	 * of generic params, so what could happen is that a generic
5221 	 * inst with params from image A is put into the cache, then
5222 	 * image B gets that generic inst from the cache, image A is
5223 	 * unloaded, so the inst is deleted, but image B still retains
5224 	 * a pointer to it.
5225 	 */
5226 	if (mono_generic_param_owner (p1) == mono_generic_param_owner (p2))
5227 		return TRUE;
5228 
5229 	/*
5230 	 * If `signature_only' is true, we're comparing two (method) signatures.
5231 	 * In this case, the owner of two type parameters doesn't need to match.
5232 	 */
5233 
5234 	return signature_only;
5235 }
5236 
5237 gboolean
mono_metadata_generic_param_equal(MonoGenericParam * p1,MonoGenericParam * p2)5238 mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2)
5239 {
5240 	return mono_metadata_generic_param_equal_internal (p1, p2, TRUE);
5241 }
5242 
5243 static gboolean
mono_metadata_class_equal(MonoClass * c1,MonoClass * c2,gboolean signature_only)5244 mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only)
5245 {
5246 	if (c1 == c2)
5247 		return TRUE;
5248 	if (mono_class_is_ginst (c1) && mono_class_is_ginst (c2))
5249 		return _mono_metadata_generic_class_equal (mono_class_get_generic_class (c1), mono_class_get_generic_class (c2), signature_only);
5250 	if (mono_class_is_ginst (c1) && mono_class_is_gtd (c2))
5251 		return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c1), c2, signature_only);
5252 	if (mono_class_is_gtd (c1) && mono_class_is_ginst (c2))
5253 		return _mono_metadata_generic_class_container_equal (mono_class_get_generic_class (c2), c1, signature_only);
5254 	if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
5255 		return mono_metadata_generic_param_equal_internal (
5256 			c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
5257 	if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR))
5258 		return mono_metadata_generic_param_equal_internal (
5259 			c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
5260 	if (signature_only &&
5261 	    (c1->byval_arg.type == MONO_TYPE_SZARRAY) && (c2->byval_arg.type == MONO_TYPE_SZARRAY))
5262 		return mono_metadata_class_equal (c1->byval_arg.data.klass, c2->byval_arg.data.klass, signature_only);
5263 	if (signature_only &&
5264 	    (c1->byval_arg.type == MONO_TYPE_ARRAY) && (c2->byval_arg.type == MONO_TYPE_ARRAY))
5265 		return do_mono_metadata_type_equal (&c1->byval_arg, &c2->byval_arg, signature_only);
5266 	return FALSE;
5267 }
5268 
5269 static gboolean
mono_metadata_fnptr_equal(MonoMethodSignature * s1,MonoMethodSignature * s2,gboolean signature_only)5270 mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only)
5271 {
5272 	gpointer iter1 = 0, iter2 = 0;
5273 
5274 	if (s1 == s2)
5275 		return TRUE;
5276 	if (s1->call_convention != s2->call_convention)
5277 		return FALSE;
5278 	if (s1->sentinelpos != s2->sentinelpos)
5279 		return FALSE;
5280 	if (s1->hasthis != s2->hasthis)
5281 		return FALSE;
5282 	if (s1->explicit_this != s2->explicit_this)
5283 		return FALSE;
5284 	if (! do_mono_metadata_type_equal (s1->ret, s2->ret, signature_only))
5285 		return FALSE;
5286 	if (s1->param_count != s2->param_count)
5287 		return FALSE;
5288 
5289 	while (TRUE) {
5290 		MonoType *t1 = mono_signature_get_params (s1, &iter1);
5291 		MonoType *t2 = mono_signature_get_params (s2, &iter2);
5292 
5293 		if (t1 == NULL || t2 == NULL)
5294 			return (t1 == t2);
5295 		if (! do_mono_metadata_type_equal (t1, t2, signature_only))
5296 			return FALSE;
5297 	}
5298 }
5299 
5300 /*
5301  * mono_metadata_type_equal:
5302  * @t1: a type
5303  * @t2: another type
5304  * @signature_only: If true, treat ginsts as equal which are instantiated separately but have equal positional value
5305  *
5306  * Determine if @t1 and @t2 represent the same type.
5307  * Returns: #TRUE if @t1 and @t2 are equal.
5308  */
5309 static gboolean
do_mono_metadata_type_equal(MonoType * t1,MonoType * t2,gboolean signature_only)5310 do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only)
5311 {
5312 	if (t1->type != t2->type || t1->byref != t2->byref)
5313 		return FALSE;
5314 
5315 	switch (t1->type) {
5316 	case MONO_TYPE_VOID:
5317 	case MONO_TYPE_BOOLEAN:
5318 	case MONO_TYPE_CHAR:
5319 	case MONO_TYPE_I1:
5320 	case MONO_TYPE_U1:
5321 	case MONO_TYPE_I2:
5322 	case MONO_TYPE_U2:
5323 	case MONO_TYPE_I4:
5324 	case MONO_TYPE_U4:
5325 	case MONO_TYPE_I8:
5326 	case MONO_TYPE_U8:
5327 	case MONO_TYPE_R4:
5328 	case MONO_TYPE_R8:
5329 	case MONO_TYPE_STRING:
5330 	case MONO_TYPE_I:
5331 	case MONO_TYPE_U:
5332 	case MONO_TYPE_OBJECT:
5333 	case MONO_TYPE_TYPEDBYREF:
5334 		return TRUE;
5335 	case MONO_TYPE_VALUETYPE:
5336 	case MONO_TYPE_CLASS:
5337 	case MONO_TYPE_SZARRAY:
5338 		return mono_metadata_class_equal (t1->data.klass, t2->data.klass, signature_only);
5339 	case MONO_TYPE_PTR:
5340 		return do_mono_metadata_type_equal (t1->data.type, t2->data.type, signature_only);
5341 	case MONO_TYPE_ARRAY:
5342 		if (t1->data.array->rank != t2->data.array->rank)
5343 			return FALSE;
5344 		return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass, signature_only);
5345 	case MONO_TYPE_GENERICINST:
5346 		return _mono_metadata_generic_class_equal (
5347 			t1->data.generic_class, t2->data.generic_class, signature_only);
5348 	case MONO_TYPE_VAR:
5349 		return mono_metadata_generic_param_equal_internal (
5350 			t1->data.generic_param, t2->data.generic_param, signature_only);
5351 	case MONO_TYPE_MVAR:
5352 		return mono_metadata_generic_param_equal_internal (
5353 			t1->data.generic_param, t2->data.generic_param, signature_only);
5354 	case MONO_TYPE_FNPTR:
5355 		return mono_metadata_fnptr_equal (t1->data.method, t2->data.method, signature_only);
5356 	default:
5357 		g_error ("implement type compare for %0x!", t1->type);
5358 		return FALSE;
5359 	}
5360 
5361 	return FALSE;
5362 }
5363 
5364 /**
5365  * mono_metadata_type_equal:
5366  */
5367 gboolean
mono_metadata_type_equal(MonoType * t1,MonoType * t2)5368 mono_metadata_type_equal (MonoType *t1, MonoType *t2)
5369 {
5370 	return do_mono_metadata_type_equal (t1, t2, FALSE);
5371 }
5372 
5373 /**
5374  * mono_metadata_type_equal_full:
5375  * \param t1 a type
5376  * \param t2 another type
5377  * \param signature_only if signature only comparison should be made
5378  *
5379  * Determine if \p t1 and \p t2 are signature compatible if \p signature_only is TRUE, otherwise
5380  * behaves the same way as mono_metadata_type_equal.
5381  * The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
5382  * \returns TRUE if \p t1 and \p t2 are equal taking \p signature_only into account.
5383  */
5384 gboolean
mono_metadata_type_equal_full(MonoType * t1,MonoType * t2,gboolean signature_only)5385 mono_metadata_type_equal_full (MonoType *t1, MonoType *t2, gboolean signature_only)
5386 {
5387 	return do_mono_metadata_type_equal (t1, t2, signature_only);
5388 }
5389 
5390 /**
5391  * mono_metadata_signature_equal:
5392  * \param sig1 a signature
5393  * \param sig2 another signature
5394  *
5395  * Determine if \p sig1 and \p sig2 represent the same signature, with the
5396  * same number of arguments and the same types.
5397  * \returns TRUE if \p sig1 and \p sig2 are equal.
5398  */
5399 gboolean
mono_metadata_signature_equal(MonoMethodSignature * sig1,MonoMethodSignature * sig2)5400 mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *sig2)
5401 {
5402 	int i;
5403 
5404 	if (sig1->hasthis != sig2->hasthis || sig1->param_count != sig2->param_count)
5405 		return FALSE;
5406 
5407 	if (sig1->generic_param_count != sig2->generic_param_count)
5408 		return FALSE;
5409 
5410 	/*
5411 	 * We're just comparing the signatures of two methods here:
5412 	 *
5413 	 * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
5414 	 * U and V are equal here.
5415 	 *
5416 	 * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
5417 	 */
5418 
5419 	for (i = 0; i < sig1->param_count; i++) {
5420 		MonoType *p1 = sig1->params[i];
5421 		MonoType *p2 = sig2->params[i];
5422 
5423 		/* if (p1->attrs != p2->attrs)
5424 			return FALSE;
5425 		*/
5426 		if (!do_mono_metadata_type_equal (p1, p2, TRUE))
5427 			return FALSE;
5428 	}
5429 
5430 	if (!do_mono_metadata_type_equal (sig1->ret, sig2->ret, TRUE))
5431 		return FALSE;
5432 	return TRUE;
5433 }
5434 
5435 /**
5436  * mono_metadata_type_dup:
5437  * \param image image to alloc memory from
5438  * \param original type to duplicate
5439  * \returns copy of type allocated from the image's mempool (or from the heap, if \p image is null).
5440  */
5441 MonoType *
mono_metadata_type_dup(MonoImage * image,const MonoType * o)5442 mono_metadata_type_dup (MonoImage *image, const MonoType *o)
5443 {
5444 	MonoType *r = NULL;
5445 	int sizeof_o = MONO_SIZEOF_TYPE;
5446 	if (o->num_mods)
5447 		sizeof_o += o->num_mods  * sizeof (MonoCustomMod);
5448 
5449 	r = image ? (MonoType *)mono_image_alloc0 (image, sizeof_o) : (MonoType *)g_malloc (sizeof_o);
5450 
5451 	memcpy (r, o, sizeof_o);
5452 
5453 	if (o->type == MONO_TYPE_PTR) {
5454 		r->data.type = mono_metadata_type_dup (image, o->data.type);
5455 	} else if (o->type == MONO_TYPE_ARRAY) {
5456 		r->data.array = mono_dup_array_type (image, o->data.array);
5457 	} else if (o->type == MONO_TYPE_FNPTR) {
5458 		/*FIXME the dup'ed signature is leaked mono_metadata_free_type*/
5459 		r->data.method = mono_metadata_signature_deep_dup (image, o->data.method);
5460 	}
5461 	return r;
5462 }
5463 
5464 /**
5465  * mono_signature_hash:
5466  */
5467 guint
mono_signature_hash(MonoMethodSignature * sig)5468 mono_signature_hash (MonoMethodSignature *sig)
5469 {
5470 	guint i, res = sig->ret->type;
5471 
5472 	for (i = 0; i < sig->param_count; i++)
5473 		res = (res << 5) - res + mono_type_hash (sig->params[i]);
5474 
5475 	return res;
5476 }
5477 
5478 /*
5479  * mono_metadata_encode_value:
5480  * @value: value to encode
5481  * @buf: buffer where to write the compressed representation
5482  * @endbuf: pointer updated to point at the end of the encoded output
5483  *
5484  * Encodes the value @value in the compressed representation used
5485  * in metadata and stores the result in @buf. @buf needs to be big
5486  * enough to hold the data (4 bytes).
5487  */
5488 void
mono_metadata_encode_value(guint32 value,char * buf,char ** endbuf)5489 mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
5490 {
5491 	char *p = buf;
5492 
5493 	if (value < 0x80)
5494 		*p++ = value;
5495 	else if (value < 0x4000) {
5496 		p [0] = 0x80 | (value >> 8);
5497 		p [1] = value & 0xff;
5498 		p += 2;
5499 	} else {
5500 		p [0] = (value >> 24) | 0xc0;
5501 		p [1] = (value >> 16) & 0xff;
5502 		p [2] = (value >> 8) & 0xff;
5503 		p [3] = value & 0xff;
5504 		p += 4;
5505 	}
5506 	if (endbuf)
5507 		*endbuf = p;
5508 }
5509 
5510 /**
5511  * mono_metadata_field_info:
5512  * \param meta the Image the field is defined in
5513  * \param index the index in the field table representing the field
5514  * \param offset a pointer to an integer where to store the offset that  may have been specified for the field in a FieldLayout table
5515  * \param rva a pointer to the RVA of the field data in the image that may have been defined in a \c FieldRVA table
5516  * \param marshal_spec a pointer to the marshal spec that may have been defined for the field in a \c FieldMarshal table.
5517  *
5518  * Gather info for field \p index that may have been defined in the \c FieldLayout,
5519  * \c FieldRVA and \c FieldMarshal tables.
5520  * Either of \p offset, \p rva and \p marshal_spec can be NULL if you're not interested
5521  * in the data.
5522  */
5523 void
mono_metadata_field_info(MonoImage * meta,guint32 index,guint32 * offset,guint32 * rva,MonoMarshalSpec ** marshal_spec)5524 mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
5525 			  MonoMarshalSpec **marshal_spec)
5526 {
5527 	mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, FALSE);
5528 }
5529 
5530 void
mono_metadata_field_info_with_mempool(MonoImage * meta,guint32 index,guint32 * offset,guint32 * rva,MonoMarshalSpec ** marshal_spec)5531 mono_metadata_field_info_with_mempool (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
5532 			  MonoMarshalSpec **marshal_spec)
5533 {
5534 	mono_metadata_field_info_full (meta, index, offset, rva, marshal_spec, TRUE);
5535 }
5536 
5537 static void
mono_metadata_field_info_full(MonoImage * meta,guint32 index,guint32 * offset,guint32 * rva,MonoMarshalSpec ** marshal_spec,gboolean alloc_from_image)5538 mono_metadata_field_info_full (MonoImage *meta, guint32 index, guint32 *offset, guint32 *rva,
5539 				       MonoMarshalSpec **marshal_spec, gboolean alloc_from_image)
5540 {
5541 	MonoTableInfo *tdef;
5542 	locator_t loc;
5543 
5544 	loc.idx = index + 1;
5545 	if (meta->uncompressed_metadata)
5546 		loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
5547 
5548 	if (offset) {
5549 		tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
5550 
5551 		loc.col_idx = MONO_FIELD_LAYOUT_FIELD;
5552 		loc.t = tdef;
5553 
5554 		if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
5555 			*offset = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_LAYOUT_OFFSET);
5556 		} else {
5557 			*offset = (guint32)-1;
5558 		}
5559 	}
5560 	if (rva) {
5561 		tdef = &meta->tables [MONO_TABLE_FIELDRVA];
5562 
5563 		loc.col_idx = MONO_FIELD_RVA_FIELD;
5564 		loc.t = tdef;
5565 
5566 		if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
5567 			/*
5568 			 * LAMESPEC: There is no signature, no nothing, just the raw data.
5569 			 */
5570 			*rva = mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_RVA_RVA);
5571 		} else {
5572 			*rva = 0;
5573 		}
5574 	}
5575 	if (marshal_spec) {
5576 		const char *p;
5577 
5578 		if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) {
5579 			*marshal_spec = mono_metadata_parse_marshal_spec_full (alloc_from_image ? meta : NULL, meta, p);
5580 		}
5581 	}
5582 
5583 }
5584 
5585 /**
5586  * mono_metadata_get_constant_index:
5587  * \param meta the Image the field is defined in
5588  * \param index the token that may have a row defined in the constants table
5589  * \param hint possible position for the row
5590  *
5591  * \p token must be a \c FieldDef, \c ParamDef or \c PropertyDef token.
5592  *
5593  * \returns the index into the \c Constants table or 0 if not found.
5594  */
5595 guint32
mono_metadata_get_constant_index(MonoImage * meta,guint32 token,guint32 hint)5596 mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
5597 {
5598 	MonoTableInfo *tdef;
5599 	locator_t loc;
5600 	guint32 index = mono_metadata_token_index (token);
5601 
5602 	tdef = &meta->tables [MONO_TABLE_CONSTANT];
5603 	index <<= MONO_HASCONSTANT_BITS;
5604 	switch (mono_metadata_token_table (token)) {
5605 	case MONO_TABLE_FIELD:
5606 		index |= MONO_HASCONSTANT_FIEDDEF;
5607 		break;
5608 	case MONO_TABLE_PARAM:
5609 		index |= MONO_HASCONSTANT_PARAM;
5610 		break;
5611 	case MONO_TABLE_PROPERTY:
5612 		index |= MONO_HASCONSTANT_PROPERTY;
5613 		break;
5614 	default:
5615 		g_warning ("Not a valid token for the constant table: 0x%08x", token);
5616 		return 0;
5617 	}
5618 	loc.idx = index;
5619 	loc.col_idx = MONO_CONSTANT_PARENT;
5620 	loc.t = tdef;
5621 
5622 	/* FIXME: Index translation */
5623 
5624 	if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
5625 		return hint;
5626 
5627 	if (tdef->base && mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
5628 		return loc.result + 1;
5629 	}
5630 	return 0;
5631 }
5632 
5633 /**
5634  * mono_metadata_events_from_typedef:
5635  * \param meta metadata context
5636  * \param index 0-based index (in the \c TypeDef table) describing a type
5637  * \returns the 0-based index in the \c Event table for the events in the
5638  * type. The last event that belongs to the type (plus 1) is stored
5639  * in the \p end_idx pointer.
5640  */
5641 guint32
mono_metadata_events_from_typedef(MonoImage * meta,guint32 index,guint * end_idx)5642 mono_metadata_events_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
5643 {
5644 	locator_t loc;
5645 	guint32 start, end;
5646 	MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_EVENTMAP];
5647 
5648 	*end_idx = 0;
5649 
5650 	if (!tdef->base)
5651 		return 0;
5652 
5653 	loc.t = tdef;
5654 	loc.col_idx = MONO_EVENT_MAP_PARENT;
5655 	loc.idx = index + 1;
5656 
5657 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5658 		return 0;
5659 
5660 	start = mono_metadata_decode_row_col (tdef, loc.result, MONO_EVENT_MAP_EVENTLIST);
5661 	if (loc.result + 1 < tdef->rows) {
5662 		end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_EVENT_MAP_EVENTLIST) - 1;
5663 	} else {
5664 		end = meta->tables [MONO_TABLE_EVENT].rows;
5665 	}
5666 
5667 	*end_idx = end;
5668 	return start - 1;
5669 }
5670 
5671 /**
5672  * mono_metadata_methods_from_event:
5673  * \param meta metadata context
5674  * \param index 0-based index (in the \c Event table) describing a event
5675  * \returns the 0-based index in the \c MethodDef table for the methods in the
5676  * event. The last method that belongs to the event (plus 1) is stored
5677  * in the \p end_idx pointer.
5678  */
5679 guint32
mono_metadata_methods_from_event(MonoImage * meta,guint32 index,guint * end_idx)5680 mono_metadata_methods_from_event   (MonoImage *meta, guint32 index, guint *end_idx)
5681 {
5682 	locator_t loc;
5683 	guint start, end;
5684 	guint32 cols [MONO_METHOD_SEMA_SIZE];
5685 	MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
5686 
5687 	*end_idx = 0;
5688 	if (!msemt->base)
5689 		return 0;
5690 
5691 	if (meta->uncompressed_metadata)
5692 	    index = search_ptr_table (meta, MONO_TABLE_EVENT_POINTER, index + 1) - 1;
5693 
5694 	loc.t = msemt;
5695 	loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
5696 	loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
5697 
5698 	if (!mono_binary_search (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
5699 		return 0;
5700 
5701 	start = loc.result;
5702 	/*
5703 	 * We may end up in the middle of the rows...
5704 	 */
5705 	while (start > 0) {
5706 		if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
5707 			start--;
5708 		else
5709 			break;
5710 	}
5711 	end = start + 1;
5712 	while (end < msemt->rows) {
5713 		mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
5714 		if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
5715 			break;
5716 		++end;
5717 	}
5718 	*end_idx = end;
5719 	return start;
5720 }
5721 
5722 /**
5723  * mono_metadata_properties_from_typedef:
5724  * \param meta metadata context
5725  * \param index 0-based index (in the \c TypeDef table) describing a type
5726  * \returns the 0-based index in the \c Property table for the properties in the
5727  * type. The last property that belongs to the type (plus 1) is stored
5728  * in the \p end_idx pointer.
5729  */
5730 guint32
mono_metadata_properties_from_typedef(MonoImage * meta,guint32 index,guint * end_idx)5731 mono_metadata_properties_from_typedef (MonoImage *meta, guint32 index, guint *end_idx)
5732 {
5733 	locator_t loc;
5734 	guint32 start, end;
5735 	MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_PROPERTYMAP];
5736 
5737 	*end_idx = 0;
5738 
5739 	if (!tdef->base)
5740 		return 0;
5741 
5742 	loc.t = tdef;
5743 	loc.col_idx = MONO_PROPERTY_MAP_PARENT;
5744 	loc.idx = index + 1;
5745 
5746 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5747 		return 0;
5748 
5749 	start = mono_metadata_decode_row_col (tdef, loc.result, MONO_PROPERTY_MAP_PROPERTY_LIST);
5750 	if (loc.result + 1 < tdef->rows) {
5751 		end = mono_metadata_decode_row_col (tdef, loc.result + 1, MONO_PROPERTY_MAP_PROPERTY_LIST) - 1;
5752 	} else {
5753 		end = meta->tables [MONO_TABLE_PROPERTY].rows;
5754 	}
5755 
5756 	*end_idx = end;
5757 	return start - 1;
5758 }
5759 
5760 /**
5761  * mono_metadata_methods_from_property:
5762  * \param meta metadata context
5763  * \param index 0-based index (in the \c PropertyDef table) describing a property
5764  * \returns the 0-based index in the \c MethodDef table for the methods in the
5765  * property. The last method that belongs to the property (plus 1) is stored
5766  * in the \p end_idx pointer.
5767  */
5768 guint32
mono_metadata_methods_from_property(MonoImage * meta,guint32 index,guint * end_idx)5769 mono_metadata_methods_from_property   (MonoImage *meta, guint32 index, guint *end_idx)
5770 {
5771 	locator_t loc;
5772 	guint start, end;
5773 	guint32 cols [MONO_METHOD_SEMA_SIZE];
5774 	MonoTableInfo *msemt = &meta->tables [MONO_TABLE_METHODSEMANTICS];
5775 
5776 	*end_idx = 0;
5777 	if (!msemt->base)
5778 		return 0;
5779 
5780 	if (meta->uncompressed_metadata)
5781 	    index = search_ptr_table (meta, MONO_TABLE_PROPERTY_POINTER, index + 1) - 1;
5782 
5783 	loc.t = msemt;
5784 	loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
5785 	loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
5786 
5787 	if (!mono_binary_search (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
5788 		return 0;
5789 
5790 	start = loc.result;
5791 	/*
5792 	 * We may end up in the middle of the rows...
5793 	 */
5794 	while (start > 0) {
5795 		if (loc.idx == mono_metadata_decode_row_col (msemt, start - 1, MONO_METHOD_SEMA_ASSOCIATION))
5796 			start--;
5797 		else
5798 			break;
5799 	}
5800 	end = start + 1;
5801 	while (end < msemt->rows) {
5802 		mono_metadata_decode_row (msemt, end, cols, MONO_METHOD_SEMA_SIZE);
5803 		if (cols [MONO_METHOD_SEMA_ASSOCIATION] != loc.idx)
5804 			break;
5805 		++end;
5806 	}
5807 	*end_idx = end;
5808 	return start;
5809 }
5810 
5811 /**
5812  * mono_metadata_implmap_from_method:
5813  */
5814 guint32
mono_metadata_implmap_from_method(MonoImage * meta,guint32 method_idx)5815 mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
5816 {
5817 	locator_t loc;
5818 	MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_IMPLMAP];
5819 
5820 	if (!tdef->base)
5821 		return 0;
5822 
5823 	/* No index translation seems to be needed */
5824 
5825 	loc.t = tdef;
5826 	loc.col_idx = MONO_IMPLMAP_MEMBER;
5827 	loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
5828 
5829 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
5830 		return 0;
5831 
5832 	return loc.result + 1;
5833 }
5834 
5835 /**
5836  * mono_type_create_from_typespec:
5837  * \param image context where the image is created
5838  * \param type_spec  typespec token
5839  * \deprecated use \c mono_type_create_from_typespec_checked that has proper error handling
5840  *
5841  * Creates a \c MonoType representing the \c TypeSpec indexed by the \p type_spec
5842  * token.
5843  */
5844 MonoType *
mono_type_create_from_typespec(MonoImage * image,guint32 type_spec)5845 mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
5846 {
5847 	MonoError error;
5848 	MonoType *type = mono_type_create_from_typespec_checked (image, type_spec, &error);
5849 	if (!type)
5850 		 g_error ("Could not create typespec %x due to %s", type_spec, mono_error_get_message (&error));
5851 	return type;
5852 }
5853 
5854 MonoType *
mono_type_create_from_typespec_checked(MonoImage * image,guint32 type_spec,MonoError * error)5855 mono_type_create_from_typespec_checked (MonoImage *image, guint32 type_spec, MonoError *error)
5856 
5857 {
5858 	guint32 idx = mono_metadata_token_index (type_spec);
5859 	MonoTableInfo *t;
5860 	guint32 cols [MONO_TYPESPEC_SIZE];
5861 	const char *ptr;
5862 	MonoType *type, *type2;
5863 
5864 	error_init (error);
5865 
5866 	type = (MonoType *)mono_conc_hashtable_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
5867 	if (type)
5868 		return type;
5869 
5870 	t = &image->tables [MONO_TABLE_TYPESPEC];
5871 
5872 	mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
5873 	ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
5874 
5875 	if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], type_spec, NULL)) {
5876 		mono_error_set_bad_image (error, image, "Could not verify type spec %08x.", type_spec);
5877 		return NULL;
5878 	}
5879 
5880 	mono_metadata_decode_value (ptr, &ptr);
5881 
5882 	type = mono_metadata_parse_type_checked (image, NULL, 0, TRUE, ptr, &ptr, error);
5883 	if (!type)
5884 		return NULL;
5885 
5886 	type2 = mono_metadata_type_dup (image, type);
5887 	mono_metadata_free_type (type);
5888 
5889 	mono_image_lock (image);
5890 
5891 	/* We might leak some data in the image mempool if found */
5892 	type = mono_conc_hashtable_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type2);
5893 	if (!type)
5894 		type = type2;
5895 
5896 	mono_image_unlock (image);
5897 
5898 	return type;
5899 }
5900 
5901 
5902 static char*
mono_image_strndup(MonoImage * image,const char * data,guint len)5903 mono_image_strndup (MonoImage *image, const char *data, guint len)
5904 {
5905 	char *res;
5906 	if (!image)
5907 		return g_strndup (data, len);
5908 	res = (char *)mono_image_alloc (image, len + 1);
5909 	memcpy (res, data, len);
5910 	res [len] = 0;
5911 	return res;
5912 }
5913 
5914 /**
5915  * mono_metadata_parse_marshal_spec:
5916  */
5917 MonoMarshalSpec *
mono_metadata_parse_marshal_spec(MonoImage * image,const char * ptr)5918 mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
5919 {
5920 	return mono_metadata_parse_marshal_spec_full (NULL, image, ptr);
5921 }
5922 
5923 /*
5924  * If IMAGE is non-null, memory will be allocated from its mempool, otherwise it will be allocated using malloc.
5925  * PARENT_IMAGE is the image containing the marshal spec.
5926  */
5927 MonoMarshalSpec *
mono_metadata_parse_marshal_spec_full(MonoImage * image,MonoImage * parent_image,const char * ptr)5928 mono_metadata_parse_marshal_spec_full (MonoImage *image, MonoImage *parent_image, const char *ptr)
5929 {
5930 	MonoMarshalSpec *res;
5931 	int len;
5932 	const char *start = ptr;
5933 
5934 	/* fixme: this is incomplete, but I cant find more infos in the specs */
5935 
5936 	if (image)
5937 		res = (MonoMarshalSpec *)mono_image_alloc0 (image, sizeof (MonoMarshalSpec));
5938 	else
5939 		res = g_new0 (MonoMarshalSpec, 1);
5940 
5941 	len = mono_metadata_decode_value (ptr, &ptr);
5942 	res->native = (MonoMarshalNative)*ptr++;
5943 
5944 	if (res->native == MONO_NATIVE_LPARRAY) {
5945 		res->data.array_data.param_num = -1;
5946 		res->data.array_data.num_elem = -1;
5947 		res->data.array_data.elem_mult = -1;
5948 
5949 		if (ptr - start <= len)
5950 			res->data.array_data.elem_type = (MonoMarshalNative)*ptr++;
5951 		if (ptr - start <= len)
5952 			res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr);
5953 		if (ptr - start <= len)
5954 			res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5955 		if (ptr - start <= len) {
5956 			/*
5957 			 * LAMESPEC: Older spec versions say this parameter comes before
5958 			 * num_elem. Never spec versions don't talk about elem_mult at
5959 			 * all, but csc still emits it, and it is used to distinguish
5960 			 * between param_num being 0, and param_num being omitted.
5961 			 * So if (param_num == 0) && (num_elem > 0), then
5962 			 * elem_mult == 0 -> the array size is num_elem
5963 			 * elem_mult == 1 -> the array size is @param_num + num_elem
5964 			 */
5965 			res->data.array_data.elem_mult = mono_metadata_decode_value (ptr, &ptr);
5966 		}
5967 	}
5968 
5969 	if (res->native == MONO_NATIVE_BYVALTSTR) {
5970 		if (ptr - start <= len)
5971 			res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5972 	}
5973 
5974 	if (res->native == MONO_NATIVE_BYVALARRAY) {
5975 		if (ptr - start <= len)
5976 			res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
5977 	}
5978 
5979 	if (res->native == MONO_NATIVE_CUSTOM) {
5980 		/* skip unused type guid */
5981 		len = mono_metadata_decode_value (ptr, &ptr);
5982 		ptr += len;
5983 		/* skip unused native type name */
5984 		len = mono_metadata_decode_value (ptr, &ptr);
5985 		ptr += len;
5986 		/* read custom marshaler type name */
5987 		len = mono_metadata_decode_value (ptr, &ptr);
5988 		res->data.custom_data.custom_name = mono_image_strndup (image, ptr, len);
5989 		ptr += len;
5990 		/* read cookie string */
5991 		len = mono_metadata_decode_value (ptr, &ptr);
5992 		res->data.custom_data.cookie = mono_image_strndup (image, ptr, len);
5993 		res->data.custom_data.image = parent_image;
5994 	}
5995 
5996 	if (res->native == MONO_NATIVE_SAFEARRAY) {
5997 		res->data.safearray_data.elem_type = (MonoMarshalVariant)0;
5998 		res->data.safearray_data.num_elem = 0;
5999 		if (ptr - start <= len)
6000 			res->data.safearray_data.elem_type = (MonoMarshalVariant)*ptr++;
6001 		if (ptr - start <= len)
6002 			res->data.safearray_data.num_elem = *ptr++;
6003 	}
6004 	return res;
6005 }
6006 
6007 /**
6008  * mono_metadata_free_marshal_spec:
6009  */
6010 void
mono_metadata_free_marshal_spec(MonoMarshalSpec * spec)6011 mono_metadata_free_marshal_spec (MonoMarshalSpec *spec)
6012 {
6013 	if (spec->native == MONO_NATIVE_CUSTOM) {
6014 		g_free (spec->data.custom_data.custom_name);
6015 		g_free (spec->data.custom_data.cookie);
6016 	}
6017 	g_free (spec);
6018 }
6019 
6020 /**
6021  * mono_type_to_unmanaged:
6022  * The value pointed to by \p conv will contain the kind of marshalling required for this
6023  * particular type one of the \c MONO_MARSHAL_CONV_ enumeration values.
6024  * \returns A \c MonoMarshalNative enumeration value (<code>MONO_NATIVE_</code>) value
6025  * describing the underlying native reprensetation of the type.
6026  */
6027 guint32
mono_type_to_unmanaged(MonoType * type,MonoMarshalSpec * mspec,gboolean as_field,gboolean unicode,MonoMarshalConv * conv)6028 mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_field,
6029 			gboolean unicode, MonoMarshalConv *conv)
6030 {
6031 	MonoMarshalConv dummy_conv;
6032 	int t = type->type;
6033 
6034 	if (!conv)
6035 		conv = &dummy_conv;
6036 
6037 	*conv = MONO_MARSHAL_CONV_NONE;
6038 
6039 	if (type->byref)
6040 		return MONO_NATIVE_UINT;
6041 
6042 handle_enum:
6043 	switch (t) {
6044 	case MONO_TYPE_BOOLEAN:
6045 		if (mspec) {
6046 			switch (mspec->native) {
6047 			case MONO_NATIVE_VARIANTBOOL:
6048 				*conv = MONO_MARSHAL_CONV_BOOL_VARIANTBOOL;
6049 				return MONO_NATIVE_VARIANTBOOL;
6050 			case MONO_NATIVE_BOOLEAN:
6051 				*conv = MONO_MARSHAL_CONV_BOOL_I4;
6052 				return MONO_NATIVE_BOOLEAN;
6053 			case MONO_NATIVE_I1:
6054 			case MONO_NATIVE_U1:
6055 				return mspec->native;
6056 			default:
6057 				g_error ("cant marshal bool to native type %02x", mspec->native);
6058 			}
6059 		}
6060 		*conv = MONO_MARSHAL_CONV_BOOL_I4;
6061 		return MONO_NATIVE_BOOLEAN;
6062 	case MONO_TYPE_CHAR:
6063 		if (mspec) {
6064 			switch (mspec->native) {
6065 			case MONO_NATIVE_U2:
6066 			case MONO_NATIVE_U1:
6067 				return mspec->native;
6068 			default:
6069 				g_error ("cant marshal char to native type %02x", mspec->native);
6070 			}
6071 		}
6072 		return unicode ? MONO_NATIVE_U2 : MONO_NATIVE_U1;
6073 	case MONO_TYPE_I1: return MONO_NATIVE_I1;
6074 	case MONO_TYPE_U1: return MONO_NATIVE_U1;
6075 	case MONO_TYPE_I2: return MONO_NATIVE_I2;
6076 	case MONO_TYPE_U2: return MONO_NATIVE_U2;
6077 	case MONO_TYPE_I4: return MONO_NATIVE_I4;
6078 	case MONO_TYPE_U4: return MONO_NATIVE_U4;
6079 	case MONO_TYPE_I8: return MONO_NATIVE_I8;
6080 	case MONO_TYPE_U8: return MONO_NATIVE_U8;
6081 	case MONO_TYPE_R4: return MONO_NATIVE_R4;
6082 	case MONO_TYPE_R8: return MONO_NATIVE_R8;
6083 	case MONO_TYPE_STRING:
6084 		if (mspec) {
6085 			switch (mspec->native) {
6086 			case MONO_NATIVE_BSTR:
6087 				*conv = MONO_MARSHAL_CONV_STR_BSTR;
6088 				return MONO_NATIVE_BSTR;
6089 			case MONO_NATIVE_LPSTR:
6090 				*conv = MONO_MARSHAL_CONV_STR_LPSTR;
6091 				return MONO_NATIVE_LPSTR;
6092 			case MONO_NATIVE_LPWSTR:
6093 				*conv = MONO_MARSHAL_CONV_STR_LPWSTR;
6094 				return MONO_NATIVE_LPWSTR;
6095 			case MONO_NATIVE_LPTSTR:
6096 				*conv = MONO_MARSHAL_CONV_STR_LPTSTR;
6097 				return MONO_NATIVE_LPTSTR;
6098 			case MONO_NATIVE_ANSIBSTR:
6099 				*conv = MONO_MARSHAL_CONV_STR_ANSIBSTR;
6100 				return MONO_NATIVE_ANSIBSTR;
6101 			case MONO_NATIVE_TBSTR:
6102 				*conv = MONO_MARSHAL_CONV_STR_TBSTR;
6103 				return MONO_NATIVE_TBSTR;
6104 			case MONO_NATIVE_UTF8STR:
6105 				*conv = MONO_MARSHAL_CONV_STR_UTF8STR;
6106 				return MONO_NATIVE_UTF8STR;
6107 			case MONO_NATIVE_BYVALTSTR:
6108 				if (unicode)
6109 					*conv = MONO_MARSHAL_CONV_STR_BYVALWSTR;
6110 				else
6111 					*conv = MONO_MARSHAL_CONV_STR_BYVALSTR;
6112 				return MONO_NATIVE_BYVALTSTR;
6113 			default:
6114 				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);
6115 			}
6116 		}
6117 		if (unicode) {
6118 			*conv = MONO_MARSHAL_CONV_STR_LPWSTR;
6119 			return MONO_NATIVE_LPWSTR;
6120 		}
6121 		else {
6122 			*conv = MONO_MARSHAL_CONV_STR_LPSTR;
6123 			return MONO_NATIVE_LPSTR;
6124 		}
6125 	case MONO_TYPE_PTR: return MONO_NATIVE_UINT;
6126 	case MONO_TYPE_VALUETYPE: /*FIXME*/
6127 		if (type->data.klass->enumtype) {
6128 			t = mono_class_enum_basetype (type->data.klass)->type;
6129 			goto handle_enum;
6130 		}
6131 		if (type->data.klass == mono_defaults.handleref_class){
6132 			*conv = MONO_MARSHAL_CONV_HANDLEREF;
6133 			return MONO_NATIVE_INT;
6134 		}
6135 		return MONO_NATIVE_STRUCT;
6136 	case MONO_TYPE_SZARRAY:
6137 	case MONO_TYPE_ARRAY:
6138 		if (mspec) {
6139 			switch (mspec->native) {
6140 			case MONO_NATIVE_BYVALARRAY:
6141 				if ((type->data.klass->element_class == mono_defaults.char_class) && !unicode)
6142 					*conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY;
6143 				else
6144 					*conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
6145 				return MONO_NATIVE_BYVALARRAY;
6146 			case MONO_NATIVE_SAFEARRAY:
6147 				*conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY;
6148 				return MONO_NATIVE_SAFEARRAY;
6149 			case MONO_NATIVE_LPARRAY:
6150 				*conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
6151 				return MONO_NATIVE_LPARRAY;
6152 			default:
6153 				g_error ("cant marshal array as native type %02x", mspec->native);
6154 			}
6155 		}
6156 
6157 		*conv = MONO_MARSHAL_CONV_ARRAY_LPARRAY;
6158 		return MONO_NATIVE_LPARRAY;
6159 	case MONO_TYPE_I: return MONO_NATIVE_INT;
6160 	case MONO_TYPE_U: return MONO_NATIVE_UINT;
6161 	case MONO_TYPE_CLASS:
6162 	case MONO_TYPE_OBJECT: {
6163 		/* FIXME : we need to handle ArrayList and StringBuilder here, probably */
6164 		if (mspec) {
6165 			switch (mspec->native) {
6166 			case MONO_NATIVE_STRUCT:
6167 				return MONO_NATIVE_STRUCT;
6168 			case MONO_NATIVE_CUSTOM:
6169 				return MONO_NATIVE_CUSTOM;
6170 			case MONO_NATIVE_INTERFACE:
6171 				*conv = MONO_MARSHAL_CONV_OBJECT_INTERFACE;
6172 				return MONO_NATIVE_INTERFACE;
6173 			case MONO_NATIVE_IDISPATCH:
6174 				*conv = MONO_MARSHAL_CONV_OBJECT_IDISPATCH;
6175 				return MONO_NATIVE_IDISPATCH;
6176 			case MONO_NATIVE_IUNKNOWN:
6177 				*conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN;
6178 				return MONO_NATIVE_IUNKNOWN;
6179 			case MONO_NATIVE_FUNC:
6180 				if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
6181 											 type->data.klass == mono_defaults.delegate_class ||
6182 											 type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
6183 					*conv = MONO_MARSHAL_CONV_DEL_FTN;
6184 					return MONO_NATIVE_FUNC;
6185 				}
6186 				/* Fall through */
6187 			default:
6188 				g_error ("cant marshal object as native type %02x", mspec->native);
6189 			}
6190 		}
6191 		if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
6192 					     type->data.klass == mono_defaults.delegate_class ||
6193 					     type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
6194 			*conv = MONO_MARSHAL_CONV_DEL_FTN;
6195 			return MONO_NATIVE_FUNC;
6196 		}
6197 		if (mono_class_try_get_safehandle_class () && type->data.klass == mono_class_try_get_safehandle_class ()){
6198 			*conv = MONO_MARSHAL_CONV_SAFEHANDLE;
6199 			return MONO_NATIVE_INT;
6200 		}
6201 		*conv = MONO_MARSHAL_CONV_OBJECT_STRUCT;
6202 		return MONO_NATIVE_STRUCT;
6203 	}
6204 	case MONO_TYPE_FNPTR: return MONO_NATIVE_FUNC;
6205 	case MONO_TYPE_GENERICINST:
6206 		type = &type->data.generic_class->container_class->byval_arg;
6207 		t = type->type;
6208 		goto handle_enum;
6209 	case MONO_TYPE_TYPEDBYREF:
6210 	default:
6211 		g_error ("type 0x%02x not handled in marshal", t);
6212 	}
6213 	return MONO_NATIVE_MAX;
6214 }
6215 
6216 /**
6217  * mono_metadata_get_marshal_info:
6218  */
6219 const char*
mono_metadata_get_marshal_info(MonoImage * meta,guint32 idx,gboolean is_field)6220 mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
6221 {
6222 	locator_t loc;
6223 	MonoTableInfo *tdef  = &meta->tables [MONO_TABLE_FIELDMARSHAL];
6224 
6225 	if (!tdef->base)
6226 		return NULL;
6227 
6228 	loc.t = tdef;
6229 	loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
6230 	loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
6231 
6232 	/* FIXME: Index translation */
6233 
6234 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
6235 		return NULL;
6236 
6237 	return mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE));
6238 }
6239 
6240 MonoMethod*
method_from_method_def_or_ref(MonoImage * m,guint32 tok,MonoGenericContext * context,MonoError * error)6241 method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context, MonoError *error)
6242 {
6243 	MonoMethod *result = NULL;
6244 	guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
6245 
6246 	error_init (error);
6247 
6248 	switch (tok & MONO_METHODDEFORREF_MASK) {
6249 	case MONO_METHODDEFORREF_METHODDEF:
6250 		result = mono_get_method_checked (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context, error);
6251 		break;
6252 	case MONO_METHODDEFORREF_METHODREF:
6253 		result = mono_get_method_checked (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context, error);
6254 		break;
6255 	default:
6256 		mono_error_set_bad_image (error, m, "Invalid MethodDefOfRef token %x", tok);
6257 	}
6258 
6259 	return result;
6260 }
6261 
6262 /*
6263  * mono_class_get_overrides_full:
6264  *
6265  *   Return the method overrides belonging to class @type_token in @overrides, and
6266  * the number of overrides in @num_overrides.
6267  *
6268  * Returns: TRUE on success, FALSE on failure.
6269  */
6270 gboolean
mono_class_get_overrides_full(MonoImage * image,guint32 type_token,MonoMethod *** overrides,gint32 * num_overrides,MonoGenericContext * generic_context)6271 mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides,
6272 			       MonoGenericContext *generic_context)
6273 {
6274 	MonoError error;
6275 	locator_t loc;
6276 	MonoTableInfo *tdef  = &image->tables [MONO_TABLE_METHODIMPL];
6277 	guint32 start, end;
6278 	gint32 i, num;
6279 	guint32 cols [MONO_METHODIMPL_SIZE];
6280 	MonoMethod **result;
6281 	gint32 ok = TRUE;
6282 
6283 	*overrides = NULL;
6284 	if (num_overrides)
6285 		*num_overrides = 0;
6286 
6287 	if (!tdef->base)
6288 		return TRUE;
6289 
6290 	loc.t = tdef;
6291 	loc.col_idx = MONO_METHODIMPL_CLASS;
6292 	loc.idx = mono_metadata_token_index (type_token);
6293 
6294 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
6295 		return TRUE;
6296 
6297 	start = loc.result;
6298 	end = start + 1;
6299 	/*
6300 	 * We may end up in the middle of the rows...
6301 	 */
6302 	while (start > 0) {
6303 		if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_METHODIMPL_CLASS))
6304 			start--;
6305 		else
6306 			break;
6307 	}
6308 	while (end < tdef->rows) {
6309 		if (loc.idx == mono_metadata_decode_row_col (tdef, end, MONO_METHODIMPL_CLASS))
6310 			end++;
6311 		else
6312 			break;
6313 	}
6314 	num = end - start;
6315 	result = g_new (MonoMethod*, num * 2);
6316 	for (i = 0; i < num; ++i) {
6317 		MonoMethod *method;
6318 
6319 		if (!mono_verifier_verify_methodimpl_row (image, start + i, &error)) {
6320 			mono_error_cleanup (&error); /* FIXME don't swallow the error */
6321 			ok = FALSE;
6322 			break;
6323 		}
6324 
6325 		mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
6326 		method = method_from_method_def_or_ref (
6327 			image, cols [MONO_METHODIMPL_DECLARATION], generic_context, &error);
6328 		if (method == NULL) {
6329 			mono_error_cleanup (&error); /* FIXME don't swallow the error */
6330 			ok = FALSE;
6331 		}
6332 		result [i * 2] = method;
6333 		method = method_from_method_def_or_ref (
6334 			image, cols [MONO_METHODIMPL_BODY], generic_context, &error);
6335 		if (method == NULL) {
6336 			mono_error_cleanup (&error); /* FIXME don't swallow the error */
6337 			ok = FALSE;
6338 		}
6339 		result [i * 2 + 1] = method;
6340 	}
6341 
6342 	*overrides = result;
6343 	if (num_overrides)
6344 		*num_overrides = num;
6345 	return ok;
6346 }
6347 
6348 /**
6349  * mono_guid_to_string:
6350  *
6351  * Converts a 16 byte Microsoft GUID to the standard string representation.
6352  */
6353 char *
mono_guid_to_string(const guint8 * guid)6354 mono_guid_to_string (const guint8 *guid)
6355 {
6356 	return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
6357 				guid[3], guid[2], guid[1], guid[0],
6358 				guid[5], guid[4],
6359 				guid[7], guid[6],
6360 				guid[8], guid[9],
6361 				guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
6362 }
6363 
6364 /**
6365  * mono_guid_to_string_minimal:
6366  *
6367  * Converts a 16 byte Microsoft GUID to lower case no '-' representation..
6368  */
6369 char *
mono_guid_to_string_minimal(const guint8 * guid)6370 mono_guid_to_string_minimal (const guint8 *guid)
6371 {
6372 	return g_strdup_printf ("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
6373 				guid[3], guid[2], guid[1], guid[0],
6374 				guid[5], guid[4],
6375 				guid[7], guid[6],
6376 				guid[8], guid[9],
6377 				guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
6378 }
6379 static gboolean
get_constraints(MonoImage * image,int owner,MonoClass *** constraints,MonoGenericContainer * container,MonoError * error)6380 get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container, MonoError *error)
6381 {
6382 	MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
6383 	guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
6384 	guint32 i, token, found;
6385 	MonoClass *klass, **res;
6386 	GSList *cons = NULL, *tmp;
6387 	MonoGenericContext *context = &container->context;
6388 
6389 	error_init (error);
6390 
6391 	*constraints = NULL;
6392 	found = 0;
6393 	for (i = 0; i < tdef->rows; ++i) {
6394 		mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
6395 		if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
6396 			token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
6397 			klass = mono_class_get_and_inflate_typespec_checked (image, token, context, error);
6398 			if (!klass) {
6399 				g_slist_free (cons);
6400 				return FALSE;
6401 			}
6402 			cons = g_slist_append (cons, klass);
6403 			++found;
6404 		} else {
6405 			/* contiguous list finished */
6406 			if (found)
6407 				break;
6408 		}
6409 	}
6410 	if (!found)
6411 		return TRUE;
6412 	res = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * (found + 1));
6413 	for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
6414 		res [i] = (MonoClass *)tmp->data;
6415 	}
6416 	g_slist_free (cons);
6417 	*constraints = res;
6418 	return TRUE;
6419 }
6420 
6421 /*
6422  * mono_metadata_get_generic_param_row:
6423  *
6424  * @image:
6425  * @token: TypeOrMethodDef token, owner for GenericParam
6426  * @owner: coded token, set on return
6427  *
6428  * Returns: 1-based row-id in the GenericParam table whose
6429  * owner is @token. 0 if not found.
6430  */
6431 guint32
mono_metadata_get_generic_param_row(MonoImage * image,guint32 token,guint32 * owner)6432 mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *owner)
6433 {
6434 	MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
6435 	locator_t loc;
6436 
6437 	g_assert (owner);
6438 	if (!tdef->base)
6439 		return 0;
6440 
6441 	if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
6442 		*owner = MONO_TYPEORMETHOD_TYPE;
6443 	else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
6444 		*owner = MONO_TYPEORMETHOD_METHOD;
6445 	else {
6446 		g_error ("wrong token %x to get_generic_param_row", token);
6447 		return 0;
6448 	}
6449 	*owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
6450 
6451 	loc.idx = *owner;
6452 	loc.col_idx = MONO_GENERICPARAM_OWNER;
6453 	loc.t = tdef;
6454 
6455 	if (!mono_binary_search (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
6456 		return 0;
6457 
6458 	/* Find the first entry by searching backwards */
6459 	while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_GENERICPARAM_OWNER) == loc.idx))
6460 		loc.result --;
6461 
6462 	return loc.result + 1;
6463 }
6464 
6465 gboolean
mono_metadata_has_generic_params(MonoImage * image,guint32 token)6466 mono_metadata_has_generic_params (MonoImage *image, guint32 token)
6467 {
6468 	guint32 owner;
6469 	return mono_metadata_get_generic_param_row (image, token, &owner);
6470 }
6471 
6472 /*
6473  * Memory is allocated from IMAGE's mempool.
6474  */
6475 gboolean
mono_metadata_load_generic_param_constraints_checked(MonoImage * image,guint32 token,MonoGenericContainer * container,MonoError * error)6476 mono_metadata_load_generic_param_constraints_checked (MonoImage *image, guint32 token,
6477 					      MonoGenericContainer *container, MonoError *error)
6478 {
6479 
6480 	guint32 start_row, i, owner;
6481 	error_init (error);
6482 
6483 	if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
6484 		return TRUE;
6485 	for (i = 0; i < container->type_argc; i++) {
6486 		if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container, error)) {
6487 			return FALSE;
6488 		}
6489 	}
6490 	return TRUE;
6491 }
6492 
6493 /*
6494  * mono_metadata_load_generic_params:
6495  *
6496  * Load the type parameters from the type or method definition @token.
6497  *
6498  * Use this method after parsing a type or method definition to figure out whether it's a generic
6499  * type / method.  When parsing a method definition, @parent_container points to the generic container
6500  * of the current class, if any.
6501  *
6502  * Note: This method does not load the constraints: for typedefs, this has to be done after fully
6503  *       creating the type.
6504  *
6505  * Returns: NULL if @token is not a generic type or method definition or the new generic container.
6506  *
6507  * LOCKING: Acquires the loader lock
6508  *
6509  */
6510 MonoGenericContainer *
mono_metadata_load_generic_params(MonoImage * image,guint32 token,MonoGenericContainer * parent_container)6511 mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
6512 {
6513 	MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
6514 	guint32 cols [MONO_GENERICPARAM_SIZE];
6515 	guint32 i, owner = 0, n;
6516 	MonoGenericContainer *container;
6517 	MonoGenericParamFull *params;
6518 	MonoGenericContext *context;
6519 
6520 	if (!(i = mono_metadata_get_generic_param_row (image, token, &owner)))
6521 		return NULL;
6522 	mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
6523 	params = NULL;
6524 	n = 0;
6525 	container = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
6526 	container->owner.image = image; // Temporarily mark as anonymous, but this will be overriden by caller
6527 	container->is_anonymous = TRUE;
6528 	do {
6529 		n++;
6530 		params = (MonoGenericParamFull *)g_realloc (params, sizeof (MonoGenericParamFull) * n);
6531 		memset (&params [n - 1], 0, sizeof (MonoGenericParamFull));
6532 		params [n - 1].param.owner = container;
6533 		params [n - 1].param.num = cols [MONO_GENERICPARAM_NUMBER];
6534 		params [n - 1].info.token = i | MONO_TOKEN_GENERIC_PARAM;
6535 		params [n - 1].info.flags = cols [MONO_GENERICPARAM_FLAGS];
6536 		params [n - 1].info.name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
6537 		if (params [n - 1].param.num != n - 1)
6538 			g_warning ("GenericParam table unsorted or hole in generic param sequence: token %d", i);
6539 		if (++i > tdef->rows)
6540 			break;
6541 		mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
6542 	} while (cols [MONO_GENERICPARAM_OWNER] == owner);
6543 
6544 	container->type_argc = n;
6545 	container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (image, sizeof (MonoGenericParamFull) * n);
6546 	memcpy (container->type_params, params, sizeof (MonoGenericParamFull) * n);
6547 	g_free (params);
6548 	container->parent = parent_container;
6549 
6550 	if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
6551 		container->is_method = 1;
6552 
6553 	g_assert (container->parent == NULL || container->is_method);
6554 
6555 	context = &container->context;
6556 	if (container->is_method) {
6557 		context->class_inst = container->parent ? container->parent->context.class_inst : NULL;
6558 		context->method_inst = mono_get_shared_generic_inst (container);
6559 	} else {
6560 		context->class_inst = mono_get_shared_generic_inst (container);
6561 	}
6562 
6563 	return container;
6564 }
6565 
6566 MonoGenericInst *
mono_get_shared_generic_inst(MonoGenericContainer * container)6567 mono_get_shared_generic_inst (MonoGenericContainer *container)
6568 {
6569 	MonoType **type_argv;
6570 	MonoType *helper;
6571 	MonoGenericInst *nginst;
6572 	int i;
6573 
6574 	type_argv = g_new0 (MonoType *, container->type_argc);
6575 	helper = g_new0 (MonoType, container->type_argc);
6576 
6577 	for (i = 0; i < container->type_argc; i++) {
6578 		MonoType *t = &helper [i];
6579 
6580 		t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6581 		t->data.generic_param = mono_generic_container_get_param (container, i);
6582 
6583 		type_argv [i] = t;
6584 	}
6585 
6586 	nginst = mono_metadata_get_generic_inst (container->type_argc, type_argv);
6587 
6588 	g_free (type_argv);
6589 	g_free (helper);
6590 
6591 	return nginst;
6592 }
6593 
6594 /**
6595  * mono_type_is_byref:
6596  * \param type the \c MonoType operated on
6597  * \returns TRUE if \p type represents a type passed by reference,
6598  * FALSE otherwise.
6599  */
6600 gboolean
mono_type_is_byref(MonoType * type)6601 mono_type_is_byref (MonoType *type)
6602 {
6603 	return type->byref;
6604 }
6605 
6606 /**
6607  * mono_type_get_type:
6608  * \param type the \c MonoType operated on
6609  * \returns the IL type value for \p type. This is one of the \c MonoTypeEnum
6610  * enum members like \c MONO_TYPE_I4 or \c MONO_TYPE_STRING.
6611  */
6612 int
mono_type_get_type(MonoType * type)6613 mono_type_get_type (MonoType *type)
6614 {
6615 	return type->type;
6616 }
6617 
6618 /**
6619  * mono_type_get_signature:
6620  * \param type the \c MonoType operated on
6621  * It is only valid to call this function if \p type is a \c MONO_TYPE_FNPTR .
6622  * \returns the \c MonoMethodSignature pointer that describes the signature
6623  * of the function pointer \p type represents.
6624  */
6625 MonoMethodSignature*
mono_type_get_signature(MonoType * type)6626 mono_type_get_signature (MonoType *type)
6627 {
6628 	g_assert (type->type == MONO_TYPE_FNPTR);
6629 	return type->data.method;
6630 }
6631 
6632 /**
6633  * mono_type_get_class:
6634  * \param type the \c MonoType operated on
6635  * It is only valid to call this function if \p type is a \c MONO_TYPE_CLASS or a
6636  * \c MONO_TYPE_VALUETYPE . For more general functionality, use \c mono_class_from_mono_type,
6637  * instead.
6638  * \returns the \c MonoClass pointer that describes the class that \p type represents.
6639  */
6640 MonoClass*
mono_type_get_class(MonoType * type)6641 mono_type_get_class (MonoType *type)
6642 {
6643 	/* FIXME: review the runtime users before adding the assert here */
6644 	return type->data.klass;
6645 }
6646 
6647 /**
6648  * mono_type_get_array_type:
6649  * \param type the \c MonoType operated on
6650  * It is only valid to call this function if \p type is a \c MONO_TYPE_ARRAY .
6651  * \returns a \c MonoArrayType struct describing the array type that \p type
6652  * represents. The info includes details such as rank, array element type
6653  * and the sizes and bounds of multidimensional arrays.
6654  */
6655 MonoArrayType*
mono_type_get_array_type(MonoType * type)6656 mono_type_get_array_type (MonoType *type)
6657 {
6658 	return type->data.array;
6659 }
6660 
6661 /**
6662  * mono_type_get_ptr_type:
6663  * \pararm type the \c MonoType operated on
6664  * It is only valid to call this function if \p type is a \c MONO_TYPE_PTR .
6665  * \returns the \c MonoType pointer that describes the type that \p type
6666  * represents a pointer to.
6667  */
6668 MonoType*
mono_type_get_ptr_type(MonoType * type)6669 mono_type_get_ptr_type (MonoType *type)
6670 {
6671 	g_assert (type->type == MONO_TYPE_PTR);
6672 	return type->data.type;
6673 }
6674 
6675 /**
6676  * mono_type_get_modifiers:
6677  */
6678 MonoClass*
mono_type_get_modifiers(MonoType * type,gboolean * is_required,gpointer * iter)6679 mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
6680 {
6681 	/* FIXME: implement */
6682 	return NULL;
6683 }
6684 
6685 /**
6686  * mono_type_is_struct:
6687  * \param type the \c MonoType operated on
6688  * \returns TRUE if \p type is a struct, that is a \c ValueType but not an enum
6689  * or a basic type like \c System.Int32 . FALSE otherwise.
6690  */
6691 mono_bool
mono_type_is_struct(MonoType * type)6692 mono_type_is_struct (MonoType *type)
6693 {
6694 	return (!type->byref && ((type->type == MONO_TYPE_VALUETYPE &&
6695 		!type->data.klass->enumtype) || (type->type == MONO_TYPE_TYPEDBYREF) ||
6696 		((type->type == MONO_TYPE_GENERICINST) &&
6697 		mono_metadata_generic_class_is_valuetype (type->data.generic_class) &&
6698 		!type->data.generic_class->container_class->enumtype)));
6699 }
6700 
6701 /**
6702  * mono_type_is_void:
6703  * \param type the \c MonoType operated on
6704  * \returns TRUE if \p type is \c System.Void . FALSE otherwise.
6705  */
6706 mono_bool
mono_type_is_void(MonoType * type)6707 mono_type_is_void (MonoType *type)
6708 {
6709 	return (type && (type->type == MONO_TYPE_VOID) && !type->byref);
6710 }
6711 
6712 /**
6713  * mono_type_is_pointer:
6714  * \param type the \c MonoType operated on
6715  * \returns TRUE if \p type is a managed or unmanaged pointer type. FALSE otherwise.
6716  */
6717 mono_bool
mono_type_is_pointer(MonoType * type)6718 mono_type_is_pointer (MonoType *type)
6719 {
6720 	return (type && ((type->byref || (type->type == MONO_TYPE_I) || type->type == MONO_TYPE_STRING)
6721 		|| (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
6722 		(type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_OBJECT) ||
6723 		(type->type == MONO_TYPE_ARRAY) || (type->type == MONO_TYPE_PTR) ||
6724 		(type->type == MONO_TYPE_FNPTR)));
6725 }
6726 
6727 /**
6728  * mono_type_is_reference:
6729  * \param type the \c MonoType operated on
6730  * \returns TRUE if \p type represents an object reference. FALSE otherwise.
6731  */
6732 mono_bool
mono_type_is_reference(MonoType * type)6733 mono_type_is_reference (MonoType *type)
6734 {
6735 	return (type && (((type->type == MONO_TYPE_STRING) ||
6736 		(type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) ||
6737 		(type->type == MONO_TYPE_OBJECT) || (type->type == MONO_TYPE_ARRAY)) ||
6738 		((type->type == MONO_TYPE_GENERICINST) &&
6739 		!mono_metadata_generic_class_is_valuetype (type->data.generic_class))));
6740 }
6741 
6742 mono_bool
mono_type_is_generic_parameter(MonoType * type)6743 mono_type_is_generic_parameter (MonoType *type)
6744 {
6745 	return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
6746 }
6747 
6748 /**
6749  * mono_signature_get_return_type:
6750  * \param sig the method signature inspected
6751  * \returns the return type of the method signature \p sig
6752  */
6753 MonoType*
mono_signature_get_return_type(MonoMethodSignature * sig)6754 mono_signature_get_return_type (MonoMethodSignature *sig)
6755 {
6756 	return sig->ret;
6757 }
6758 
6759 /**
6760  * mono_signature_get_params:
6761  * \param sig the method signature inspected
6762  * \param iter pointer to an iterator
6763  * Iterates over the parameters for the method signature \p sig.
6764  * A \c void* pointer must be initialized to NULL to start the iteration
6765  * and its address is passed to this function repeteadly until it returns
6766  * NULL.
6767  * \returns the next parameter type of the method signature \p sig,
6768  * NULL when finished.
6769  */
6770 MonoType*
mono_signature_get_params(MonoMethodSignature * sig,gpointer * iter)6771 mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
6772 {
6773 	MonoType** type;
6774 	if (!iter)
6775 		return NULL;
6776 	if (!*iter) {
6777 		/* start from the first */
6778 		if (sig->param_count) {
6779 			*iter = &sig->params [0];
6780 			return sig->params [0];
6781 		} else {
6782 			/* no method */
6783 			return NULL;
6784 		}
6785 	}
6786 	type = (MonoType **)*iter;
6787 	type++;
6788 	if (type < &sig->params [sig->param_count]) {
6789 		*iter = type;
6790 		return *type;
6791 	}
6792 	return NULL;
6793 }
6794 
6795 /**
6796  * mono_signature_get_param_count:
6797  * \param sig the method signature inspected
6798  * \returns the number of parameters in the method signature \p sig.
6799  */
6800 guint32
mono_signature_get_param_count(MonoMethodSignature * sig)6801 mono_signature_get_param_count (MonoMethodSignature *sig)
6802 {
6803 	return sig->param_count;
6804 }
6805 
6806 /**
6807  * mono_signature_get_call_conv:
6808  * \param sig the method signature inspected
6809  * \returns the call convention of the method signature \p sig.
6810  */
6811 guint32
mono_signature_get_call_conv(MonoMethodSignature * sig)6812 mono_signature_get_call_conv (MonoMethodSignature *sig)
6813 {
6814 	return sig->call_convention;
6815 }
6816 
6817 /**
6818  * mono_signature_vararg_start:
6819  * \param sig the method signature inspected
6820  * \returns the number of the first vararg parameter in the
6821  * method signature \param sig. \c -1 if this is not a vararg signature.
6822  */
6823 int
mono_signature_vararg_start(MonoMethodSignature * sig)6824 mono_signature_vararg_start (MonoMethodSignature *sig)
6825 {
6826 	return sig->sentinelpos;
6827 }
6828 
6829 /**
6830  * mono_signature_is_instance:
6831  * \param sig the method signature inspected
6832  * \returns TRUE if this the method signature \p sig has an implicit
6833  * first instance argument. FALSE otherwise.
6834  */
6835 gboolean
mono_signature_is_instance(MonoMethodSignature * sig)6836 mono_signature_is_instance (MonoMethodSignature *sig)
6837 {
6838 	return sig->hasthis;
6839 }
6840 
6841 /**
6842  * mono_signature_param_is_out
6843  * \param sig the method signature inspected
6844  * \param param_num the 0-based index of the inspected parameter
6845  * \returns TRUE if the parameter is an out parameter, FALSE
6846  * otherwise.
6847  */
6848 mono_bool
mono_signature_param_is_out(MonoMethodSignature * sig,int param_num)6849 mono_signature_param_is_out (MonoMethodSignature *sig, int param_num)
6850 {
6851 	g_assert (param_num >= 0 && param_num < sig->param_count);
6852 	return (sig->params [param_num]->attrs & PARAM_ATTRIBUTE_OUT) != 0;
6853 }
6854 
6855 /**
6856  * mono_signature_explicit_this:
6857  * \param sig the method signature inspected
6858  * \returns TRUE if this the method signature \p sig has an explicit
6859  * instance argument. FALSE otherwise.
6860  */
6861 gboolean
mono_signature_explicit_this(MonoMethodSignature * sig)6862 mono_signature_explicit_this (MonoMethodSignature *sig)
6863 {
6864 	return sig->explicit_this;
6865 }
6866 
6867 /* for use with allocated memory blocks (assumes alignment is to 8 bytes) */
6868 guint
mono_aligned_addr_hash(gconstpointer ptr)6869 mono_aligned_addr_hash (gconstpointer ptr)
6870 {
6871 	/* Same hashing we use for objects */
6872 	return (GPOINTER_TO_UINT (ptr) >> 3) * 2654435761u;
6873 }
6874 
6875 /*
6876  * If @field belongs to an inflated generic class, return the corresponding field of the
6877  * generic type definition class.
6878  */
6879 MonoClassField*
mono_metadata_get_corresponding_field_from_generic_type_definition(MonoClassField * field)6880 mono_metadata_get_corresponding_field_from_generic_type_definition (MonoClassField *field)
6881 {
6882 	MonoClass *gtd;
6883 	int offset;
6884 
6885 	if (!mono_class_is_ginst (field->parent))
6886 		return field;
6887 
6888 	gtd = mono_class_get_generic_class (field->parent)->container_class;
6889 	offset = field - field->parent->fields;
6890 	return gtd->fields + offset;
6891 }
6892 
6893 /*
6894  * If @event belongs to an inflated generic class, return the corresponding event of the
6895  * generic type definition class.
6896  */
6897 MonoEvent*
mono_metadata_get_corresponding_event_from_generic_type_definition(MonoEvent * event)6898 mono_metadata_get_corresponding_event_from_generic_type_definition (MonoEvent *event)
6899 {
6900 	MonoClass *gtd;
6901 	int offset;
6902 
6903 	if (!mono_class_is_ginst (event->parent))
6904 		return event;
6905 
6906 	gtd = mono_class_get_generic_class (event->parent)->container_class;
6907 	offset = event - mono_class_get_event_info (event->parent)->events;
6908 	return mono_class_get_event_info (gtd)->events + offset;
6909 }
6910 
6911 /*
6912  * If @property belongs to an inflated generic class, return the corresponding property of the
6913  * generic type definition class.
6914  */
6915 MonoProperty*
mono_metadata_get_corresponding_property_from_generic_type_definition(MonoProperty * property)6916 mono_metadata_get_corresponding_property_from_generic_type_definition (MonoProperty *property)
6917 {
6918 	MonoClassPropertyInfo *info;
6919 	MonoClass *gtd;
6920 	int offset;
6921 
6922 	if (!mono_class_is_ginst (property->parent))
6923 		return property;
6924 
6925 	info = mono_class_get_property_info (property->parent);
6926 	gtd = mono_class_get_generic_class (property->parent)->container_class;
6927 	offset = property - info->properties;
6928 	return mono_class_get_property_info (gtd)->properties + offset;
6929 }
6930 
6931 MonoWrapperCaches*
mono_method_get_wrapper_cache(MonoMethod * method)6932 mono_method_get_wrapper_cache (MonoMethod *method)
6933 {
6934 	if (method->is_inflated) {
6935 		MonoMethodInflated *imethod = (MonoMethodInflated *)method;
6936 		return &imethod->owner->wrapper_caches;
6937 	} else {
6938 		return &method->klass->image->wrapper_caches;
6939 	}
6940 }
6941 
6942 // This is support for the mempool reference tracking feature in checked-build, but lives in metadata.c due to use of static variables of this file.
6943 
6944 /**
6945  * mono_find_image_set_owner:
6946  *
6947  * Find the imageset, if any, which a given pointer is located in the memory of.
6948  */
6949 MonoImageSet *
mono_find_image_set_owner(void * ptr)6950 mono_find_image_set_owner (void *ptr)
6951 {
6952 	MonoImageSet *owner = NULL;
6953 	int i;
6954 
6955 	image_sets_lock ();
6956 
6957 	if (image_sets)
6958 	{
6959 		for (i = 0; !owner && i < image_sets->len; ++i) {
6960 			MonoImageSet *set = (MonoImageSet *)g_ptr_array_index (image_sets, i);
6961 			if (mono_mempool_contains_addr (set->mempool, ptr))
6962 				owner = set;
6963 		}
6964 	}
6965 
6966 	image_sets_unlock ();
6967 
6968 	return owner;
6969 }
6970 
6971 void
mono_loader_set_strict_strong_names(gboolean enabled)6972 mono_loader_set_strict_strong_names (gboolean enabled)
6973 {
6974 	check_strong_names_strictly = enabled;
6975 }
6976 
6977 gboolean
mono_loader_get_strict_strong_names(void)6978 mono_loader_get_strict_strong_names (void)
6979 {
6980 	return check_strong_names_strictly;
6981 }
6982