Switch to compiler-tester
[mono.git] / mono / metadata / domain.c
1
2 /*
3  * domain.c: MonoDomain functions
4  *
5  * Author:
6  *      Dietmar Maurer (dietmar@ximian.com)
7  *      Patrik Torstensson
8  *
9  * (C) 2001 Ximian, Inc.
10  */
11
12 #include <config.h>
13 #include <glib.h>
14 #include <string.h>
15 #include <sys/stat.h>
16
17 #include <mono/os/gc_wrapper.h>
18
19 #include <mono/utils/mono-compiler.h>
20 #include <mono/metadata/object.h>
21 #include <mono/metadata/object-internals.h>
22 #include <mono/metadata/domain-internals.h>
23 #include <mono/metadata/class-internals.h>
24 #include <mono/metadata/assembly.h>
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/cil-coff.h>
27 #include <mono/metadata/rawbuffer.h>
28 #include <mono/metadata/metadata-internals.h>
29 #include <mono/metadata/gc-internal.h>
30 #include <mono/metadata/mono-debug-debugger.h>
31 #include <mono/metadata/appdomain.h>
32 #include <metadata/threads.h>
33
34 /* #define DEBUG_DOMAIN_UNLOAD */
35
36 /* we need to use both the Tls* functions and __thread because
37  * some archs may generate faster jit code with one meachanism
38  * or the other (we used to do it because tls slots were GC-tracked,
39  * but we can't depend on this).
40  */
41 static guint32 appdomain_thread_id = -1;
42  
43 #ifdef HAVE_KW_THREAD
44 static __thread MonoDomain * tls_appdomain MONO_TLS_FAST;
45 #define GET_APPDOMAIN() tls_appdomain
46 #define SET_APPDOMAIN(x) do { \
47         tls_appdomain = x; \
48         TlsSetValue (appdomain_thread_id, x); \
49 } while (FALSE)
50
51 #else
52
53 #define GET_APPDOMAIN() ((MonoDomain *)TlsGetValue (appdomain_thread_id))
54 #define SET_APPDOMAIN(x) TlsSetValue (appdomain_thread_id, x);
55
56 #endif
57
58 #define GET_APPCONTEXT() (mono_thread_current ()->current_appcontext)
59 #define SET_APPCONTEXT(x) mono_thread_current ()->current_appcontext = (x)
60
61 static guint16 appdomain_list_size = 0;
62 static guint16 appdomain_next = 0;
63 static MonoDomain **appdomains_list = NULL;
64
65 static CRITICAL_SECTION appdomains_mutex;
66
67 static MonoDomain *mono_root_domain = NULL;
68
69 /* AppConfigInfo: Information about runtime versions supported by an 
70  * aplication.
71  */
72 typedef struct {
73         GSList *supported_runtimes;
74         char *required_runtime;
75         int configuration_count;
76         int startup_count;
77 } AppConfigInfo;
78
79 static const MonoRuntimeInfo *current_runtime = NULL;
80
81 /* This is the list of runtime versions supported by this JIT.
82  */
83 static const MonoRuntimeInfo supported_runtimes[] = {
84         {"v1.0.3705", "1.0", { {1,0,5000,0}, {7,0,5000,0} }     },
85         {"v1.1.4322", "1.0", { {1,0,5000,0}, {7,0,5000,0} }     },
86         {"v2.0.50215","2.0", { {2,0,3600,0}, {8,0,3600,0} }     }
87 };
88
89
90 /* The stable runtime version */
91 #define DEFAULT_RUNTIME_VERSION "v1.1.4322"
92
93 static void
94 get_runtimes_from_exe (const char *exe_file, const MonoRuntimeInfo** runtimes);
95
96 static const MonoRuntimeInfo*
97 get_runtime_by_version (const char *version);
98
99 guint32
100 mono_domain_get_tls_key (void)
101 {
102         return appdomain_thread_id;
103 }
104
105 gint32
106 mono_domain_get_tls_offset (void)
107 {
108         int offset = -1;
109         MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
110 /*      __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:" 
111                 : "=r" (offset));*/
112         return offset;
113 }
114
115 static MonoJitInfoTable *
116 mono_jit_info_table_new (void)
117 {
118         return g_array_new (FALSE, FALSE, sizeof (gpointer));
119 }
120
121 static void
122 mono_jit_info_table_free (MonoJitInfoTable *table)
123 {
124         g_array_free (table, TRUE);
125 }
126
127 static int
128 mono_jit_info_table_index (MonoJitInfoTable *table, char *addr)
129 {
130         int left = 0, right = table->len;
131
132         while (left < right) {
133                 int pos = (left + right) / 2;
134                 MonoJitInfo *ji = g_array_index (table, gpointer, pos);
135                 char *start = ji->code_start;
136                 char *end = start + ji->code_size;
137
138                 if (addr < start)
139                         right = pos;
140                 else if (addr >= end) 
141                         left = pos + 1;
142                 else
143                         return pos;
144         }
145
146         return left;
147 }
148
149 MonoJitInfo *
150 mono_jit_info_table_find (MonoDomain *domain, char *addr)
151 {
152         MonoJitInfoTable *table = domain->jit_info_table;
153         guint left = 0, right;
154
155         mono_domain_lock (domain);
156
157         right = table->len;
158         while (left < right) {
159                 guint pos = (left + right) / 2;
160                 MonoJitInfo *ji = g_array_index (table, gpointer, pos);
161
162                 if (addr < (char*)ji->code_start)
163                         right = pos;
164                 else if (addr >= (char*)ji->code_start + ji->code_size) 
165                         left = pos + 1;
166                 else {
167                         mono_domain_unlock (domain);
168                         return ji;
169                 }
170         }
171         mono_domain_unlock (domain);
172
173         /* maybe it is shared code, so we also search in the root domain */
174         if (domain != mono_root_domain)
175                 return mono_jit_info_table_find (mono_root_domain, addr);
176
177         return NULL;
178 }
179
180 void
181 mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
182 {
183         MonoJitInfoTable *table = domain->jit_info_table;
184         gpointer start = ji->code_start;
185         int pos;
186
187         mono_domain_lock (domain);
188         pos = mono_jit_info_table_index (table, start);
189
190         g_array_insert_val (table, pos, ji);
191         mono_domain_unlock (domain);
192 }
193
194 void
195 mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
196 {
197         MonoJitInfoTable *table = domain->jit_info_table;
198         gpointer start = ji->code_start;
199         int pos;
200
201         mono_domain_lock (domain);
202         pos = mono_jit_info_table_index (table, start);
203         g_assert (g_array_index (table, gpointer, pos) == ji);
204
205         g_array_remove_index (table, pos);
206         mono_domain_unlock (domain);
207 }       
208
209 gboolean
210 mono_string_equal (MonoString *s1, MonoString *s2)
211 {
212         int l1 = mono_string_length (s1);
213         int l2 = mono_string_length (s2);
214
215         if (s1 == s2)
216                 return TRUE;
217         if (l1 != l2)
218                 return FALSE;
219
220         return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0; 
221 }
222
223 guint
224 mono_string_hash (MonoString *s)
225 {
226         const guint16 *p = mono_string_chars (s);
227         int i, len = mono_string_length (s);
228         guint h = 0;
229
230         for (i = 0; i < len; i++) {
231                 h = (h << 5) - h + *p;
232                 p++;
233         }
234
235         return h;       
236 }
237
238 gboolean
239 mono_ptrarray_equal (gpointer *s1, gpointer *s2)
240 {
241         int len = GPOINTER_TO_INT (s1 [0]);
242         if (len != GPOINTER_TO_INT (s2 [0]))
243                 return FALSE;
244
245         return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0; 
246 }
247
248 guint
249 mono_ptrarray_hash (gpointer *s)
250 {
251         int i;
252         int len = GPOINTER_TO_INT (s [0]);
253         guint hash = 0;
254         
255         for (i = 1; i < len; i++)
256                 hash += GPOINTER_TO_UINT (s [i]);
257
258         return hash;    
259 }
260
261 /*
262  * Allocate an id for domain and set domain->domain_id.
263  * LOCKING: must be called while holding appdomains_mutex.
264  * We try to assign low numbers to the domain, so it can be used
265  * as an index in data tables to lookup domain-specific info
266  * with minimal memory overhead. We also try not to reuse the
267  * same id too quickly (to help debugging).
268  */
269 static int
270 domain_id_alloc (MonoDomain *domain)
271 {
272         int id = -1, i;
273         if (!appdomains_list) {
274                 appdomain_list_size = 2;
275                 appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
276         }
277         for (i = appdomain_next; i < appdomain_list_size; ++i) {
278                 if (!appdomains_list [i]) {
279                         id = i;
280                         break;
281                 }
282         }
283         if (id == -1) {
284                 for (i = 0; i < appdomain_next; ++i) {
285                         if (!appdomains_list [i]) {
286                                 id = i;
287                                 break;
288                         }
289                 }
290         }
291         if (id == -1) {
292                 MonoDomain **new_list;
293                 int new_size = appdomain_list_size * 2;
294                 if (new_size >= (1 << 16))
295                         g_assert_not_reached ();
296                 id = appdomain_list_size;
297                 new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
298                 memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
299                 mono_gc_free_fixed (appdomains_list);
300                 appdomains_list = new_list;
301                 appdomain_list_size = new_size;
302         }
303         domain->domain_id = id;
304         appdomains_list [id] = domain;
305         appdomain_next++;
306         if (appdomain_next > appdomain_list_size)
307                 appdomain_next = 0;
308         return id;
309 }
310
311 MonoDomain *
312 mono_domain_create (void)
313 {
314         MonoDomain *domain;
315
316         domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL);
317         domain->domain = NULL;
318         domain->setup = NULL;
319         domain->friendly_name = NULL;
320         domain->search_path = NULL;
321
322         domain->mp = mono_mempool_new ();
323         domain->code_mp = mono_code_manager_new ();
324         domain->env = mono_g_hash_table_new ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal);
325         domain->domain_assemblies = NULL;
326         domain->class_vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
327         domain->proxy_vtable_hash = mono_g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
328         domain->static_data_hash = mono_g_hash_table_new (mono_aligned_addr_hash, NULL);
329         domain->jit_code_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
330         domain->ldstr_table = mono_g_hash_table_new ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal);
331         domain->jit_info_table = mono_jit_info_table_new ();
332         domain->class_init_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
333         domain->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
334         domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
335         domain->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
336
337         InitializeCriticalSection (&domain->lock);
338
339         EnterCriticalSection (&appdomains_mutex);
340         domain_id_alloc (domain);
341         LeaveCriticalSection (&appdomains_mutex);
342
343         return domain;
344 }
345
346 /**
347  * mono_init_internal:
348  * 
349  * Creates the initial application domain and initializes the mono_defaults
350  * structure.
351  * This function is guaranteed to not run any IL code.
352  * If exe_filename is not NULL, the method will determine the required runtime
353  * from the exe configuration file or the version PE field.
354  * If runtime_version is not NULL, that runtime version will be used.
355  * Either exe_filename or runtime_version must be provided.
356  *
357  * Returns: the initial domain.
358  */
359 static MonoDomain *
360 mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
361 {
362         static MonoDomain *domain = NULL;
363         MonoAssembly *ass = NULL;
364         MonoImageOpenStatus status = MONO_IMAGE_OK;
365         const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
366         int n;
367
368         if (domain)
369                 g_assert_not_reached ();
370
371         MONO_GC_PRE_INIT ();
372
373         appdomain_thread_id = TlsAlloc ();
374
375         InitializeCriticalSection (&appdomains_mutex);
376
377         mono_metadata_init ();
378         mono_raw_buffer_init ();
379         mono_images_init ();
380         mono_assemblies_init ();
381         mono_loader_init ();
382
383         /* FIXME: When should we release this memory? */
384         MONO_GC_REGISTER_ROOT (appdomains_list);
385
386         domain = mono_domain_create ();
387         mono_root_domain = domain;
388
389         SET_APPDOMAIN (domain);
390         
391         /* Get a list of runtimes supported by the exe */
392         if (exe_filename != NULL) {
393                 get_runtimes_from_exe (exe_filename, runtimes);
394         } else if (runtime_version != NULL) {
395                 runtimes [0] = get_runtime_by_version (runtime_version);
396                 runtimes [1] = NULL;
397         }
398
399         if (runtimes [0] == NULL) {
400                 const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
401                 runtimes [0] = default_runtime;
402                 runtimes [1] = NULL;
403                 g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
404                 g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
405         }
406
407         /* The selected runtime will be the first one for which there is a mscrolib.dll */
408         for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
409                 current_runtime = runtimes [n];
410                 ass = mono_assembly_load_corlib (current_runtime, &status);
411                 if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
412                         break;
413         }
414
415         if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
416                 switch (status){
417                 case MONO_IMAGE_ERROR_ERRNO: {
418                         char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
419                         g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
420                         g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
421                         g_free (corlib_file);
422                         break;
423                 }
424                 case MONO_IMAGE_IMAGE_INVALID:
425                         g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
426                                  mono_assembly_getrootdir ());
427                         break;
428                 case MONO_IMAGE_MISSING_ASSEMBLYREF:
429                         g_print ("Missing assembly reference in %s/mscorlib.dll\n",
430                                  mono_assembly_getrootdir ());
431                         break;
432                 case MONO_IMAGE_OK:
433                         /* to suppress compiler warning */
434                         break;
435                 }
436                 
437                 exit (1);
438         }
439         mono_defaults.corlib = mono_assembly_get_image (ass);
440
441         mono_defaults.object_class = mono_class_from_name (
442                 mono_defaults.corlib, "System", "Object");
443         g_assert (mono_defaults.object_class != 0);
444
445         mono_defaults.void_class = mono_class_from_name (
446                 mono_defaults.corlib, "System", "Void");
447         g_assert (mono_defaults.void_class != 0);
448
449         mono_defaults.boolean_class = mono_class_from_name (
450                 mono_defaults.corlib, "System", "Boolean");
451         g_assert (mono_defaults.boolean_class != 0);
452
453         mono_defaults.byte_class = mono_class_from_name (
454                 mono_defaults.corlib, "System", "Byte");
455         g_assert (mono_defaults.byte_class != 0);
456
457         mono_defaults.sbyte_class = mono_class_from_name (
458                 mono_defaults.corlib, "System", "SByte");
459         g_assert (mono_defaults.sbyte_class != 0);
460
461         mono_defaults.int16_class = mono_class_from_name (
462                 mono_defaults.corlib, "System", "Int16");
463         g_assert (mono_defaults.int16_class != 0);
464
465         mono_defaults.uint16_class = mono_class_from_name (
466                 mono_defaults.corlib, "System", "UInt16");
467         g_assert (mono_defaults.uint16_class != 0);
468
469         mono_defaults.int32_class = mono_class_from_name (
470                 mono_defaults.corlib, "System", "Int32");
471         g_assert (mono_defaults.int32_class != 0);
472
473         mono_defaults.uint32_class = mono_class_from_name (
474                 mono_defaults.corlib, "System", "UInt32");
475         g_assert (mono_defaults.uint32_class != 0);
476
477         mono_defaults.uint_class = mono_class_from_name (
478                 mono_defaults.corlib, "System", "UIntPtr");
479         g_assert (mono_defaults.uint_class != 0);
480
481         mono_defaults.int_class = mono_class_from_name (
482                 mono_defaults.corlib, "System", "IntPtr");
483         g_assert (mono_defaults.int_class != 0);
484
485         mono_defaults.int64_class = mono_class_from_name (
486                 mono_defaults.corlib, "System", "Int64");
487         g_assert (mono_defaults.int64_class != 0);
488
489         mono_defaults.uint64_class = mono_class_from_name (
490                 mono_defaults.corlib, "System", "UInt64");
491         g_assert (mono_defaults.uint64_class != 0);
492
493         mono_defaults.single_class = mono_class_from_name (
494                 mono_defaults.corlib, "System", "Single");
495         g_assert (mono_defaults.single_class != 0);
496
497         mono_defaults.double_class = mono_class_from_name (
498                 mono_defaults.corlib, "System", "Double");
499         g_assert (mono_defaults.double_class != 0);
500
501         mono_defaults.char_class = mono_class_from_name (
502                 mono_defaults.corlib, "System", "Char");
503         g_assert (mono_defaults.char_class != 0);
504
505         mono_defaults.string_class = mono_class_from_name (
506                 mono_defaults.corlib, "System", "String");
507         g_assert (mono_defaults.string_class != 0);
508
509         mono_defaults.enum_class = mono_class_from_name (
510                 mono_defaults.corlib, "System", "Enum");
511         g_assert (mono_defaults.enum_class != 0);
512
513         mono_defaults.array_class = mono_class_from_name (
514                 mono_defaults.corlib, "System", "Array");
515         g_assert (mono_defaults.array_class != 0);
516
517         mono_defaults.delegate_class = mono_class_from_name (
518                 mono_defaults.corlib, "System", "Delegate");
519         g_assert (mono_defaults.delegate_class != 0 );
520
521         mono_defaults.multicastdelegate_class = mono_class_from_name (
522                 mono_defaults.corlib, "System", "MulticastDelegate");
523         g_assert (mono_defaults.multicastdelegate_class != 0 );
524
525         mono_defaults.asyncresult_class = mono_class_from_name (
526                 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", 
527                 "AsyncResult");
528         g_assert (mono_defaults.asyncresult_class != 0 );
529
530         mono_defaults.waithandle_class = mono_class_from_name (
531                 mono_defaults.corlib, "System.Threading", "WaitHandle");
532         g_assert (mono_defaults.waithandle_class != 0 );
533
534         mono_defaults.typehandle_class = mono_class_from_name (
535                 mono_defaults.corlib, "System", "RuntimeTypeHandle");
536         g_assert (mono_defaults.typehandle_class != 0);
537
538         mono_defaults.methodhandle_class = mono_class_from_name (
539                 mono_defaults.corlib, "System", "RuntimeMethodHandle");
540         g_assert (mono_defaults.methodhandle_class != 0);
541
542         mono_defaults.fieldhandle_class = mono_class_from_name (
543                 mono_defaults.corlib, "System", "RuntimeFieldHandle");
544         g_assert (mono_defaults.fieldhandle_class != 0);
545
546         mono_defaults.monotype_class = mono_class_from_name (
547                 mono_defaults.corlib, "System", "MonoType");
548         g_assert (mono_defaults.monotype_class != 0);
549
550         mono_defaults.exception_class = mono_class_from_name (
551                 mono_defaults.corlib, "System", "Exception");
552         g_assert (mono_defaults.exception_class != 0);
553
554         mono_defaults.threadabortexception_class = mono_class_from_name (
555                 mono_defaults.corlib, "System.Threading", "ThreadAbortException");
556         g_assert (mono_defaults.threadabortexception_class != 0);
557
558         mono_defaults.thread_class = mono_class_from_name (
559                 mono_defaults.corlib, "System.Threading", "Thread");
560         g_assert (mono_defaults.thread_class != 0);
561
562         mono_defaults.appdomain_class = mono_class_from_name (
563                 mono_defaults.corlib, "System", "AppDomain");
564         g_assert (mono_defaults.appdomain_class != 0);
565
566         mono_defaults.transparent_proxy_class = mono_class_from_name (
567                 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
568         g_assert (mono_defaults.transparent_proxy_class != 0);
569
570         mono_defaults.real_proxy_class = mono_class_from_name (
571                 mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
572         g_assert (mono_defaults.real_proxy_class != 0);
573
574         mono_defaults.mono_method_message_class = mono_class_from_name (
575                 mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
576         g_assert (mono_defaults.mono_method_message_class != 0);
577
578         mono_defaults.field_info_class = mono_class_from_name (
579                 mono_defaults.corlib, "System.Reflection", "FieldInfo");
580         g_assert (mono_defaults.field_info_class != 0);
581
582         mono_defaults.method_info_class = mono_class_from_name (
583                 mono_defaults.corlib, "System.Reflection", "MethodInfo");
584         g_assert (mono_defaults.method_info_class != 0);
585
586         mono_defaults.stringbuilder_class = mono_class_from_name (
587                 mono_defaults.corlib, "System.Text", "StringBuilder");
588         g_assert (mono_defaults.stringbuilder_class != 0);
589
590         mono_defaults.math_class = mono_class_from_name (
591                 mono_defaults.corlib, "System", "Math");
592         g_assert (mono_defaults.math_class != 0);
593
594         mono_defaults.stack_frame_class = mono_class_from_name (
595                 mono_defaults.corlib, "System.Diagnostics", "StackFrame");
596         g_assert (mono_defaults.stack_frame_class != 0);
597
598         mono_defaults.stack_trace_class = mono_class_from_name (
599                 mono_defaults.corlib, "System.Diagnostics", "StackTrace");
600         g_assert (mono_defaults.stack_trace_class != 0);
601
602         mono_defaults.marshal_class = mono_class_from_name (
603                 mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
604         g_assert (mono_defaults.marshal_class != 0);
605
606         mono_defaults.iserializeable_class = mono_class_from_name (
607                 mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable");
608         g_assert (mono_defaults.iserializeable_class != 0);
609
610         mono_defaults.serializationinfo_class = mono_class_from_name (
611                 mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo");
612         g_assert (mono_defaults.serializationinfo_class != 0);
613
614         mono_defaults.streamingcontext_class = mono_class_from_name (
615                 mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext");
616         g_assert (mono_defaults.streamingcontext_class != 0);
617
618         mono_defaults.typed_reference_class =  mono_class_from_name (
619                 mono_defaults.corlib, "System", "TypedReference");
620         g_assert (mono_defaults.typed_reference_class != 0);
621
622         mono_defaults.argumenthandle_class =  mono_class_from_name (
623                 mono_defaults.corlib, "System", "RuntimeArgumentHandle");
624         g_assert (mono_defaults.argumenthandle_class != 0);
625
626         mono_defaults.marshalbyrefobject_class =  mono_class_from_name (
627                 mono_defaults.corlib, "System", "MarshalByRefObject");
628         g_assert (mono_defaults.marshalbyrefobject_class != 0);
629
630         mono_defaults.monitor_class =  mono_class_from_name (
631                 mono_defaults.corlib, "System.Threading", "Monitor");
632         g_assert (mono_defaults.monitor_class != 0);
633
634         mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
635                 mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
636         g_assert (mono_defaults.iremotingtypeinfo_class != 0);
637
638         mono_defaults.runtimesecurityframe_class = mono_class_from_name (
639                 mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
640
641         mono_defaults.executioncontext_class = mono_class_from_name (
642                 mono_defaults.corlib, "System.Threading", "ExecutionContext");
643
644         domain->friendly_name = g_path_get_basename (filename);
645
646         return domain;
647 }
648
649 /**
650  * mono_init:
651  * 
652  * Creates the initial application domain and initializes the mono_defaults
653  * structure.
654  * This function is guaranteed to not run any IL code.
655  * The runtime is initialized using the default runtime version.
656  *
657  * Returns: the initial domain.
658  */
659 MonoDomain *
660 mono_init (const char *domain_name)
661 {
662         return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
663 }
664
665 /**
666  * mono_init_from_assembly:
667  * 
668  * Creates the initial application domain and initializes the mono_defaults
669  * structure.
670  * This function is guaranteed to not run any IL code.
671  * The runtime is initialized using the runtime version required by the
672  * provided executable. The version is determined by looking at the exe 
673  * configuration file and the version PE field)
674  *
675  * Returns: the initial domain.
676  */
677 MonoDomain *
678 mono_init_from_assembly (const char *domain_name, const char *filename)
679 {
680         return mono_init_internal (domain_name, filename, NULL);
681 }
682
683 /**
684  * mono_init_version:
685  * 
686  * Creates the initial application domain and initializes the mono_defaults
687  * structure.
688  * This function is guaranteed to not run any IL code.
689  * The runtime is initialized using the provided rutime version.
690  *
691  * Returns: the initial domain.
692  */
693 MonoDomain *
694 mono_init_version (const char *domain_name, const char *version)
695 {
696         return mono_init_internal (domain_name, NULL, version);
697 }
698
699 MonoDomain*
700 mono_get_root_domain (void)
701 {
702         return mono_root_domain;
703 }
704
705 /**
706  * mono_domain_get:
707  *
708  * Returns: the current domain.
709  */
710 MonoDomain *
711 mono_domain_get ()
712 {
713         return GET_APPDOMAIN ();
714 }
715
716 /**
717  * mono_domain_set_internal:
718  * @domain: the new domain
719  *
720  * Sets the current domain to @domain.
721  */
722 void
723 mono_domain_set_internal (MonoDomain *domain)
724 {
725         SET_APPDOMAIN (domain);
726         SET_APPCONTEXT (domain->default_context);
727 }
728
729 void
730 mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
731 {
732         int i, size;
733         MonoDomain **copy;
734
735         /*
736          * Create a copy of the data to avoid calling the user callback
737          * inside the lock because that could lead to deadlocks.
738          * We can do this because this function is not perf. critical.
739          */
740         EnterCriticalSection (&appdomains_mutex);
741         size = appdomain_list_size;
742         copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
743         memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
744         LeaveCriticalSection (&appdomains_mutex);
745
746         for (i = 0; i < size; ++i) {
747                 if (copy [i])
748                         func (copy [i], user_data);
749         }
750
751         mono_gc_free_fixed (copy);
752 }
753
754 /**
755  * mono_domain_assembly_open:
756  * @domain: the application domain
757  * @name: file name of the assembly
758  *
759  * fixme: maybe we should integrate this with mono_assembly_open ??
760  */
761 MonoAssembly *
762 mono_domain_assembly_open (MonoDomain *domain, const char *name)
763 {
764         MonoAssembly *ass;
765         GSList *tmp;
766
767         mono_domain_lock (domain);
768         for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
769                 ass = tmp->data;
770                 if (strcmp (name, ass->aname.name) == 0) {
771                         mono_domain_unlock (domain);
772                         return ass;
773                 }
774         }
775         mono_domain_unlock (domain);
776
777         if (!(ass = mono_assembly_open (name, NULL)))
778                 return NULL;
779
780         return ass;
781 }
782
783 static void
784 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
785 {
786         MonoJitDynamicMethodInfo *di = value;
787         mono_code_manager_destroy (di->code_mp);
788         g_free (di);
789 }
790
791 static void
792 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
793 {
794         g_slist_free (value);
795 }
796
797 void
798 mono_domain_free (MonoDomain *domain, gboolean force)
799 {
800         GSList *tmp;
801         if ((domain == mono_root_domain) && !force) {
802                 g_warning ("cant unload root domain");
803                 return;
804         }
805
806         EnterCriticalSection (&appdomains_mutex);
807         appdomains_list [domain->domain_id] = NULL;
808         LeaveCriticalSection (&appdomains_mutex);
809
810         /* FIXME: free delegate_hash_table when it's used */
811         if (domain->search_path) {
812                 g_strfreev (domain->search_path);
813                 domain->search_path = NULL;
814         }
815         domain->create_proxy_for_type_method = NULL;
816         domain->private_invoke_method = NULL;
817         domain->default_context = NULL;
818         domain->out_of_memory_ex = NULL;
819         domain->null_reference_ex = NULL;
820         domain->stack_overflow_ex = NULL;
821         domain->entry_assembly = NULL;
822         g_free (domain->friendly_name);
823         domain->friendly_name = NULL;
824         for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
825                 MonoAssembly *ass = tmp->data;
826                 /*g_print ("Unloading domain %p, assembly %s, refcount: %d\n", domain, ass->aname.name, ass->ref_count);*/
827                 mono_assembly_close (ass);
828         }
829         g_slist_free (domain->domain_assemblies);
830         domain->domain_assemblies = NULL;
831
832         mono_g_hash_table_destroy (domain->env);
833         domain->env = NULL;
834         g_hash_table_destroy (domain->class_vtable_hash);
835         domain->class_vtable_hash = NULL;
836         mono_g_hash_table_destroy (domain->proxy_vtable_hash);
837         domain->proxy_vtable_hash = NULL;
838         mono_g_hash_table_destroy (domain->static_data_hash);
839         domain->static_data_hash = NULL;
840         g_hash_table_destroy (domain->jit_code_hash);
841         domain->jit_code_hash = NULL;
842         if (domain->dynamic_code_hash) {
843                 g_hash_table_foreach (domain->dynamic_code_hash, dynamic_method_info_free, NULL);
844                 g_hash_table_destroy (domain->dynamic_code_hash);
845                 domain->dynamic_code_hash = NULL;
846         }
847         mono_g_hash_table_destroy (domain->ldstr_table);
848         domain->ldstr_table = NULL;
849         mono_jit_info_table_free (domain->jit_info_table);
850         domain->jit_info_table = NULL;
851 #ifdef DEBUG_DOMAIN_UNLOAD
852         mono_mempool_invalidate (domain->mp);
853         mono_code_manager_invalidate (domain->code_mp);
854 #else
855         mono_mempool_destroy (domain->mp);
856         domain->mp = NULL;
857         mono_code_manager_destroy (domain->code_mp);
858         domain->code_mp = NULL;
859 #endif  
860         if (domain->jump_target_hash) {
861                 g_hash_table_foreach (domain->jump_target_hash, delete_jump_list, NULL);
862                 g_hash_table_destroy (domain->jump_target_hash);
863                 domain->jump_target_hash = NULL;
864         }
865         if (domain->type_hash) {
866                 mono_g_hash_table_destroy (domain->type_hash);
867                 domain->type_hash = NULL;
868         }
869         if (domain->refobject_hash) {
870                 mono_g_hash_table_destroy (domain->refobject_hash);
871                 domain->refobject_hash = NULL;
872         }
873         g_hash_table_destroy (domain->class_init_trampoline_hash);
874         domain->class_init_trampoline_hash = NULL;
875         g_hash_table_destroy (domain->jump_trampoline_hash);
876         domain->jump_trampoline_hash = NULL;
877         g_hash_table_destroy (domain->finalizable_objects_hash);
878         domain->finalizable_objects_hash = NULL;
879         g_hash_table_destroy (domain->jit_trampoline_hash);
880         domain->jit_trampoline_hash = NULL;
881         if (domain->special_static_fields) {
882                 g_hash_table_destroy (domain->special_static_fields);
883                 domain->special_static_fields = NULL;
884         }
885         DeleteCriticalSection (&domain->lock);
886         domain->setup = NULL;
887
888         /* FIXME: anything else required ? */
889
890         mono_gc_free_fixed (domain);
891
892         if ((domain == mono_root_domain))
893                 mono_root_domain = NULL;
894 }
895
896 /**
897  * mono_domain_get_id:
898  *
899  * Returns: the a domain for a specific domain id.
900  */
901 MonoDomain * 
902 mono_domain_get_by_id (gint32 domainid) 
903 {
904         MonoDomain * domain;
905
906         EnterCriticalSection (&appdomains_mutex);
907         if (domainid < appdomain_list_size)
908                 domain = appdomains_list [domainid];
909         else
910                 domain = NULL;
911         LeaveCriticalSection (&appdomains_mutex);
912
913         return domain;
914 }
915
916 gint32
917 mono_domain_get_id (MonoDomain *domain)
918 {
919         return domain->domain_id;
920 }
921
922 void 
923 mono_context_set (MonoAppContext * new_context)
924 {
925         SET_APPCONTEXT (new_context);
926 }
927
928 MonoAppContext * 
929 mono_context_get (void)
930 {
931         return GET_APPCONTEXT ();
932 }
933
934 MonoImage*
935 mono_get_corlib (void)
936 {
937         return mono_defaults.corlib;
938 }
939
940 MonoClass*
941 mono_get_object_class (void)
942 {
943         return mono_defaults.object_class;
944 }
945
946 MonoClass*
947 mono_get_byte_class (void)
948 {
949         return mono_defaults.byte_class;
950 }
951
952 MonoClass*
953 mono_get_void_class (void)
954 {
955         return mono_defaults.void_class;
956 }
957
958 MonoClass*
959 mono_get_boolean_class (void)
960 {
961         return mono_defaults.boolean_class;
962 }
963
964 MonoClass*
965 mono_get_sbyte_class (void)
966 {
967         return mono_defaults.sbyte_class;
968 }
969
970 MonoClass*
971 mono_get_int16_class (void)
972 {
973         return mono_defaults.int16_class;
974 }
975
976 MonoClass*
977 mono_get_uint16_class (void)
978 {
979         return mono_defaults.uint16_class;
980 }
981
982 MonoClass*
983 mono_get_int32_class (void)
984 {
985         return mono_defaults.int32_class;
986 }
987
988 MonoClass*
989 mono_get_uint32_class (void)
990 {
991         return mono_defaults.uint32_class;
992 }
993
994 MonoClass*
995 mono_get_intptr_class (void)
996 {
997         return mono_defaults.int_class;
998 }
999
1000 MonoClass*
1001 mono_get_uintptr_class (void)
1002 {
1003         return mono_defaults.uint_class;
1004 }
1005
1006 MonoClass*
1007 mono_get_int64_class (void)
1008 {
1009         return mono_defaults.int64_class;
1010 }
1011
1012 MonoClass*
1013 mono_get_uint64_class (void)
1014 {
1015         return mono_defaults.uint64_class;
1016 }
1017
1018 MonoClass*
1019 mono_get_single_class (void)
1020 {
1021         return mono_defaults.single_class;
1022 }
1023
1024 MonoClass*
1025 mono_get_double_class (void)
1026 {
1027         return mono_defaults.double_class;
1028 }
1029
1030 MonoClass*
1031 mono_get_char_class (void)
1032 {
1033         return mono_defaults.char_class;
1034 }
1035
1036 MonoClass*
1037 mono_get_string_class (void)
1038 {
1039         return mono_defaults.string_class;
1040 }
1041
1042 MonoClass*
1043 mono_get_enum_class (void)
1044 {
1045         return mono_defaults.enum_class;
1046 }
1047
1048 MonoClass*
1049 mono_get_array_class (void)
1050 {
1051         return mono_defaults.array_class;
1052 }
1053
1054 MonoClass*
1055 mono_get_thread_class (void)
1056 {
1057         return mono_defaults.thread_class;
1058 }
1059
1060 MonoClass*
1061 mono_get_exception_class (void)
1062 {
1063         return mono_defaults.exception_class;
1064 }
1065
1066
1067 static char* get_attribute_value (const gchar **attribute_names, 
1068                                         const gchar **attribute_values, 
1069                                         const char *att_name)
1070 {
1071         int n;
1072         for (n=0; attribute_names[n] != NULL; n++) {
1073                 if (strcmp (attribute_names[n], att_name) == 0)
1074                         return g_strdup (attribute_values[n]);
1075         }
1076         return NULL;
1077 }
1078
1079 static void start_element (GMarkupParseContext *context, 
1080                            const gchar         *element_name,
1081                            const gchar        **attribute_names,
1082                            const gchar        **attribute_values,
1083                            gpointer             user_data,
1084                            GError             **error)
1085 {
1086         AppConfigInfo* app_config = (AppConfigInfo*) user_data;
1087         
1088         if (strcmp (element_name, "configuration") == 0) {
1089                 app_config->configuration_count++;
1090                 return;
1091         }
1092         if (strcmp (element_name, "startup") == 0) {
1093                 app_config->startup_count++;
1094                 return;
1095         }
1096         
1097         if (app_config->configuration_count != 1 || app_config->startup_count != 1)
1098                 return;
1099         
1100         if (strcmp (element_name, "requiredRuntime") == 0) {
1101                 app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
1102         } else if (strcmp (element_name, "supportedRuntime") == 0) {
1103                 char *version = get_attribute_value (attribute_names, attribute_values, "version");
1104                 app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
1105         }
1106 }
1107
1108 static void end_element   (GMarkupParseContext *context,
1109                            const gchar         *element_name,
1110                            gpointer             user_data,
1111                            GError             **error)
1112 {
1113         AppConfigInfo* app_config = (AppConfigInfo*) user_data;
1114         
1115         if (strcmp (element_name, "configuration") == 0) {
1116                 app_config->configuration_count--;
1117         } else if (strcmp (element_name, "startup") == 0) {
1118                 app_config->startup_count--;
1119         }
1120 }
1121
1122 static const GMarkupParser 
1123 mono_parser = {
1124         start_element,
1125         end_element,
1126         NULL,
1127         NULL,
1128         NULL
1129 };
1130
1131 static AppConfigInfo *
1132 app_config_parse (const char *filename)
1133 {
1134         AppConfigInfo *app_config;
1135         GMarkupParseContext *context;
1136         char *text;
1137         gsize len;
1138         
1139         struct stat buf;
1140         if (stat (filename, &buf) != 0)
1141                 return NULL;
1142         
1143         app_config = g_new0 (AppConfigInfo, 1);
1144
1145         if (!g_file_get_contents (filename, &text, &len, NULL))
1146                 return NULL;
1147
1148         context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
1149         if (g_markup_parse_context_parse (context, text, len, NULL)) {
1150                 g_markup_parse_context_end_parse (context, NULL);
1151         }
1152         g_markup_parse_context_free (context);
1153         g_free (text);
1154         return app_config;
1155 }
1156
1157 static void 
1158 app_config_free (AppConfigInfo* app_config)
1159 {
1160         char *rt;
1161         GSList *list = app_config->supported_runtimes;
1162         while (list != NULL) {
1163                 rt = (char*)list->data;
1164                 g_free (rt);
1165                 list = g_slist_next (list);
1166         }
1167         g_slist_free (app_config->supported_runtimes);
1168         g_free (app_config->required_runtime);
1169         g_free (app_config);
1170 }
1171
1172
1173 static const MonoRuntimeInfo*
1174 get_runtime_by_version (const char *version)
1175 {
1176         int n;
1177         int max = G_N_ELEMENTS (supported_runtimes);
1178         
1179         for (n=0; n<max; n++) {
1180                 if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
1181                         return &supported_runtimes[n];
1182         }
1183         return NULL;
1184 }
1185
1186 static void
1187 get_runtimes_from_exe (const char *exe_file, const MonoRuntimeInfo** runtimes)
1188 {
1189         AppConfigInfo* app_config;
1190         char *version;
1191         char *config_name;
1192         const MonoRuntimeInfo* runtime = NULL;
1193         MonoImage *image = NULL;
1194         
1195         config_name = g_strconcat (exe_file, ".config", NULL);
1196         app_config = app_config_parse (config_name);
1197         g_free (config_name);
1198         
1199         if (app_config != NULL) {
1200                 /* Check supportedRuntime elements, if none is supported, fail.
1201                  * If there are no such elements, look for a requiredRuntime element.
1202                  */
1203                 if (app_config->supported_runtimes != NULL) {
1204                         int n = 0;
1205                         GSList *list = app_config->supported_runtimes;
1206                         while (list != NULL) {
1207                                 version = (char*) list->data;
1208                                 runtime = get_runtime_by_version (version);
1209                                 if (runtime != NULL)
1210                                         runtimes [n++] = runtime;
1211                                 list = g_slist_next (list);
1212                         }
1213                         runtimes [n] = NULL;
1214                         app_config_free (app_config);
1215                         return;
1216                 }
1217                 
1218                 /* Check the requiredRuntime element. This is for 1.0 apps only. */
1219                 if (app_config->required_runtime != NULL) {
1220                         runtimes [0] = get_runtime_by_version (app_config->required_runtime);
1221                         runtimes [1] = NULL;
1222                         app_config_free (app_config);
1223                         return;
1224                 }
1225                 app_config_free (app_config);
1226         }
1227         
1228         /* Look for a runtime with the exact version */
1229         image = mono_image_open (exe_file, NULL);
1230         if (image == NULL) {
1231                 /* The image is wrong or the file was not found. In this case return
1232                  * a default runtime and leave to the initialization method the work of
1233                  * reporting the error.
1234                  */
1235                 runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
1236                 runtimes [1] = NULL;
1237                 return;
1238         }
1239
1240         runtimes [0] = get_runtime_by_version (image->version);
1241         runtimes [1] = NULL;
1242 }
1243
1244
1245 /**
1246  * mono_get_runtime_info:
1247  *
1248  * Returns: the version of the current runtime instance.
1249  */
1250 const MonoRuntimeInfo*
1251 mono_get_runtime_info (void)
1252 {
1253         return current_runtime;
1254 }
1255
1256 gchar *
1257 mono_debugger_check_runtime_version (const char *filename)
1258 {
1259         const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
1260         const MonoRuntimeInfo *rinfo;
1261
1262         get_runtimes_from_exe (filename, runtimes);
1263         rinfo = runtimes [0];
1264
1265         if (!rinfo)
1266                 return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
1267
1268         if (rinfo != current_runtime)
1269                 return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
1270                                         "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
1271                                         filename, rinfo->runtime_version);
1272
1273         return NULL;
1274 }