[runtime] Call error_init instead of mono_error_init (#4425)
[mono.git] / mono / metadata / dynamic-image.c
1 /*
2  * dynamic-image.c: Images created at runtime.
3  *   
4  * 
5  * Author:
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10  * Copyright 2011 Rodrigo Kumpera
11  * Copyright 2016 Microsoft
12  *
13  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
14  */
15
16 #include <config.h>
17 #include <glib.h>
18 #include "mono/metadata/object.h"
19 #include "mono/metadata/dynamic-image-internals.h"
20 #include "mono/metadata/dynamic-stream-internals.h"
21 #include "mono/metadata/gc-internals.h"
22 #include "mono/metadata/metadata-internals.h"
23 #include "mono/metadata/profiler-private.h"
24 #include "mono/metadata/reflection-internals.h"
25 #include "mono/metadata/sre-internals.h"
26 #include "mono/utils/checked-build.h"
27 #include "mono/utils/mono-error-internals.h"
28 #include "mono/utils/mono-os-mutex.h"
29
30 const unsigned char table_sizes [MONO_TABLE_NUM] = {
31         MONO_MODULE_SIZE,
32         MONO_TYPEREF_SIZE,
33         MONO_TYPEDEF_SIZE,
34         0,
35         MONO_FIELD_SIZE,
36         0,
37         MONO_METHOD_SIZE,
38         0,
39         MONO_PARAM_SIZE,
40         MONO_INTERFACEIMPL_SIZE,
41         MONO_MEMBERREF_SIZE,    /* 0x0A */
42         MONO_CONSTANT_SIZE,
43         MONO_CUSTOM_ATTR_SIZE,
44         MONO_FIELD_MARSHAL_SIZE,
45         MONO_DECL_SECURITY_SIZE,
46         MONO_CLASS_LAYOUT_SIZE,
47         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
48         MONO_STAND_ALONE_SIGNATURE_SIZE,
49         MONO_EVENT_MAP_SIZE,
50         0,
51         MONO_EVENT_SIZE,
52         MONO_PROPERTY_MAP_SIZE,
53         0,
54         MONO_PROPERTY_SIZE,
55         MONO_METHOD_SEMA_SIZE,
56         MONO_METHODIMPL_SIZE,
57         MONO_MODULEREF_SIZE,    /* 0x1A */
58         MONO_TYPESPEC_SIZE,
59         MONO_IMPLMAP_SIZE,      
60         MONO_FIELD_RVA_SIZE,
61         0,
62         0,
63         MONO_ASSEMBLY_SIZE,     /* 0x20 */
64         MONO_ASSEMBLY_PROCESSOR_SIZE,
65         MONO_ASSEMBLYOS_SIZE,
66         MONO_ASSEMBLYREF_SIZE,
67         MONO_ASSEMBLYREFPROC_SIZE,
68         MONO_ASSEMBLYREFOS_SIZE,
69         MONO_FILE_SIZE,
70         MONO_EXP_TYPE_SIZE,
71         MONO_MANIFEST_SIZE,
72         MONO_NESTED_CLASS_SIZE,
73
74         MONO_GENERICPARAM_SIZE, /* 0x2A */
75         MONO_METHODSPEC_SIZE,
76         MONO_GENPARCONSTRAINT_SIZE
77
78 };
79
80 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
81 static GPtrArray *dynamic_images;
82 static mono_mutex_t dynamic_images_mutex;
83
84 static inline void
85 dynamic_images_lock (void)
86 {
87         mono_os_mutex_lock (&dynamic_images_mutex);
88 }
89
90 static inline void
91 dynamic_images_unlock (void)
92 {
93         mono_os_mutex_unlock (&dynamic_images_mutex);
94 }
95
96 void
97 mono_dynamic_images_init (void)
98 {
99         mono_os_mutex_init (&dynamic_images_mutex);
100 }
101
102 #ifndef DISABLE_REFLECTION_EMIT
103 static void
104 string_heap_init (MonoDynamicStream *sh)
105 {
106         mono_dynstream_init (sh);
107 }
108 #endif
109
110 #ifndef DISABLE_REFLECTION_EMIT
111 static int
112 mono_blob_entry_hash (const char* str)
113 {
114         MONO_REQ_GC_NEUTRAL_MODE;
115
116         guint len, h;
117         const char *end;
118         len = mono_metadata_decode_blob_size (str, &str);
119         if (len > 0) {
120                 end = str + len;
121                 h = *str;
122                 for (str += 1; str < end; str++)
123                         h = (h << 5) - h + *str;
124                 return h;
125         } else {
126                 return 0;
127         }
128 }
129
130 static gboolean
131 mono_blob_entry_equal (const char *str1, const char *str2) {
132         MONO_REQ_GC_NEUTRAL_MODE;
133
134         int len, len2;
135         const char *end1;
136         const char *end2;
137         len = mono_metadata_decode_blob_size (str1, &end1);
138         len2 = mono_metadata_decode_blob_size (str2, &end2);
139         if (len != len2)
140                 return 0;
141         return memcmp (end1, end2, len) == 0;
142 }
143 #endif
144
145
146 /**
147  * mono_find_dynamic_image_owner:
148  *
149  * Find the dynamic image, if any, which a given pointer is located in the memory of.
150  */
151 MonoImage *
152 mono_find_dynamic_image_owner (void *ptr)
153 {
154         MonoImage *owner = NULL;
155         int i;
156
157         dynamic_images_lock ();
158
159         if (dynamic_images)
160         {
161                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
162                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
163                         if (mono_mempool_contains_addr (image->mempool, ptr))
164                                 owner = image;
165                 }
166         }
167
168         dynamic_images_unlock ();
169
170         return owner;
171 }
172
173 static inline void
174 dynamic_image_lock (MonoDynamicImage *image)
175 {
176         MONO_ENTER_GC_SAFE;
177         mono_image_lock ((MonoImage*)image);
178         MONO_EXIT_GC_SAFE;
179 }
180
181 static inline void
182 dynamic_image_unlock (MonoDynamicImage *image)
183 {
184         mono_image_unlock ((MonoImage*)image);
185 }
186
187 #ifndef DISABLE_REFLECTION_INIT
188 /*
189  * mono_dynamic_image_register_token:
190  *
191  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
192  * the Module.ResolveXXXToken () methods to work.
193  */
194 void
195 mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObjectHandle obj)
196 {
197         MONO_REQ_GC_UNSAFE_MODE;
198
199         dynamic_image_lock (assembly);
200         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), MONO_HANDLE_RAW (obj));
201         dynamic_image_unlock (assembly);
202 }
203 #else
204 void
205 mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObjectHandle obj)
206 {
207 }
208 #endif
209
210 static MonoObject*
211 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
212 {
213         MONO_REQ_GC_UNSAFE_MODE;
214
215         MonoObject *obj;
216
217         dynamic_image_lock (assembly);
218         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
219         dynamic_image_unlock (assembly);
220
221         return obj;
222 }
223
224 /**
225  * 
226  * mono_dynamic_image_is_valid_token:
227  * 
228  * Returns TRUE if token is valid in the given image.
229  * 
230  */
231 gboolean
232 mono_dynamic_image_is_valid_token (MonoDynamicImage *image, guint32 token)
233 {
234         return lookup_dyn_token (image, token) != NULL;
235 }
236
237 #ifndef DISABLE_REFLECTION_EMIT
238
239 #endif /* DISABLE_REFLECTION_EMIT */
240
241 #ifndef DISABLE_REFLECTION_EMIT
242 /**
243  * mono_reflection_lookup_dynamic_token:
244  *
245  * Finish the Builder object pointed to by TOKEN and return the corresponding
246  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
247  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
248  * mapping table.
249  *
250  * LOCKING: Take the loader lock
251  */
252 gpointer
253 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
254 {
255         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
256         MonoObject *obj;
257         MonoClass *klass;
258
259         error_init (error);
260         
261         obj = lookup_dyn_token (assembly, token);
262         if (!obj) {
263                 if (valid_token)
264                         g_error ("Could not find required dynamic token 0x%08x", token);
265                 else {
266                         mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
267                         return NULL;
268                 }
269         }
270
271         if (!handle_class)
272                 handle_class = &klass;
273         gpointer result = mono_reflection_resolve_object (image, obj, handle_class, context, error);
274         return result;
275 }
276 #else /* DISABLE_REFLECTION_EMIT */
277 gpointer
278 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
279 {
280         error_init (error);
281         return NULL;
282 }
283 #endif /* DISABLE_REFLECTION_EMIT */
284
285 #ifndef DISABLE_REFLECTION_EMIT
286 MonoDynamicImage*
287 mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
288 {
289         static const guchar entrycode [16] = {0xff, 0x25, 0};
290         MonoDynamicImage *image;
291         int i;
292
293         const char *version;
294
295         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
296                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
297         else
298                 version = mono_get_runtime_info ()->runtime_version;
299
300 #if HAVE_BOEHM_GC
301         /* The MonoGHashTable's need GC tracking */
302         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
303 #else
304         image = g_new0 (MonoDynamicImage, 1);
305 #endif
306
307         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
308         
309         /*g_print ("created image %p\n", image);*/
310         /* keep in sync with image.c */
311         image->image.name = assembly_name;
312         image->image.assembly_name = image->image.name; /* they may be different */
313         image->image.module_name = module_name;
314         image->image.version = g_strdup (version);
315         image->image.md_version_major = 1;
316         image->image.md_version_minor = 1;
317         image->image.dynamic = TRUE;
318
319         image->image.references = g_new0 (MonoAssembly*, 1);
320         image->image.references [0] = NULL;
321
322         mono_image_init (&image->image);
323
324         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
325         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
326         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
327         image->method_aux_hash = g_hash_table_new (NULL, NULL);
328         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
329         image->handleref = g_hash_table_new (NULL, NULL);
330         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
331         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
332         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
333         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
334         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
335         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
336         image->gen_params = g_ptr_array_new ();
337         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
338
339         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
340         string_heap_init (&image->sheap);
341         mono_dynstream_add_data (&image->us, "", 1);
342         mono_dynamic_image_add_to_blob_cached (image, (char*) "", 1, NULL, 0);
343         /* import tables... */
344         mono_dynstream_add_data (&image->code, (char*)entrycode, sizeof (entrycode));
345         image->iat_offset = mono_dynstream_add_zero (&image->code, 8); /* two IAT entries */
346         image->idt_offset = mono_dynstream_add_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
347         image->imp_names_offset = mono_dynstream_add_zero (&image->code, 2); /* flags for name entry */
348         mono_dynstream_add_data (&image->code, "_CorExeMain", 12);
349         mono_dynstream_add_data (&image->code, "mscoree.dll", 12);
350         image->ilt_offset = mono_dynstream_add_zero (&image->code, 8); /* two ILT entries */
351         mono_dynstream_data_align (&image->code);
352
353         image->cli_header_offset = mono_dynstream_add_zero (&image->code, sizeof (MonoCLIHeader));
354
355         for (i=0; i < MONO_TABLE_NUM; ++i) {
356                 image->tables [i].next_idx = 1;
357                 image->tables [i].columns = table_sizes [i];
358         }
359
360         image->image.assembly = (MonoAssembly*)assembly;
361         image->run = assembly->run;
362         image->save = assembly->save;
363         image->pe_kind = 0x1; /* ILOnly */
364         image->machine = 0x14c; /* I386 */
365         
366         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
367
368         dynamic_images_lock ();
369
370         if (!dynamic_images)
371                 dynamic_images = g_ptr_array_new ();
372
373         g_ptr_array_add (dynamic_images, image);
374
375         dynamic_images_unlock ();
376
377         return image;
378 }
379 #else /* DISABLE_REFLECTION_EMIT */
380 MonoDynamicImage*
381 mono_dynamic_image_create (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
382 {
383         g_assert_not_reached ();
384         return NULL;
385 }
386 #endif /* DISABLE_REFLECTION_EMIT */
387
388 guint32
389 mono_dynamic_image_add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
390 {
391         MONO_REQ_GC_NEUTRAL_MODE;
392
393         guint32 idx;
394         char *copy;
395         gpointer oldkey, oldval;
396
397         copy = (char *)g_malloc (s1+s2);
398         memcpy (copy, b1, s1);
399         memcpy (copy + s1, b2, s2);
400         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
401                 g_free (copy);
402                 idx = GPOINTER_TO_UINT (oldval);
403         } else {
404                 idx = mono_dynstream_add_data (&assembly->blob, b1, s1);
405                 mono_dynstream_add_data (&assembly->blob, b2, s2);
406                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
407         }
408         return idx;
409 }
410
411 void
412 mono_dynimage_alloc_table (MonoDynamicTable *table, guint nrows)
413 {
414         MONO_REQ_GC_NEUTRAL_MODE;
415
416         table->rows = nrows;
417         g_assert (table->columns);
418         if (nrows + 1 >= table->alloc_rows) {
419                 while (nrows + 1 >= table->alloc_rows) {
420                         if (table->alloc_rows == 0)
421                                 table->alloc_rows = 16;
422                         else
423                                 table->alloc_rows *= 2;
424                 }
425
426                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
427         }
428 }
429
430
431 static void
432 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
433 {
434         g_free (key);
435 }
436
437 static void
438 release_hashtable (MonoGHashTable **hash)
439 {
440         if (*hash) {
441                 mono_g_hash_table_destroy (*hash);
442                 *hash = NULL;
443         }
444 }
445
446 void
447 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
448 {
449         release_hashtable (&image->token_fixups);
450         release_hashtable (&image->handleref_managed);
451         release_hashtable (&image->tokens);
452         release_hashtable (&image->remapped_tokens);
453         release_hashtable (&image->generic_def_objects);
454 }
455
456 // Free dynamic image pass one: Free resources but not image itself
457 void
458 mono_dynamic_image_free (MonoDynamicImage *image)
459 {
460         MonoDynamicImage *di = image;
461         GList *list;
462         int i;
463
464         if (di->typespec)
465                 g_hash_table_destroy (di->typespec);
466         if (di->typeref)
467                 g_hash_table_destroy (di->typeref);
468         if (di->handleref)
469                 g_hash_table_destroy (di->handleref);
470         if (di->handleref_managed)
471                 mono_g_hash_table_destroy (di->handleref_managed);
472         if (di->tokens)
473                 mono_g_hash_table_destroy (di->tokens);
474         if (di->remapped_tokens)
475                 mono_g_hash_table_destroy (di->remapped_tokens);
476         if (di->generic_def_objects)
477                 mono_g_hash_table_destroy (di->generic_def_objects);
478         if (di->blob_cache) {
479                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
480                 g_hash_table_destroy (di->blob_cache);
481         }
482         if (di->standalonesig_cache)
483                 g_hash_table_destroy (di->standalonesig_cache);
484         for (list = di->array_methods; list; list = list->next) {
485                 ArrayMethod *am = (ArrayMethod *)list->data;
486                 mono_sre_array_method_free (am);
487         }
488         g_list_free (di->array_methods);
489         if (di->gen_params) {
490                 for (i = 0; i < di->gen_params->len; i++) {
491                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
492                         mono_sre_generic_param_table_entry_free (entry);
493                 }
494                 g_ptr_array_free (di->gen_params, TRUE);
495         }
496         if (di->token_fixups)
497                 mono_g_hash_table_destroy (di->token_fixups);
498         if (di->method_to_table_idx)
499                 g_hash_table_destroy (di->method_to_table_idx);
500         if (di->field_to_table_idx)
501                 g_hash_table_destroy (di->field_to_table_idx);
502         if (di->method_aux_hash)
503                 g_hash_table_destroy (di->method_aux_hash);
504         if (di->vararg_aux_hash)
505                 g_hash_table_destroy (di->vararg_aux_hash);
506         g_free (di->strong_name);
507         g_free (di->win32_res);
508         if (di->public_key)
509                 g_free (di->public_key);
510
511         /*g_print ("string heap destroy for image %p\n", di);*/
512         mono_dynamic_stream_reset (&di->sheap);
513         mono_dynamic_stream_reset (&di->code);
514         mono_dynamic_stream_reset (&di->resources);
515         mono_dynamic_stream_reset (&di->us);
516         mono_dynamic_stream_reset (&di->blob);
517         mono_dynamic_stream_reset (&di->tstream);
518         mono_dynamic_stream_reset (&di->guid);
519         for (i = 0; i < MONO_TABLE_NUM; ++i) {
520                 g_free (di->tables [i].values);
521         }
522
523         dynamic_images_lock ();
524
525         if (dynamic_images)
526                 g_ptr_array_remove (dynamic_images, di);
527
528         dynamic_images_unlock ();
529 }
530
531 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
532 void
533 mono_dynamic_image_free_image (MonoDynamicImage *image)
534 {
535         /* See create_dynamic_mono_image () */
536 #if HAVE_BOEHM_GC
537         /* Allocated using GC_MALLOC */
538 #else
539         g_free (image);
540 #endif
541 }