Fix an uninitialized memory error in the AOT runtime.
[mono.git] / mono / mini / aot-runtime.c
1 /*
2  * aot-runtime.c: mono Ahead of Time compiler
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Zoltan Varga (vargaz@gmail.com)
7  *
8  * (C) 2002 Ximian, Inc.
9  * Copyright 2003-2011 Novell, Inc.
10  * Copyright 2011 Xamarin, Inc.
11  */
12
13 #include "config.h"
14 #include <sys/types.h>
15 #ifdef HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18 #include <fcntl.h>
19 #include <string.h>
20 #ifdef HAVE_SYS_MMAN_H
21 #include <sys/mman.h>
22 #endif
23
24 #if HOST_WIN32
25 #include <winsock2.h>
26 #include <windows.h>
27 #endif
28
29 #ifdef HAVE_EXECINFO_H
30 #include <execinfo.h>
31 #endif
32
33 #include <errno.h>
34 #include <sys/stat.h>
35
36 #ifdef HAVE_SYS_WAIT_H
37 #include <sys/wait.h>  /* for WIFEXITED, WEXITSTATUS */
38 #endif
39
40 #ifdef HAVE_DL_ITERATE_PHDR
41 #include <link.h>
42 #endif
43
44 #include <mono/metadata/tabledefs.h>
45 #include <mono/metadata/class.h>
46 #include <mono/metadata/object.h>
47 #include <mono/metadata/tokentype.h>
48 #include <mono/metadata/appdomain.h>
49 #include <mono/metadata/debug-helpers.h>
50 #include <mono/metadata/assembly.h>
51 #include <mono/metadata/metadata-internals.h>
52 #include <mono/metadata/marshal.h>
53 #include <mono/metadata/gc-internal.h>
54 #include <mono/metadata/monitor.h>
55 #include <mono/metadata/threads-types.h>
56 #include <mono/metadata/mono-endian.h>
57 #include <mono/utils/mono-logger-internal.h>
58 #include <mono/utils/mono-mmap.h>
59 #include "mono/utils/mono-compiler.h"
60 #include <mono/utils/mono-counters.h>
61
62 #include "mini.h"
63 #include "version.h"
64
65 #ifndef DISABLE_AOT
66
67 #ifdef TARGET_WIN32
68 #define SHARED_EXT ".dll"
69 #elif ((defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__)) || defined(__MACH__)) && !defined(__linux__)
70 #define SHARED_EXT ".dylib"
71 #elif defined(__APPLE__) && defined(TARGET_X86) && !defined(__native_client_codegen__)
72 #define SHARED_EXT ".dylib"
73 #else
74 #define SHARED_EXT ".so"
75 #endif
76
77 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
78 #define ROUND_DOWN(VALUE,SIZE)  ((VALUE) & ~((SIZE) - 1))
79
80 typedef struct MonoAotModule {
81         char *aot_name;
82         /* Pointer to the Global Offset Table */
83         gpointer *got;
84         GHashTable *name_cache;
85         GHashTable *extra_methods;
86         /* Maps methods to their code */
87         GHashTable *method_to_code;
88         /* Maps pointers into the method info to the methods themselves */
89         GHashTable *method_ref_to_method;
90         MonoAssemblyName *image_names;
91         char **image_guids;
92         MonoAssembly *assembly;
93         MonoImage **image_table;
94         guint32 image_table_len;
95         gboolean out_of_date;
96         gboolean plt_inited;
97         guint8 *mem_begin;
98         guint8 *mem_end;
99         guint8 *code;
100         guint8 *code_end;
101         guint8 *plt;
102         guint8 *plt_end;
103         guint8 *blob;
104         gint32 *code_offsets;
105         /* This contains <offset, index> pairs sorted by offset */
106         /* This is needed because LLVM emitted methods can be in any order */
107         gint32 *sorted_code_offsets;
108         gint32 sorted_code_offsets_len;
109         guint32 *method_info_offsets;
110         guint32 *got_info_offsets;
111         guint32 *ex_info_offsets;
112         guint32 *class_info_offsets;
113         guint32 *methods_loaded;
114         guint16 *class_name_table;
115         guint32 *extra_method_table;
116         guint32 *extra_method_info_offsets;
117         guint32 *unbox_trampolines;
118         guint32 *unbox_trampolines_end;
119         guint8 *unwind_info;
120         guint8 *thumb_end;
121
122         /* Points to the mono EH data created by LLVM */
123         guint8 *mono_eh_frame;
124
125         /* Points to the trampolines */
126         guint8 *trampolines [MONO_AOT_TRAMP_NUM];
127         /* The first unused trampoline of each kind */
128         guint32 trampoline_index [MONO_AOT_TRAMP_NUM];
129
130         MonoAotFileInfo info;
131
132         gpointer *globals;
133         MonoDl *sofile;
134 } MonoAotModule;
135
136 static GHashTable *aot_modules;
137 #define mono_aot_lock() EnterCriticalSection (&aot_mutex)
138 #define mono_aot_unlock() LeaveCriticalSection (&aot_mutex)
139 static CRITICAL_SECTION aot_mutex;
140
141 /* 
142  * Maps assembly names to the mono_aot_module_<NAME>_info symbols in the
143  * AOT modules registered by mono_aot_register_module ().
144  */
145 static GHashTable *static_aot_modules;
146
147 /*
148  * Maps MonoJitInfo* to the aot module they belong to, this can be different
149  * from ji->method->klass->image's aot module for generic instances.
150  */
151 static GHashTable *ji_to_amodule;
152
153 /*
154  * Whenever to AOT compile loaded assemblies on demand and store them in
155  * a cache under $HOME/.mono/aot-cache.
156  */
157 static gboolean use_aot_cache = FALSE;
158
159 /*
160  * Whenever to spawn a new process to AOT a file or do it in-process. Only relevant if
161  * use_aot_cache is TRUE.
162  */
163 static gboolean spawn_compiler = TRUE;
164
165 /* For debugging */
166 static gint32 mono_last_aot_method = -1;
167
168 static gboolean make_unreadable = FALSE;
169 static guint32 name_table_accesses = 0;
170 static guint32 n_pagefaults = 0;
171
172 /* Used to speed-up find_aot_module () */
173 static gsize aot_code_low_addr = (gssize)-1;
174 static gsize aot_code_high_addr = 0;
175
176 static GHashTable *aot_jit_icall_hash;
177
178 static void
179 init_plt (MonoAotModule *info);
180
181 /*****************************************************/
182 /*                 AOT RUNTIME                       */
183 /*****************************************************/
184
185 /*
186  * load_image:
187  *
188  *   Load one of the images referenced by AMODULE. Returns NULL if the image is not
189  * found, and sets the loader error if SET_ERROR is TRUE.
190  */
191 static MonoImage *
192 load_image (MonoAotModule *amodule, int index, gboolean set_error)
193 {
194         MonoAssembly *assembly;
195         MonoImageOpenStatus status;
196
197         g_assert (index < amodule->image_table_len);
198
199         if (amodule->image_table [index])
200                 return amodule->image_table [index];
201         if (amodule->out_of_date)
202                 return NULL;
203
204         assembly = mono_assembly_load (&amodule->image_names [index], amodule->assembly->basedir, &status);
205         if (!assembly) {
206                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is unusable because dependency %s is not found.\n", amodule->aot_name, amodule->image_names [index].name);
207                 amodule->out_of_date = TRUE;
208
209                 if (set_error) {
210                         char *full_name = mono_stringify_assembly_name (&amodule->image_names [index]);
211                         mono_loader_set_error_assembly_load (full_name, FALSE);
212                         g_free (full_name);
213                 }
214                 return NULL;
215         }
216
217         if (strcmp (assembly->image->guid, amodule->image_guids [index])) {
218                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is unusable (GUID of dependent assembly %s doesn't match (expected '%s', got '%s').\n", amodule->aot_name, amodule->image_names [index].name, amodule->image_guids [index], assembly->image->guid);
219                 amodule->out_of_date = TRUE;
220                 return NULL;
221         }
222
223         amodule->image_table [index] = assembly->image;
224         return assembly->image;
225 }
226
227 static inline gint32
228 decode_value (guint8 *ptr, guint8 **rptr)
229 {
230         guint8 b = *ptr;
231         gint32 len;
232         
233         if ((b & 0x80) == 0){
234                 len = b;
235                 ++ptr;
236         } else if ((b & 0x40) == 0){
237                 len = ((b & 0x3f) << 8 | ptr [1]);
238                 ptr += 2;
239         } else if (b != 0xff) {
240                 len = ((b & 0x1f) << 24) |
241                         (ptr [1] << 16) |
242                         (ptr [2] << 8) |
243                         ptr [3];
244                 ptr += 4;
245         }
246         else {
247                 len = (ptr [1] << 24) | (ptr [2] << 16) | (ptr [3] << 8) | ptr [4];
248                 ptr += 5;
249         }
250         if (rptr)
251                 *rptr = ptr;
252
253         //printf ("DECODE: %d.\n", len);
254         return len;
255 }
256
257 /*
258  * mono_aot_get_method:
259  *
260  *   Decode an offset table emitted by emit_offset_table (), returning the INDEXth
261  * entry.
262  */
263 static guint32
264 mono_aot_get_offset (guint32 *table, int index)
265 {
266         int i, group, ngroups, index_entry_size;
267         int start_offset, offset, noffsets, group_size;
268         guint8 *data_start, *p;
269         guint32 *index32 = NULL;
270         guint16 *index16 = NULL;
271         
272         noffsets = table [0];
273         group_size = table [1];
274         ngroups = table [2];
275         index_entry_size = table [3];
276         group = index / group_size;
277
278         if (index_entry_size == 2) {
279                 index16 = (guint16*)&table [4];
280                 data_start = (guint8*)&index16 [ngroups];
281                 p = data_start + index16 [group];
282         } else {
283                 index32 = (guint32*)&table [4];
284                 data_start = (guint8*)&index32 [ngroups];
285                 p = data_start + index32 [group];
286         }
287
288         /* offset will contain the value of offsets [group * group_size] */
289         offset = start_offset = decode_value (p, &p);
290         for (i = group * group_size + 1; i <= index; ++i) {
291                 offset += decode_value (p, &p);
292         }
293
294         //printf ("Offset lookup: %d -> %d, start=%d, p=%d\n", index, offset, start_offset, table [3 + group]);
295
296         return offset;
297 }
298
299 static MonoMethod*
300 decode_resolve_method_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf);
301
302 static MonoClass*
303 decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf);
304
305 static MonoGenericInst*
306 decode_generic_inst (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
307 {
308         int type_argc, i;
309         MonoType **type_argv;
310         MonoGenericInst *inst;
311         guint8 *p = buf;
312
313         type_argc = decode_value (p, &p);
314         type_argv = g_new0 (MonoType*, type_argc);
315
316         for (i = 0; i < type_argc; ++i) {
317                 MonoClass *pclass = decode_klass_ref (module, p, &p);
318                 if (!pclass) {
319                         g_free (type_argv);
320                         return NULL;
321                 }
322                 type_argv [i] = &pclass->byval_arg;
323         }
324
325         inst = mono_metadata_get_generic_inst (type_argc, type_argv);
326         g_free (type_argv);
327
328         *endbuf = p;
329
330         return inst;
331 }
332
333 static gboolean
334 decode_generic_context (MonoAotModule *module, MonoGenericContext *ctx, guint8 *buf, guint8 **endbuf)
335 {
336         guint8 *p = buf;
337         guint8 *p2;
338         int argc;
339
340         p2 = p;
341         argc = decode_value (p, &p);
342         if (argc) {
343                 p = p2;
344                 ctx->class_inst = decode_generic_inst (module, p, &p);
345                 if (!ctx->class_inst)
346                         return FALSE;
347         }
348         p2 = p;
349         argc = decode_value (p, &p);
350         if (argc) {
351                 p = p2;
352                 ctx->method_inst = decode_generic_inst (module, p, &p);
353                 if (!ctx->method_inst)
354                         return FALSE;
355         }
356
357         *endbuf = p;
358         return TRUE;
359 }
360
361 static MonoClass*
362 decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
363 {
364         MonoImage *image;
365         MonoClass *klass = NULL, *eklass;
366         guint32 token, rank, idx;
367         guint8 *p = buf;
368         int reftype;
369
370         reftype = decode_value (p, &p);
371         if (reftype == 0) {
372                 *endbuf = p;
373                 return NULL;
374         }
375
376         switch (reftype) {
377         case MONO_AOT_TYPEREF_TYPEDEF_INDEX:
378                 idx = decode_value (p, &p);
379                 image = load_image (module, 0, TRUE);
380                 if (!image)
381                         return NULL;
382                 klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF + idx);
383                 break;
384         case MONO_AOT_TYPEREF_TYPEDEF_INDEX_IMAGE:
385                 idx = decode_value (p, &p);
386                 image = load_image (module, decode_value (p, &p), TRUE);
387                 if (!image)
388                         return NULL;
389                 klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF + idx);
390                 break;
391         case MONO_AOT_TYPEREF_TYPESPEC_TOKEN:
392                 token = decode_value (p, &p);
393                 image = module->assembly->image;
394                 if (!image)
395                         return NULL;
396                 klass = mono_class_get (image, token);
397                 break;
398         case MONO_AOT_TYPEREF_GINST: {
399                 MonoClass *gclass;
400                 MonoGenericContext ctx;
401                 MonoType *type;
402
403                 gclass = decode_klass_ref (module, p, &p);
404                 if (!gclass)
405                         return NULL;
406                 g_assert (gclass->generic_container);
407
408                 memset (&ctx, 0, sizeof (ctx));
409                 ctx.class_inst = decode_generic_inst (module, p, &p);
410                 if (!ctx.class_inst)
411                         return NULL;
412                 type = mono_class_inflate_generic_type (&gclass->byval_arg, &ctx);
413                 klass = mono_class_from_mono_type (type);
414                 mono_metadata_free_type (type);
415                 break;
416         }
417         case MONO_AOT_TYPEREF_VAR: {
418                 MonoType *t;
419                 MonoGenericContainer *container;
420                 int type = decode_value (p, &p);
421                 int num = decode_value (p, &p);
422                 gboolean is_method = decode_value (p, &p);
423
424                 if (is_method) {
425                         MonoMethod *method_def;
426                         g_assert (type == MONO_TYPE_MVAR);
427                         method_def = decode_resolve_method_ref (module, p, &p);
428                         if (!method_def)
429                                 return NULL;
430
431                         container = mono_method_get_generic_container (method_def);
432                 } else {
433                         MonoClass *class_def;
434                         g_assert (type == MONO_TYPE_VAR);
435                         class_def = decode_klass_ref (module, p, &p);
436                         if (!class_def)
437                                 return NULL;
438
439                         container = class_def->generic_container;
440                 }
441
442                 g_assert (container);
443
444                 // FIXME: Memory management
445                 t = g_new0 (MonoType, 1);
446                 t->type = type;
447                 t->data.generic_param = mono_generic_container_get_param (container, num);
448
449                 // FIXME: Maybe use types directly to avoid
450                 // the overhead of creating MonoClass-es
451                 klass = mono_class_from_mono_type (t);
452
453                 g_free (t);
454                 break;
455         }
456         case MONO_AOT_TYPEREF_ARRAY:
457                 /* Array */
458                 rank = decode_value (p, &p);
459                 eklass = decode_klass_ref (module, p, &p);
460                 klass = mono_array_class_get (eklass, rank);
461                 break;
462         case MONO_AOT_TYPEREF_BLOB_INDEX: {
463                 guint32 offset = decode_value (p, &p);
464                 guint8 *p2;
465
466                 p2 = module->blob + offset;
467                 klass = decode_klass_ref (module, p2, &p2);
468                 break;
469         }
470         default:
471                 g_assert_not_reached ();
472         }
473         g_assert (klass);
474         //printf ("BLA: %s\n", mono_type_full_name (&klass->byval_arg));
475         *endbuf = p;
476         return klass;
477 }
478
479 static MonoClassField*
480 decode_field_info (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
481 {
482         MonoClass *klass = decode_klass_ref (module, buf, &buf);
483         guint32 token;
484         guint8 *p = buf;
485
486         if (!klass)
487                 return NULL;
488
489         token = MONO_TOKEN_FIELD_DEF + decode_value (p, &p);
490
491         *endbuf = p;
492
493         return mono_class_get_field (klass, token);
494 }
495
496 /*
497  * Parse a MonoType encoded by encode_type () in aot-compiler.c. Return malloc-ed
498  * memory.
499  */
500 static MonoType*
501 decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
502 {
503         guint8 *p = buf;
504         MonoType *t;
505
506         t = g_malloc0 (sizeof (MonoType));
507
508         while (TRUE) {
509                 if (*p == MONO_TYPE_PINNED) {
510                         t->pinned = TRUE;
511                         ++p;
512                 } else if (*p == MONO_TYPE_BYREF) {
513                         t->byref = TRUE;
514                         ++p;
515                 } else {
516                         break;
517                 }
518         }
519
520         t->type = *p;
521         ++p;
522
523         switch (t->type) {
524         case MONO_TYPE_VOID:
525         case MONO_TYPE_BOOLEAN:
526         case MONO_TYPE_CHAR:
527         case MONO_TYPE_I1:
528         case MONO_TYPE_U1:
529         case MONO_TYPE_I2:
530         case MONO_TYPE_U2:
531         case MONO_TYPE_I4:
532         case MONO_TYPE_U4:
533         case MONO_TYPE_I8:
534         case MONO_TYPE_U8:
535         case MONO_TYPE_R4:
536         case MONO_TYPE_R8:
537         case MONO_TYPE_I:
538         case MONO_TYPE_U:
539         case MONO_TYPE_STRING:
540         case MONO_TYPE_OBJECT:
541         case MONO_TYPE_TYPEDBYREF:
542                 break;
543         case MONO_TYPE_VALUETYPE:
544         case MONO_TYPE_CLASS:
545                 t->data.klass = decode_klass_ref (module, p, &p);
546                 break;
547         case MONO_TYPE_SZARRAY:
548                 t->data.klass = decode_klass_ref (module, p, &p);
549
550                 if (!t->data.klass)
551                         return NULL;
552                 break;
553         case MONO_TYPE_PTR:
554                 t->data.type = decode_type (module, p, &p);
555                 break;
556         case MONO_TYPE_GENERICINST: {
557                 MonoClass *gclass;
558                 MonoGenericContext ctx;
559                 MonoType *type;
560                 MonoClass *klass;
561
562                 gclass = decode_klass_ref (module, p, &p);
563                 if (!gclass)
564                         return NULL;
565                 g_assert (gclass->generic_container);
566
567                 memset (&ctx, 0, sizeof (ctx));
568                 ctx.class_inst = decode_generic_inst (module, p, &p);
569                 if (!ctx.class_inst)
570                         return NULL;
571                 type = mono_class_inflate_generic_type (&gclass->byval_arg, &ctx);
572                 klass = mono_class_from_mono_type (type);
573                 t->data.generic_class = klass->generic_class;
574                 break;
575         }
576         default:
577                 g_assert_not_reached ();
578         }
579
580         *endbuf = p;
581
582         return t;
583 }
584
585 // FIXME: Error handling, memory management
586
587 static MonoMethodSignature*
588 decode_signature_with_target (MonoAotModule *module, MonoMethodSignature *target, guint8 *buf, guint8 **endbuf)
589 {
590         MonoMethodSignature *sig;
591         guint32 flags;
592         int i, param_count, call_conv;
593         guint8 *p = buf;
594         gboolean hasthis, explicit_this, has_gen_params;
595
596         flags = *p;
597         p ++;
598         has_gen_params = (flags & 0x10) != 0;
599         hasthis = (flags & 0x20) != 0;
600         explicit_this = (flags & 0x40) != 0;
601         call_conv = flags & 0x0F;
602
603         g_assert (!has_gen_params);
604
605         param_count = decode_value (p, &p);
606         if (param_count != target->param_count)
607                 return NULL;
608         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + param_count * sizeof (MonoType *));
609         sig->param_count = param_count;
610         sig->sentinelpos = -1;
611         sig->hasthis = hasthis;
612         sig->explicit_this = explicit_this;
613         sig->call_convention = call_conv;
614         sig->param_count = param_count;
615         sig->ret = decode_type (module, p, &p);
616         for (i = 0; i < param_count; ++i)
617                 sig->params [i] = decode_type (module, p, &p);
618
619         *endbuf = p;
620
621         return sig;
622 }
623
624 static gboolean
625 sig_matches_target (MonoAotModule *module, MonoMethod *target, guint8 *buf, guint8 **endbuf)
626 {
627         MonoMethodSignature *sig;
628         gboolean res;
629         guint8 *p = buf;
630         
631         sig = decode_signature_with_target (module, mono_method_signature (target), p, &p);
632         res = sig && mono_metadata_signature_equal (mono_method_signature (target), sig);
633         g_free (sig);
634         *endbuf = p;
635         return res;
636 }
637
638 static gboolean
639 wrapper_name_matches_target (guint8 *p, MonoMethod *target)
640 {
641         char *name = (char*)p;
642         char *tname;
643
644         tname = mono_aot_wrapper_name (target);
645         if (!strcmp (name, tname))
646                 return TRUE;
647         else
648                 return FALSE;
649 }
650
651 /* Stores information returned by decode_method_ref () */
652 typedef struct {
653         MonoImage *image;
654         guint32 token;
655         MonoMethod *method;
656         gboolean no_aot_trampoline;
657 } MethodRef;
658
659 /*
660  * decode_method_ref_with_target:
661  *
662  *   Decode a method reference, storing the image/token into a MethodRef structure.
663  * This avoids loading metadata for the method if the caller does not need it. If the method has
664  * no token, then it is loaded from metadata and ref->method is set to the method instance.
665  * If TARGET is non-NULL, abort decoding if it can be determined that the decoded method couldn't resolve to TARGET, and return FALSE. There are some kinds of method references
666  * which only support a non-null TARGET.
667  */
668 static gboolean
669 decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod *target, guint8 *buf, guint8 **endbuf)
670 {
671         guint32 image_index, value;
672         MonoImage *image = NULL;
673         guint8 *p = buf;
674
675         memset (ref, 0, sizeof (MethodRef));
676
677         value = decode_value (p, &p);
678         image_index = value >> 24;
679
680         if (image_index == MONO_AOT_METHODREF_NO_AOT_TRAMPOLINE) {
681                 ref->no_aot_trampoline = TRUE;
682                 value = decode_value (p, &p);
683                 image_index = value >> 24;
684         }
685
686         if (image_index < MONO_AOT_METHODREF_MIN || image_index == MONO_AOT_METHODREF_METHODSPEC || image_index == MONO_AOT_METHODREF_GINST) {
687                 if (target && target->wrapper_type)
688                         return FALSE;
689         }
690
691         if (image_index == MONO_AOT_METHODREF_WRAPPER) {
692                 guint32 wrapper_type;
693
694                 wrapper_type = decode_value (p, &p);
695
696                 if (target && target->wrapper_type != wrapper_type)
697                         return FALSE;
698
699                 /* Doesn't matter */
700                 image = mono_defaults.corlib;
701
702                 switch (wrapper_type) {
703                 case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: {
704                         MonoMethod *m = decode_resolve_method_ref (module, p, &p);
705
706                         if (!m)
707                                 return FALSE;
708                         mono_class_init (m->klass);
709                         ref->method = mono_marshal_get_remoting_invoke_with_check (m);
710                         break;
711                 }
712                 case MONO_WRAPPER_PROXY_ISINST: {
713                         MonoClass *klass = decode_klass_ref (module, p, &p);
714                         if (!klass)
715                                 return FALSE;
716                         ref->method = mono_marshal_get_proxy_cancast (klass);
717                         break;
718                 }
719                 case MONO_WRAPPER_LDFLD:
720                 case MONO_WRAPPER_LDFLDA:
721                 case MONO_WRAPPER_STFLD:
722                 case MONO_WRAPPER_ISINST: {
723                         MonoClass *klass = decode_klass_ref (module, p, &p);
724                         if (!klass)
725                                 return FALSE;
726                         if (wrapper_type == MONO_WRAPPER_LDFLD)
727                                 ref->method = mono_marshal_get_ldfld_wrapper (&klass->byval_arg);
728                         else if (wrapper_type == MONO_WRAPPER_LDFLDA)
729                                 ref->method = mono_marshal_get_ldflda_wrapper (&klass->byval_arg);
730                         else if (wrapper_type == MONO_WRAPPER_STFLD)
731                                 ref->method = mono_marshal_get_stfld_wrapper (&klass->byval_arg);
732                         else if (wrapper_type == MONO_WRAPPER_ISINST)
733                                 ref->method = mono_marshal_get_isinst (klass);
734                         else
735                                 g_assert_not_reached ();
736                         break;
737                 }
738                 case MONO_WRAPPER_LDFLD_REMOTE:
739                         ref->method = mono_marshal_get_ldfld_remote_wrapper (NULL);
740                         break;
741                 case MONO_WRAPPER_STFLD_REMOTE:
742                         ref->method = mono_marshal_get_stfld_remote_wrapper (NULL);
743                         break;
744                 case MONO_WRAPPER_ALLOC: {
745                         int atype = decode_value (p, &p);
746
747                         ref->method = mono_gc_get_managed_allocator_by_type (atype);
748                         g_assert (ref->method);
749                         break;
750                 }
751                 case MONO_WRAPPER_WRITE_BARRIER:
752                         ref->method = mono_gc_get_write_barrier ();
753                         break;
754                 case MONO_WRAPPER_STELEMREF: {
755                         int subtype = decode_value (p, &p);
756
757                         if (subtype == 0) {
758                                 ref->method = mono_marshal_get_stelemref ();
759                         } else {
760                                 g_assert (subtype == MONO_AOT_WRAPPER_BY_NAME);
761                                 g_assert (target);
762                                 if (wrapper_name_matches_target (p, target))
763                                         ref->method = target;
764                                 else
765                                         return FALSE;
766                         }
767                         break;
768                 }
769                 case MONO_WRAPPER_SYNCHRONIZED: {
770                         MonoMethod *m = decode_resolve_method_ref (module, p, &p);
771
772                         if (!m)
773                                 return FALSE;
774                         ref->method = mono_marshal_get_synchronized_wrapper (m);
775                         break;
776                 }
777                 case MONO_WRAPPER_UNKNOWN: {
778                         MonoMethodDesc *desc;
779                         MonoMethod *orig_method;
780                         int subtype = decode_value (p, &p);
781
782                         if (subtype == MONO_AOT_WRAPPER_PTR_TO_STRUCTURE || subtype == MONO_AOT_WRAPPER_STRUCTURE_TO_PTR) {
783                                 MonoClass *klass = decode_klass_ref (module, p, &p);
784                                 
785                                 if (!klass)
786                                         return FALSE;
787
788                                 g_assert (target);
789                                 if (klass != target->klass)
790                                         return FALSE;
791
792                                 if (subtype == MONO_AOT_WRAPPER_PTR_TO_STRUCTURE) {
793                                         if (strcmp (target->name, "PtrToStructure"))
794                                                 return FALSE;
795                                         ref->method = mono_marshal_get_ptr_to_struct (klass);
796                                 } else {
797                                         if (strcmp (target->name, "StructureToPtr"))
798                                                 return FALSE;
799                                         ref->method = mono_marshal_get_struct_to_ptr (klass);
800                                 }
801                         } else {
802                                 if (subtype == MONO_AOT_WRAPPER_MONITOR_ENTER)
803                                         desc = mono_method_desc_new ("Monitor:Enter", FALSE);
804                                 else if (subtype == MONO_AOT_WRAPPER_MONITOR_EXIT)
805                                         desc = mono_method_desc_new ("Monitor:Exit", FALSE);
806                                 else if (subtype == MONO_AOT_WRAPPER_MONITOR_ENTER_V4)
807                                         desc = mono_method_desc_new ("Monitor:Enter(object,bool&)", FALSE);
808                                 else
809                                         g_assert_not_reached ();
810                                 orig_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
811                                 g_assert (orig_method);
812                                 mono_method_desc_free (desc);
813                                 ref->method = mono_monitor_get_fast_path (orig_method);
814                         }
815                         break;
816                 }
817                 case MONO_WRAPPER_MANAGED_TO_MANAGED: {
818                         int subtype = decode_value (p, &p);
819
820                         if (subtype == MONO_AOT_WRAPPER_ELEMENT_ADDR) {
821                                 int rank = decode_value (p, &p);
822                                 int elem_size = decode_value (p, &p);
823
824                                 ref->method = mono_marshal_get_array_address (rank, elem_size);
825                         } else {
826                                 g_assert (subtype == MONO_AOT_WRAPPER_BY_NAME);
827                                 g_assert (target);
828                                 if (wrapper_name_matches_target (p, target))
829                                         ref->method = target;
830                                 else
831                                         return FALSE;
832                         }
833                         break;
834                 }
835                 case MONO_WRAPPER_MANAGED_TO_NATIVE: {
836                         MonoMethod *m;
837                         int subtype = decode_value (p, &p);
838                         char *name;
839
840                         if (subtype == MONO_AOT_WRAPPER_JIT_ICALL) {
841                                 g_assert (target);
842
843                                 name = (char*)p;
844                                 if (strcmp (target->name, name) != 0)
845                                         return FALSE;
846                                 ref->method = target;
847                         } else {
848                                 m = decode_resolve_method_ref (module, p, &p);
849
850                                 if (!m)
851                                         return FALSE;
852
853                                 /* This should only happen when looking for an extra method */
854                                 g_assert (target);
855                                 if (mono_marshal_method_from_wrapper (target) == m)
856                                         ref->method = target;
857                                 else
858                                         return FALSE;
859                         }
860                         break;
861                 }
862                 case MONO_WRAPPER_CASTCLASS: {
863                         int subtype = decode_value (p, &p);
864
865                         if (subtype == MONO_AOT_WRAPPER_CASTCLASS_WITH_CACHE)
866                                 ref->method = mono_marshal_get_castclass_with_cache ();
867                         else if (subtype == MONO_AOT_WRAPPER_ISINST_WITH_CACHE)
868                                 ref->method = mono_marshal_get_isinst_with_cache ();
869                         else
870                                 g_assert_not_reached ();
871                         break;
872                 }
873                 case MONO_WRAPPER_RUNTIME_INVOKE: {
874                         int subtype = decode_value (p, &p);
875
876                         g_assert (target);
877
878                         if (subtype == MONO_AOT_WRAPPER_RUNTIME_INVOKE_DYNAMIC) {
879                                 if (strcmp (target->name, "runtime_invoke_dynamic") != 0)
880                                         return FALSE;
881                                 ref->method = target;
882                         } else if (subtype == MONO_AOT_WRAPPER_RUNTIME_INVOKE_DIRECT) {
883                                 /* Direct wrapper */
884                                 MonoMethod *m = decode_resolve_method_ref (module, p, &p);
885
886                                 if (!m)
887                                         return FALSE;
888                                 ref->method = mono_marshal_get_runtime_invoke (m, FALSE);
889                         } else if (subtype == MONO_AOT_WRAPPER_RUNTIME_INVOKE_VIRTUAL) {
890                                 /* Virtual direct wrapper */
891                                 MonoMethod *m = decode_resolve_method_ref (module, p, &p);
892
893                                 if (!m)
894                                         return FALSE;
895                                 ref->method = mono_marshal_get_runtime_invoke (m, TRUE);
896                         } else {
897                                 if (sig_matches_target (module, target, p, &p))
898                                         ref->method = target;
899                                 else
900                                         return FALSE;
901                         }
902                         break;
903                 }
904                 case MONO_WRAPPER_DELEGATE_INVOKE:
905                 case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE:
906                 case MONO_WRAPPER_DELEGATE_END_INVOKE: {
907                         /*
908                          * These wrappers are associated with a signature, not with a method.
909                          * Since we can't decode them into methods, they need a target method.
910                          */
911                         g_assert (target);
912
913                         if (sig_matches_target (module, target, p, &p))
914                                 ref->method = target;
915                         else
916                                 return FALSE;
917                         break;
918                 }
919                 case MONO_WRAPPER_NATIVE_TO_MANAGED: {
920                         MonoMethod *m;
921                         MonoClass *klass;
922
923                         m = decode_resolve_method_ref (module, p, &p);
924                         if (!m)
925                                 return FALSE;
926                         klass = decode_klass_ref (module, p, &p);
927                         if (!klass)
928                                 return FALSE;
929                         ref->method = mono_marshal_get_managed_wrapper (m, klass, 0);
930                         break;
931                 }
932                 default:
933                         g_assert_not_reached ();
934                 }
935         } else if (image_index == MONO_AOT_METHODREF_METHODSPEC) {
936                 image_index = decode_value (p, &p);
937                 ref->token = decode_value (p, &p);
938
939                 image = load_image (module, image_index, TRUE);
940                 if (!image)
941                         return FALSE;
942         } else if (image_index == MONO_AOT_METHODREF_GINST) {
943                 MonoClass *klass;
944                 MonoGenericContext ctx;
945
946                 /* 
947                  * These methods do not have a token which resolves them, so we 
948                  * resolve them immediately.
949                  */
950                 klass = decode_klass_ref (module, p, &p);
951                 if (!klass)
952                         return FALSE;
953
954                 if (target && target->klass != klass)
955                         return FALSE;
956
957                 image_index = decode_value (p, &p);
958                 ref->token = decode_value (p, &p);
959
960                 image = load_image (module, image_index, TRUE);
961                 if (!image)
962                         return FALSE;
963
964                 ref->method = mono_get_method_full (image, ref->token, NULL, NULL);
965                 if (!ref->method)
966                         return FALSE;
967
968                 memset (&ctx, 0, sizeof (ctx));
969
970                 if (FALSE && klass->generic_class) {
971                         ctx.class_inst = klass->generic_class->context.class_inst;
972                         ctx.method_inst = NULL;
973  
974                         ref->method = mono_class_inflate_generic_method_full (ref->method, klass, &ctx);
975                 }                       
976
977                 memset (&ctx, 0, sizeof (ctx));
978
979                 if (!decode_generic_context (module, &ctx, p, &p))
980                         return FALSE;
981
982                 ref->method = mono_class_inflate_generic_method_full (ref->method, klass, &ctx);
983         } else if (image_index == MONO_AOT_METHODREF_ARRAY) {
984                 MonoClass *klass;
985                 int method_type;
986
987                 klass = decode_klass_ref (module, p, &p);
988                 if (!klass)
989                         return FALSE;
990                 method_type = decode_value (p, &p);
991                 switch (method_type) {
992                 case 0:
993                         ref->method = mono_class_get_method_from_name (klass, ".ctor", klass->rank);
994                         break;
995                 case 1:
996                         ref->method = mono_class_get_method_from_name (klass, ".ctor", klass->rank * 2);
997                         break;
998                 case 2:
999                         ref->method = mono_class_get_method_from_name (klass, "Get", -1);
1000                         break;
1001                 case 3:
1002                         ref->method = mono_class_get_method_from_name (klass, "Address", -1);
1003                         break;
1004                 case 4:
1005                         ref->method = mono_class_get_method_from_name (klass, "Set", -1);
1006                         break;
1007                 default:
1008                         g_assert_not_reached ();
1009                 }
1010         } else {
1011                 g_assert (image_index < MONO_AOT_METHODREF_MIN);
1012                 ref->token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
1013
1014                 image = load_image (module, image_index, TRUE);
1015                 if (!image)
1016                         return FALSE;
1017         }
1018
1019         *endbuf = p;
1020
1021         ref->image = image;
1022
1023         return TRUE;
1024 }
1025
1026 static gboolean
1027 decode_method_ref (MonoAotModule *module, MethodRef *ref, guint8 *buf, guint8 **endbuf)
1028 {
1029         return decode_method_ref_with_target (module, ref, NULL, buf, endbuf);
1030 }
1031
1032 /*
1033  * decode_resolve_method_ref_with_target:
1034  *
1035  *   Similar to decode_method_ref, but resolve and return the method itself.
1036  */
1037 static MonoMethod*
1038 decode_resolve_method_ref_with_target (MonoAotModule *module, MonoMethod *target, guint8 *buf, guint8 **endbuf)
1039 {
1040         MethodRef ref;
1041         gboolean res;
1042
1043         res = decode_method_ref_with_target (module, &ref, target, buf, endbuf);
1044         if (!res)
1045                 return NULL;
1046         if (ref.method)
1047                 return ref.method;
1048         if (!ref.image)
1049                 return NULL;
1050         return mono_get_method (ref.image, ref.token, NULL);
1051 }
1052
1053 static MonoMethod*
1054 decode_resolve_method_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
1055 {
1056         return decode_resolve_method_ref_with_target (module, NULL, buf, endbuf);
1057 }
1058
1059 static void
1060 create_cache_structure (void)
1061 {
1062         const char *home;
1063         char *tmp;
1064         int err;
1065
1066         home = g_get_home_dir ();
1067         if (!home)
1068                 return;
1069
1070         tmp = g_build_filename (home, ".mono", NULL);
1071         if (!g_file_test (tmp, G_FILE_TEST_IS_DIR)) {
1072                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT creating directory %s", tmp);
1073 #ifdef HOST_WIN32
1074                 err = mkdir (tmp);
1075 #else
1076                 err = mkdir (tmp, 0777);
1077 #endif
1078                 if (err) {
1079                         mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT failed: %s", g_strerror (errno));
1080                         g_free (tmp);
1081                         return;
1082                 }
1083         }
1084         g_free (tmp);
1085         tmp = g_build_filename (home, ".mono", "aot-cache", NULL);
1086         if (!g_file_test (tmp, G_FILE_TEST_IS_DIR)) {
1087                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT creating directory %s", tmp);
1088 #ifdef HOST_WIN32
1089                 err = mkdir (tmp);
1090 #else
1091                 err = mkdir (tmp, 0777);
1092 #endif
1093                 if (err) {
1094                         mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT failed: %s", g_strerror (errno));
1095                         g_free (tmp);
1096                         return;
1097                 }
1098         }
1099         g_free (tmp);
1100 }
1101
1102 /*
1103  * load_aot_module_from_cache:
1104  *
1105  *  Experimental code to AOT compile loaded assemblies on demand. 
1106  *
1107  * FIXME: 
1108  * - Add environment variable MONO_AOT_CACHE_OPTIONS
1109  * - Add options for controlling the cache size
1110  * - Handle full cache by deleting old assemblies lru style
1111  * - Add options for excluding assemblies during development
1112  * - Maybe add a threshold after an assembly is AOT compiled
1113  * - invoking a new mono process is a security risk
1114  * - recompile the AOT module if one of its dependencies changes
1115  */
1116 static MonoDl*
1117 load_aot_module_from_cache (MonoAssembly *assembly, char **aot_name)
1118 {
1119         char *fname, *cmd, *tmp2, *aot_options;
1120         const char *home;
1121         MonoDl *module;
1122         gboolean res;
1123         gchar *out, *err;
1124         gint exit_status;
1125
1126         *aot_name = NULL;
1127
1128         if (assembly->image->dynamic)
1129                 return NULL;
1130
1131         create_cache_structure ();
1132
1133         home = g_get_home_dir ();
1134
1135         tmp2 = g_strdup_printf ("%s-%s%s", assembly->image->assembly_name, assembly->image->guid, SHARED_EXT);
1136         fname = g_build_filename (home, ".mono", "aot-cache", tmp2, NULL);
1137         *aot_name = fname;
1138         g_free (tmp2);
1139
1140         mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT trying to load from cache: '%s'.", fname);
1141         module = mono_dl_open (fname, MONO_DL_LAZY, NULL);
1142
1143         if (!module) {
1144                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT not found.");
1145
1146                 mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT precompiling assembly '%s'... ", assembly->image->name);
1147
1148                 aot_options = g_strdup_printf ("outfile=%s", fname);
1149
1150                 if (spawn_compiler) {
1151                         /* FIXME: security */
1152                         /* FIXME: Has to pass the assembly loading path to the child process */
1153                         cmd = g_strdup_printf ("mono -O=all --aot=%s %s", aot_options, assembly->image->name);
1154
1155                         res = g_spawn_command_line_sync (cmd, &out, &err, &exit_status, NULL);
1156
1157 #if !defined(HOST_WIN32) && !defined(__ppc__) && !defined(__ppc64__) && !defined(__powerpc__)
1158                         if (res) {
1159                                 if (!WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) == 0))
1160                                         mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT failed: %s.", err);
1161                                 else
1162                                         mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT succeeded.");
1163                                 g_free (out);
1164                                 g_free (err);
1165                         }
1166 #endif
1167                         g_free (cmd);
1168                 } else {
1169                         res = mono_compile_assembly (assembly, mono_parse_default_optimizations (NULL), aot_options);
1170                         if (!res) {
1171                                 mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT failed.");
1172                         } else {
1173                                 mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT succeeded.");
1174                         }
1175                 }
1176
1177                 module = mono_dl_open (fname, MONO_DL_LAZY, NULL);
1178
1179                 g_free (aot_options);
1180         }
1181
1182         return module;
1183 }
1184
1185 static void
1186 find_symbol (MonoDl *module, gpointer *globals, const char *name, gpointer *value)
1187 {
1188         if (globals) {
1189                 int global_index;
1190                 guint16 *table, *entry;
1191                 guint16 table_size;
1192                 guint32 hash;           
1193
1194                 /* The first entry points to the hash */
1195                 table = globals [0];
1196                 globals ++;
1197
1198                 table_size = table [0];
1199                 table ++;
1200
1201                 hash = mono_metadata_str_hash (name) % table_size;
1202
1203                 entry = &table [hash * 2];
1204
1205                 /* Search the hash for the index into the globals table */
1206                 global_index = -1;
1207                 while (entry [0] != 0) {
1208                         guint32 index = entry [0] - 1;
1209                         guint32 next = entry [1];
1210
1211                         //printf ("X: %s %s\n", (char*)globals [index * 2], name);
1212
1213                         if (!strcmp (globals [index * 2], name)) {
1214                                 global_index = index;
1215                                 break;
1216                         }
1217
1218                         if (next != 0) {
1219                                 entry = &table [next * 2];
1220                         } else {
1221                                 break;
1222                         }
1223                 }
1224
1225                 if (global_index != -1)
1226                         *value = globals [global_index * 2 + 1];
1227                 else
1228                         *value = NULL;
1229         } else {
1230                 char *err = mono_dl_symbol (module, name, value);
1231
1232                 if (err)
1233                         g_free (err);
1234         }
1235 }
1236
1237 static gboolean
1238 check_usable (MonoAssembly *assembly, MonoAotFileInfo *info, char **out_msg)
1239 {
1240         char *build_info;
1241         char *msg = NULL;
1242         gboolean usable = TRUE;
1243         gboolean full_aot;
1244         guint8 *blob;
1245
1246         if (strcmp (assembly->image->guid, info->assembly_guid)) {
1247                 msg = g_strdup_printf ("doesn't match assembly");
1248                 usable = FALSE;
1249         }
1250
1251         build_info = mono_get_runtime_build_info ();
1252         if (strlen (info->runtime_version) > 0 && strcmp (info->runtime_version, build_info)) {
1253                 msg = g_strdup_printf ("compiled against runtime version '%s' while this runtime has version '%s'", info->runtime_version, build_info);
1254                 usable = FALSE;
1255         }
1256         g_free (build_info);
1257
1258         full_aot = info->flags & MONO_AOT_FILE_FLAG_FULL_AOT;
1259
1260         if (mono_aot_only && !full_aot) {
1261                 msg = g_strdup_printf ("not compiled with --aot=full");
1262                 usable = FALSE;
1263         }
1264         if (!mono_aot_only && full_aot) {
1265                 msg = g_strdup_printf ("compiled with --aot=full");
1266                 usable = FALSE;
1267         }
1268 #ifdef TARGET_ARM
1269         /* mono_arch_find_imt_method () requires this */
1270         if ((info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && !mono_use_llvm) {
1271                 msg = g_strdup_printf ("compiled against LLVM");
1272                 usable = FALSE;
1273         }
1274         if (!(info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && mono_use_llvm) {
1275                 msg = g_strdup_printf ("not compiled against LLVM");
1276                 usable = FALSE;
1277         }
1278 #endif
1279         if (mini_get_debug_options ()->mdb_optimizations && !(info->flags & MONO_AOT_FILE_FLAG_DEBUG) && !full_aot) {
1280                 msg = g_strdup_printf ("not compiled for debugging");
1281                 usable = FALSE;
1282         }
1283
1284         blob = info->blob;
1285
1286         if (info->gc_name_index != -1) {
1287                 char *gc_name = (char*)&blob [info->gc_name_index];
1288                 const char *current_gc_name = mono_gc_get_gc_name ();
1289
1290                 if (strcmp (current_gc_name, gc_name) != 0) {
1291                         msg = g_strdup_printf ("compiled against GC %s, while the current runtime uses GC %s.\n", gc_name, current_gc_name);
1292                         usable = FALSE;
1293                 }
1294         }
1295
1296         *out_msg = msg;
1297         return usable;
1298 }
1299
1300 static void
1301 load_aot_module (MonoAssembly *assembly, gpointer user_data)
1302 {
1303         char *aot_name;
1304         MonoAotModule *amodule;
1305         MonoDl *sofile;
1306         gboolean usable = TRUE;
1307         char *version_symbol = NULL;
1308         char *msg = NULL;
1309         gpointer *globals = NULL;
1310         MonoAotFileInfo *info = NULL;
1311         int i, version;
1312         guint8 *blob;
1313         gboolean do_load_image = TRUE;
1314
1315         if (mono_compile_aot)
1316                 return;
1317
1318         if (assembly->image->aot_module)
1319                 /* 
1320                  * Already loaded. This can happen because the assembly loading code might invoke
1321                  * the assembly load hooks multiple times for the same assembly.
1322                  */
1323                 return;
1324
1325         if (assembly->image->dynamic)
1326                 return;
1327
1328         if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS)
1329                 return;
1330
1331         mono_aot_lock ();
1332         if (static_aot_modules)
1333                 info = g_hash_table_lookup (static_aot_modules, assembly->aname.name);
1334         else
1335                 info = NULL;
1336         mono_aot_unlock ();
1337
1338         if (info) {
1339                 /* Statically linked AOT module */
1340                 sofile = NULL;
1341                 aot_name = g_strdup_printf ("%s", assembly->aname.name);
1342                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "Found statically linked AOT module '%s'.\n", aot_name);
1343                 globals = info->globals;
1344         } else {
1345                 if (use_aot_cache)
1346                         sofile = load_aot_module_from_cache (assembly, &aot_name);
1347                 else {
1348                         char *err;
1349                         aot_name = g_strdup_printf ("%s%s", assembly->image->name, SHARED_EXT);
1350
1351                         sofile = mono_dl_open (aot_name, MONO_DL_LAZY, &err);
1352
1353                         if (!sofile) {
1354                                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT failed to load AOT module %s: %s\n", aot_name, err);
1355                                 g_free (err);
1356                         }
1357                 }
1358         }
1359
1360         if (!sofile && !globals) {
1361                 if (mono_aot_only) {
1362                         fprintf (stderr, "Failed to load AOT module '%s' in aot-only mode.\n", aot_name);
1363                         exit (1);
1364                 }
1365                 g_free (aot_name);
1366                 return;
1367         }
1368
1369         if (!info) {
1370                 find_symbol (sofile, globals, "mono_aot_version", (gpointer *) &version_symbol);
1371                 find_symbol (sofile, globals, "mono_aot_file_info", (gpointer*)&info);
1372         }
1373
1374         if (version_symbol) {
1375                 /* Old file format */
1376                 version = atoi (version_symbol);
1377         } else {
1378                 g_assert (info);
1379                 version = info->version;
1380         }
1381
1382         if (version != MONO_AOT_FILE_VERSION) {
1383                 msg = g_strdup_printf ("wrong file format version (expected %d got %d)", MONO_AOT_FILE_VERSION, version);
1384                 usable = FALSE;
1385         } else {
1386                 usable = check_usable (assembly, info, &msg);
1387         }
1388
1389         if (!usable) {
1390                 if (mono_aot_only) {
1391                         fprintf (stderr, "Failed to load AOT module '%s' while running in aot-only mode: %s.\n", aot_name, msg);
1392                         exit (1);
1393                 } else {
1394                         mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is unusable: %s.\n", aot_name, msg);
1395                 }
1396                 g_free (msg);
1397                 g_free (aot_name);
1398                 if (sofile)
1399                         mono_dl_close (sofile);
1400                 assembly->image->aot_module = NULL;
1401                 return;
1402         }
1403
1404         /* Sanity check */
1405         g_assert (info->double_align == __alignof__ (double));
1406         g_assert (info->long_align == __alignof__ (gint64));
1407
1408         blob = info->blob;
1409
1410         amodule = g_new0 (MonoAotModule, 1);
1411         amodule->aot_name = aot_name;
1412         amodule->assembly = assembly;
1413
1414         memcpy (&amodule->info, info, sizeof (*info));
1415
1416         amodule->got = amodule->info.got;
1417         amodule->got [0] = assembly->image;
1418         amodule->globals = globals;
1419         amodule->sofile = sofile;
1420         amodule->method_to_code = g_hash_table_new (mono_aligned_addr_hash, NULL);
1421         amodule->blob = blob;
1422
1423         /* Read image table */
1424         {
1425                 guint32 table_len, i;
1426                 char *table = NULL;
1427
1428                 table = info->image_table;
1429                 g_assert (table);
1430
1431                 table_len = *(guint32*)table;
1432                 table += sizeof (guint32);
1433                 amodule->image_table = g_new0 (MonoImage*, table_len);
1434                 amodule->image_names = g_new0 (MonoAssemblyName, table_len);
1435                 amodule->image_guids = g_new0 (char*, table_len);
1436                 amodule->image_table_len = table_len;
1437                 for (i = 0; i < table_len; ++i) {
1438                         MonoAssemblyName *aname = &(amodule->image_names [i]);
1439
1440                         aname->name = g_strdup (table);
1441                         table += strlen (table) + 1;
1442                         amodule->image_guids [i] = g_strdup (table);
1443                         table += strlen (table) + 1;
1444                         if (table [0] != 0)
1445                                 aname->culture = g_strdup (table);
1446                         table += strlen (table) + 1;
1447                         memcpy (aname->public_key_token, table, strlen (table) + 1);
1448                         table += strlen (table) + 1;                    
1449
1450                         table = ALIGN_PTR_TO (table, 8);
1451                         aname->flags = *(guint32*)table;
1452                         table += 4;
1453                         aname->major = *(guint32*)table;
1454                         table += 4;
1455                         aname->minor = *(guint32*)table;
1456                         table += 4;
1457                         aname->build = *(guint32*)table;
1458                         table += 4;
1459                         aname->revision = *(guint32*)table;
1460                         table += 4;
1461                 }
1462         }
1463
1464         amodule->code_offsets = info->code_offsets;
1465         amodule->code = info->methods;
1466 #ifdef TARGET_ARM
1467         /* Mask out thumb interop bit */
1468         amodule->code = (void*)((mgreg_t)amodule->code & ~1);
1469 #endif
1470         amodule->code_end = info->methods_end;
1471         amodule->method_info_offsets = info->method_info_offsets;
1472         amodule->ex_info_offsets = info->ex_info_offsets;
1473         amodule->class_info_offsets = info->class_info_offsets;
1474         amodule->class_name_table = info->class_name_table;
1475         amodule->extra_method_table = info->extra_method_table;
1476         amodule->extra_method_info_offsets = info->extra_method_info_offsets;
1477         amodule->unbox_trampolines = info->unbox_trampolines;
1478         amodule->unbox_trampolines_end = info->unbox_trampolines_end;
1479         amodule->got_info_offsets = info->got_info_offsets;
1480         amodule->unwind_info = info->unwind_info;
1481         amodule->mem_end = info->mem_end;
1482         amodule->mem_begin = amodule->code;
1483         amodule->plt = info->plt;
1484         amodule->plt_end = info->plt_end;
1485         amodule->mono_eh_frame = info->mono_eh_frame;
1486         amodule->trampolines [MONO_AOT_TRAMP_SPECIFIC] = info->specific_trampolines;
1487         amodule->trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = info->static_rgctx_trampolines;
1488         amodule->trampolines [MONO_AOT_TRAMP_IMT_THUNK] = info->imt_thunks;
1489         amodule->thumb_end = info->thumb_end;
1490
1491         if (make_unreadable) {
1492 #ifndef TARGET_WIN32
1493                 guint8 *addr;
1494                 guint8 *page_start, *page_end;
1495                 int err, len;
1496
1497                 addr = amodule->mem_begin;
1498                 len = amodule->mem_end - amodule->mem_begin;
1499
1500                 /* Round down in both directions to avoid modifying data which is not ours */
1501                 page_start = (guint8 *) (((gssize) (addr)) & ~ (mono_pagesize () - 1)) + mono_pagesize ();
1502                 page_end = (guint8 *) (((gssize) (addr + len)) & ~ (mono_pagesize () - 1));
1503                 if (page_end > page_start) {
1504                         err = mono_mprotect (page_start, (page_end - page_start), MONO_MMAP_NONE);
1505                         g_assert (err == 0);
1506                 }
1507 #endif
1508         }
1509
1510         mono_aot_lock ();
1511
1512         aot_code_low_addr = MIN (aot_code_low_addr, (gsize)amodule->code);
1513         aot_code_high_addr = MAX (aot_code_high_addr, (gsize)amodule->code_end);
1514
1515         g_hash_table_insert (aot_modules, assembly, amodule);
1516         mono_aot_unlock ();
1517
1518         mono_jit_info_add_aot_module (assembly->image, amodule->code, amodule->code_end);
1519
1520         assembly->image->aot_module = amodule;
1521
1522         if (mono_aot_only) {
1523                 if (mono_defaults.corlib) {
1524                         /* The second got slot contains the mscorlib got addr */
1525                         MonoAotModule *mscorlib_amodule = mono_defaults.corlib->aot_module;
1526
1527                         amodule->got [1] = mscorlib_amodule->got;
1528                 } else {
1529                         amodule->got [1] = amodule->got;
1530                 }
1531         }
1532
1533         if (mono_gc_is_moving ()) {
1534                 MonoJumpInfo ji;
1535
1536                 memset (&ji, 0, sizeof (ji));
1537                 ji.type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
1538
1539                 amodule->got [2] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
1540         }
1541
1542         /*
1543          * Since we store methoddef and classdef tokens when referring to methods/classes in
1544          * referenced assemblies, we depend on the exact versions of the referenced assemblies.
1545          * MS calls this 'hard binding'. This means we have to load all referenced assemblies
1546          * non-lazily, since we can't handle out-of-date errors later.
1547          * The cached class info also depends on the exact assemblies.
1548          */
1549 #if defined(__native_client__)
1550         /* TODO: Don't 'load_image' on mscorlib due to a */
1551         /* recursive loading problem.  This should be    */
1552         /* removed if mscorlib is loaded from disk.      */
1553         if (strncmp(assembly->aname.name, "mscorlib", 8)) {
1554                 do_load_image = TRUE;
1555         } else {
1556                 do_load_image = FALSE;
1557         }
1558 #endif
1559         if (do_load_image) {
1560                 for (i = 0; i < amodule->image_table_len; ++i)
1561                         load_image (amodule, i, FALSE);
1562         }
1563
1564         if (amodule->out_of_date) {
1565                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT Module %s is unusable because a dependency is out-of-date.\n", assembly->image->name);
1566                 if (mono_aot_only) {
1567                         fprintf (stderr, "Failed to load AOT module '%s' while running in aot-only mode because a dependency cannot be found or it is out of date.\n", aot_name);
1568                         exit (1);
1569                 }
1570         }
1571         else
1572                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT loaded AOT Module for %s.\n", assembly->image->name);
1573 }
1574
1575 /*
1576  * mono_aot_register_globals:
1577  *
1578  *   This is called by the ctor function in AOT images compiled with the
1579  * 'no-dlsym' option.
1580  */
1581 void
1582 mono_aot_register_globals (gpointer *globals)
1583 {
1584         g_assert_not_reached ();
1585 }
1586
1587 /*
1588  * mono_aot_register_module:
1589  *
1590  *   This should be called by embedding code to register AOT modules statically linked
1591  * into the executable. AOT_INFO should be the value of the 
1592  * 'mono_aot_module_<ASSEMBLY_NAME>_info' global symbol from the AOT module.
1593  */
1594 void
1595 mono_aot_register_module (gpointer *aot_info)
1596 {
1597         gpointer *globals;
1598         char *aname;
1599         MonoAotFileInfo *info = (gpointer)aot_info;
1600
1601         g_assert (info->version == MONO_AOT_FILE_VERSION);
1602
1603         globals = info->globals;
1604         g_assert (globals);
1605
1606         aname = info->assembly_name;
1607
1608         /* This could be called before startup */
1609         if (aot_modules)
1610                 mono_aot_lock ();
1611
1612         if (!static_aot_modules)
1613                 static_aot_modules = g_hash_table_new (g_str_hash, g_str_equal);
1614
1615         g_hash_table_insert (static_aot_modules, aname, info);
1616
1617         if (aot_modules)
1618                 mono_aot_unlock ();
1619 }
1620
1621 void
1622 mono_aot_init (void)
1623 {
1624         InitializeCriticalSection (&aot_mutex);
1625         aot_modules = g_hash_table_new (NULL, NULL);
1626
1627         mono_install_assembly_load_hook (load_aot_module, NULL);
1628
1629         if (g_getenv ("MONO_LASTAOT"))
1630                 mono_last_aot_method = atoi (g_getenv ("MONO_LASTAOT"));
1631         if (g_getenv ("MONO_AOT_CACHE"))
1632                 use_aot_cache = TRUE;
1633 }
1634
1635 void
1636 mono_aot_cleanup (void)
1637 {
1638         if (aot_jit_icall_hash)
1639                 g_hash_table_destroy (aot_jit_icall_hash);
1640         if (aot_modules)
1641                 g_hash_table_destroy (aot_modules);
1642 }
1643
1644 static gboolean
1645 decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guint8 *buf, guint8 **endbuf)
1646 {
1647         guint32 flags;
1648         MethodRef ref;
1649         gboolean res;
1650
1651         info->vtable_size = decode_value (buf, &buf);
1652         if (info->vtable_size == -1)
1653                 /* Generic type */
1654                 return FALSE;
1655         flags = decode_value (buf, &buf);
1656         info->ghcimpl = (flags >> 0) & 0x1;
1657         info->has_finalize = (flags >> 1) & 0x1;
1658         info->has_cctor = (flags >> 2) & 0x1;
1659         info->has_nested_classes = (flags >> 3) & 0x1;
1660         info->blittable = (flags >> 4) & 0x1;
1661         info->has_references = (flags >> 5) & 0x1;
1662         info->has_static_refs = (flags >> 6) & 0x1;
1663         info->no_special_static_fields = (flags >> 7) & 0x1;
1664         info->is_generic_container = (flags >> 8) & 0x1;
1665
1666         if (info->has_cctor) {
1667                 res = decode_method_ref (module, &ref, buf, &buf);
1668                 if (!res)
1669                         return FALSE;
1670                 info->cctor_token = ref.token;
1671         }
1672         if (info->has_finalize) {
1673                 res = decode_method_ref (module, &ref, buf, &buf);
1674                 if (!res)
1675                         return FALSE;
1676                 info->finalize_image = ref.image;
1677                 info->finalize_token = ref.token;
1678         }
1679
1680         info->instance_size = decode_value (buf, &buf);
1681         info->class_size = decode_value (buf, &buf);
1682         info->packing_size = decode_value (buf, &buf);
1683         info->min_align = decode_value (buf, &buf);
1684
1685         *endbuf = buf;
1686
1687         return TRUE;
1688 }       
1689
1690 gpointer
1691 mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot)
1692 {
1693         int i;
1694         MonoClass *klass = vtable->klass;
1695         MonoAotModule *amodule = klass->image->aot_module;
1696         guint8 *info, *p;
1697         MonoCachedClassInfo class_info;
1698         gboolean err;
1699         MethodRef ref;
1700         gboolean res;
1701
1702         if (MONO_CLASS_IS_INTERFACE (klass) || klass->rank || !amodule)
1703                 return NULL;
1704
1705         info = &amodule->blob [mono_aot_get_offset (amodule->class_info_offsets, mono_metadata_token_index (klass->type_token) - 1)];
1706         p = info;
1707
1708         err = decode_cached_class_info (amodule, &class_info, p, &p);
1709         if (!err)
1710                 return NULL;
1711
1712         for (i = 0; i < slot; ++i)
1713                 decode_method_ref (amodule, &ref, p, &p);
1714
1715         res = decode_method_ref (amodule, &ref, p, &p);
1716         if (!res)
1717                 return NULL;
1718         if (ref.no_aot_trampoline)
1719                 return NULL;
1720
1721         if (mono_metadata_token_index (ref.token) == 0)
1722                 return NULL;
1723
1724         return mono_aot_get_method_from_token (domain, ref.image, ref.token);
1725 }
1726
1727 gboolean
1728 mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
1729 {
1730         MonoAotModule *amodule = klass->image->aot_module;
1731         guint8 *p;
1732         gboolean err;
1733
1734         if (klass->rank || !amodule)
1735                 return FALSE;
1736
1737         p = (guint8*)&amodule->blob [mono_aot_get_offset (amodule->class_info_offsets, mono_metadata_token_index (klass->type_token) - 1)];
1738
1739         err = decode_cached_class_info (amodule, res, p, &p);
1740         if (!err)
1741                 return FALSE;
1742
1743         return TRUE;
1744 }
1745
1746 /**
1747  * mono_aot_get_class_from_name:
1748  *
1749  *  Obtains a MonoClass with a given namespace and a given name which is located in IMAGE,
1750  * using a cache stored in the AOT file.
1751  * Stores the resulting class in *KLASS if found, stores NULL otherwise.
1752  *
1753  * Returns: TRUE if the klass was found/not found in the cache, FALSE if no aot file was 
1754  * found.
1755  */
1756 gboolean
1757 mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const char *name, MonoClass **klass)
1758 {
1759         MonoAotModule *amodule = image->aot_module;
1760         guint16 *table, *entry;
1761         guint16 table_size;
1762         guint32 hash;
1763         char full_name_buf [1024];
1764         char *full_name;
1765         const char *name2, *name_space2;
1766         MonoTableInfo  *t;
1767         guint32 cols [MONO_TYPEDEF_SIZE];
1768         GHashTable *nspace_table;
1769
1770         if (!amodule || !amodule->class_name_table)
1771                 return FALSE;
1772
1773         mono_aot_lock ();
1774
1775         *klass = NULL;
1776
1777         /* First look in the cache */
1778         if (!amodule->name_cache)
1779                 amodule->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
1780         nspace_table = g_hash_table_lookup (amodule->name_cache, name_space);
1781         if (nspace_table) {
1782                 *klass = g_hash_table_lookup (nspace_table, name);
1783                 if (*klass) {
1784                         mono_aot_unlock ();
1785                         return TRUE;
1786                 }
1787         }
1788
1789         table_size = amodule->class_name_table [0];
1790         table = amodule->class_name_table + 1;
1791
1792         if (name_space [0] == '\0')
1793                 full_name = g_strdup_printf ("%s", name);
1794         else {
1795                 if (strlen (name_space) + strlen (name) < 1000) {
1796                         sprintf (full_name_buf, "%s.%s", name_space, name);
1797                         full_name = full_name_buf;
1798                 } else {
1799                         full_name = g_strdup_printf ("%s.%s", name_space, name);
1800                 }
1801         }
1802         hash = mono_metadata_str_hash (full_name) % table_size;
1803         if (full_name != full_name_buf)
1804                 g_free (full_name);
1805
1806         entry = &table [hash * 2];
1807
1808         if (entry [0] != 0) {
1809                 t = &image->tables [MONO_TABLE_TYPEDEF];
1810
1811                 while (TRUE) {
1812                         guint32 index = entry [0];
1813                         guint32 next = entry [1];
1814                         guint32 token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, index);
1815
1816                         name_table_accesses ++;
1817
1818                         mono_metadata_decode_row (t, index - 1, cols, MONO_TYPEDEF_SIZE);
1819
1820                         name2 = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
1821                         name_space2 = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
1822
1823                         if (!strcmp (name, name2) && !strcmp (name_space, name_space2)) {
1824                                 mono_aot_unlock ();
1825                                 *klass = mono_class_get (image, token);
1826
1827                                 /* Add to cache */
1828                                 if (*klass) {
1829                                         mono_aot_lock ();
1830                                         nspace_table = g_hash_table_lookup (amodule->name_cache, name_space);
1831                                         if (!nspace_table) {
1832                                                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
1833                                                 g_hash_table_insert (amodule->name_cache, (char*)name_space2, nspace_table);
1834                                         }
1835                                         g_hash_table_insert (nspace_table, (char*)name2, *klass);
1836                                         mono_aot_unlock ();
1837                                 }
1838                                 return TRUE;
1839                         }
1840
1841                         if (next != 0) {
1842                                 entry = &table [next * 2];
1843                         } else {
1844                                 break;
1845                         }
1846                 }
1847         }
1848
1849         mono_aot_unlock ();
1850         
1851         return TRUE;
1852 }
1853
1854 /*
1855  * decode_mono_eh_frame:
1856  *
1857  *   Decode the EH information emitted by our modified LLVM compiler and construct a
1858  * MonoJitInfo structure from it.
1859  * LOCKING: Acquires the domain lock.
1860  */
1861 static MonoJitInfo*
1862 decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain, 
1863                                                    MonoMethod *method, guint8 *code, 
1864                                                    MonoJitExceptionInfo *clauses, int num_clauses,
1865                                                    int extra_size, GSList **nesting,
1866                                                    int *this_reg, int *this_offset)
1867 {
1868         guint8 *p;
1869         guint8 *fde, *cie, *code_start, *code_end;
1870         int version, fde_count;
1871         gint32 *table;
1872         int i, j, pos, left, right, offset, offset1, offset2, code_len;
1873         MonoJitExceptionInfo *ei;
1874         guint32 fde_len, ei_len, nested_len, nindex;
1875         gpointer *type_info;
1876         MonoJitInfo *jinfo;
1877         MonoLLVMFDEInfo info;
1878
1879         g_assert (amodule->mono_eh_frame);
1880
1881         p = amodule->mono_eh_frame;
1882
1883         /* p points to data emitted by LLVM in DwarfException::EmitMonoEHFrame () */
1884
1885         /* Header */
1886         version = *p;
1887         g_assert (version == 1);
1888         p ++;
1889         p = ALIGN_PTR_TO (p, 4);
1890
1891         fde_count = *(guint32*)p;
1892         p += 4;
1893         table = (gint32*)p;
1894
1895         /* There is +1 entry in the table */
1896         cie = p + ((fde_count + 1) * 8);
1897
1898         /* Binary search in the table to find the entry for code */
1899         offset = code - amodule->mono_eh_frame;
1900
1901         left = 0;
1902         right = fde_count;
1903         while (TRUE) {
1904                 pos = (left + right) / 2;
1905
1906                 offset1 = table [(pos * 2)];
1907                 if (pos + 1 == fde_count)
1908                         /* FIXME: */
1909                         offset2 = amodule->code_end - amodule->code;
1910                 else
1911                         offset2 = table [(pos + 1) * 2];
1912
1913                 if (offset < offset1)
1914                         right = pos;
1915                 else if (offset >= offset2)
1916                         left = pos + 1;
1917                 else
1918                         break;
1919         }
1920
1921         code_start = amodule->mono_eh_frame + table [(pos * 2)];
1922         /* This won't overflow because there is +1 entry in the table */
1923         code_end = amodule->mono_eh_frame + table [(pos * 2) + 2];
1924         code_len = code_end - code_start;
1925
1926         g_assert (code >= code_start && code < code_end);
1927
1928         fde = amodule->mono_eh_frame + table [(pos * 2) + 1];   
1929         /* This won't overflow because there is +1 entry in the table */
1930         fde_len = table [(pos * 2) + 2 + 1] - table [(pos * 2) + 1];
1931
1932         mono_unwind_decode_llvm_mono_fde (fde, fde_len, cie, code_start, &info);
1933         ei = info.ex_info;
1934         ei_len = info.ex_info_len;
1935         type_info = info.type_info;
1936         *this_reg = info.this_reg;
1937         *this_offset = info.this_offset;
1938
1939         /* Count number of nested clauses */
1940         nested_len = 0;
1941         for (i = 0; i < ei_len; ++i) {
1942                 /* This might be unaligned */
1943                 gint32 cindex1 = read32 (type_info [i]);
1944                 GSList *l;
1945
1946                 for (l = nesting [cindex1]; l; l = l->next) {
1947                         gint32 nesting_cindex = GPOINTER_TO_INT (l->data);
1948
1949                         for (j = 0; j < ei_len; ++j) {
1950                                 gint32 cindex2 = read32 (type_info [j]);
1951
1952                                 if (cindex2 == nesting_cindex)
1953                                         nested_len ++;
1954                         }
1955                 }
1956         }
1957
1958         /*
1959          * LLVM might represent one IL region with multiple regions, so have to
1960          * allocate a new JI.
1961          */
1962         jinfo = 
1963                 mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO + (sizeof (MonoJitExceptionInfo) * (ei_len + nested_len)) + extra_size);
1964
1965         jinfo->code_size = code_len;
1966         jinfo->used_regs = mono_cache_unwind_info (info.unw_info, info.unw_info_len);
1967         jinfo->method = method;
1968         jinfo->code_start = code;
1969         jinfo->domain_neutral = 0;
1970         /* This signals that used_regs points to a normal cached unwind info */
1971         jinfo->from_aot = 0;
1972         jinfo->num_clauses = ei_len + nested_len;
1973
1974         for (i = 0; i < ei_len; ++i) {
1975                 /*
1976                  * orig_jinfo contains the original IL exception info saved by the AOT
1977                  * compiler, we have to combine that with the information produced by LLVM
1978                  */
1979                 /* The type_info entries contain IL clause indexes */
1980                 int clause_index = read32 (type_info [i]);
1981                 MonoJitExceptionInfo *jei = &jinfo->clauses [i];
1982                 MonoJitExceptionInfo *orig_jei = &clauses [clause_index];
1983
1984                 g_assert (clause_index < num_clauses);
1985                 jei->flags = orig_jei->flags;
1986                 jei->data.catch_class = orig_jei->data.catch_class;
1987
1988                 jei->try_start = ei [i].try_start;
1989                 jei->try_end = ei [i].try_end;
1990                 jei->handler_start = ei [i].handler_start;
1991
1992                 /* Make sure we transition to thumb when a handler starts */
1993                 if (amodule->thumb_end && (guint8*)jei->handler_start < amodule->thumb_end)
1994                         jei->handler_start = (void*)((mgreg_t)jei->handler_start + 1);
1995         }
1996
1997         /* See exception_cb () in mini-llvm.c as to why this is needed */
1998         nindex = ei_len;
1999         for (i = 0; i < ei_len; ++i) {
2000                 gint32 cindex1 = read32 (type_info [i]);
2001                 GSList *l;
2002
2003                 for (l = nesting [cindex1]; l; l = l->next) {
2004                         gint32 nesting_cindex = GPOINTER_TO_INT (l->data);
2005
2006                         for (j = 0; j < ei_len; ++j) {
2007                                 gint32 cindex2 = read32 (type_info [j]);
2008
2009                                 if (cindex2 == nesting_cindex) {
2010                                         /* 
2011                                          * The try interval comes from the nested clause, everything else from the
2012                                          * nesting clause.
2013                                          */
2014                                         memcpy (&jinfo->clauses [nindex], &jinfo->clauses [j], sizeof (MonoJitExceptionInfo));
2015                                         jinfo->clauses [nindex].try_start = jinfo->clauses [i].try_start;
2016                                         jinfo->clauses [nindex].try_end = jinfo->clauses [i].try_end;
2017                                         nindex ++;
2018                                 }
2019                         }
2020                 }
2021         }
2022         g_assert (nindex == ei_len + nested_len);
2023
2024         return jinfo;
2025 }
2026
2027 /*
2028  * LOCKING: Acquires the domain lock.
2029  */
2030 static MonoJitInfo*
2031 decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, 
2032                                                          MonoMethod *method, guint8* ex_info, guint8 *addr,
2033                                                          guint8 *code, guint32 code_len)
2034 {
2035         int i, buf_len, num_clauses;
2036         MonoJitInfo *jinfo;
2037         guint used_int_regs, flags;
2038         gboolean has_generic_jit_info, has_dwarf_unwind_info, has_clauses, has_seq_points, has_try_block_holes;
2039         gboolean from_llvm, has_gc_map;
2040         guint8 *p;
2041         int generic_info_size, try_holes_info_size, num_holes, this_reg = 0, this_offset = 0;
2042
2043         /* Load the method info from the AOT file */
2044
2045         p = ex_info;
2046         flags = decode_value (p, &p);
2047         has_generic_jit_info = (flags & 1) != 0;
2048         has_dwarf_unwind_info = (flags & 2) != 0;
2049         has_clauses = (flags & 4) != 0;
2050         has_seq_points = (flags & 8) != 0;
2051         from_llvm = (flags & 16) != 0;
2052         has_try_block_holes = (flags & 32) != 0;
2053         has_gc_map = (flags & 64) != 0;
2054
2055         if (has_dwarf_unwind_info) {
2056                 guint32 offset;
2057
2058                 offset = decode_value (p, &p);
2059                 g_assert (offset < (1 << 30));
2060                 used_int_regs = offset;
2061         } else {
2062                 used_int_regs = decode_value (p, &p);
2063         }
2064         if (has_generic_jit_info)
2065                 generic_info_size = sizeof (MonoGenericJitInfo);
2066         else
2067                 generic_info_size = 0;
2068
2069         if (has_try_block_holes) {
2070                 num_holes = decode_value (p, &p);
2071                 try_holes_info_size = sizeof (MonoTryBlockHoleTableJitInfo) + num_holes * sizeof (MonoTryBlockHoleJitInfo);
2072         } else {
2073                 num_holes = try_holes_info_size = 0;
2074         }
2075         /* Exception table */
2076         if (has_clauses)
2077                 num_clauses = decode_value (p, &p);
2078         else
2079                 num_clauses = 0;
2080
2081         if (from_llvm) {
2082                 MonoJitExceptionInfo *clauses;
2083                 GSList **nesting;
2084
2085                 /*
2086                  * Part of the info is encoded by the AOT compiler, the rest is in the .eh_frame
2087                  * section.
2088                  */
2089                 clauses = g_new0 (MonoJitExceptionInfo, num_clauses);
2090                 nesting = g_new0 (GSList*, num_clauses);
2091
2092                 for (i = 0; i < num_clauses; ++i) {
2093                         MonoJitExceptionInfo *ei = &clauses [i];
2094
2095                         ei->flags = decode_value (p, &p);
2096
2097                         if (decode_value (p, &p))
2098                                 ei->data.catch_class = decode_klass_ref (amodule, p, &p);
2099
2100                         /* Read the list of nesting clauses */
2101                         while (TRUE) {
2102                                 int nesting_index = decode_value (p, &p);
2103                                 if (nesting_index == -1)
2104                                         break;
2105                                 nesting [i] = g_slist_prepend (nesting [i], GINT_TO_POINTER (nesting_index));
2106                         }
2107                 }
2108
2109                 jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, clauses, num_clauses, generic_info_size + try_holes_info_size, nesting, &this_reg, &this_offset);
2110                 jinfo->from_llvm = 1;
2111
2112                 g_free (clauses);
2113                 for (i = 0; i < num_clauses; ++i)
2114                         g_slist_free (nesting [i]);
2115                 g_free (nesting);
2116         } else {
2117                 jinfo = 
2118                         mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO + (sizeof (MonoJitExceptionInfo) * num_clauses) + generic_info_size + try_holes_info_size);
2119                 jinfo->num_clauses = num_clauses;
2120
2121                 for (i = 0; i < jinfo->num_clauses; ++i) {
2122                         MonoJitExceptionInfo *ei = &jinfo->clauses [i];
2123
2124                         ei->flags = decode_value (p, &p);
2125
2126                         ei->exvar_offset = decode_value (p, &p);
2127
2128                         if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER || ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)
2129                                 ei->data.filter = code + decode_value (p, &p);
2130                         else {
2131                                 if (decode_value (p, &p))
2132                                         ei->data.catch_class = decode_klass_ref (amodule, p, &p);
2133                         }
2134
2135                         ei->try_start = code + decode_value (p, &p);
2136                         ei->try_end = code + decode_value (p, &p);
2137                         ei->handler_start = code + decode_value (p, &p);
2138                 }
2139
2140                 jinfo->code_size = code_len;
2141                 jinfo->used_regs = used_int_regs;
2142                 jinfo->method = method;
2143                 jinfo->code_start = code;
2144                 jinfo->domain_neutral = 0;
2145                 jinfo->from_aot = 1;
2146         }
2147
2148         if (has_generic_jit_info) {
2149                 MonoGenericJitInfo *gi;
2150
2151                 jinfo->has_generic_jit_info = 1;
2152
2153                 gi = mono_jit_info_get_generic_jit_info (jinfo);
2154                 g_assert (gi);
2155
2156                 if (from_llvm) {
2157                         gi->has_this = this_reg != -1;
2158                         gi->this_reg = this_reg;
2159                         gi->this_offset = this_offset;
2160                 } else {
2161                         gi->has_this = decode_value (p, &p);
2162                         gi->this_reg = decode_value (p, &p);
2163                         gi->this_offset = decode_value (p, &p);
2164                 }
2165
2166                 /* This currently contains no data */
2167                 gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
2168
2169                 jinfo->method = decode_resolve_method_ref (amodule, p, &p);
2170         }
2171
2172         if (has_try_block_holes) {
2173                 MonoTryBlockHoleTableJitInfo *table;
2174
2175                 jinfo->has_try_block_holes = 1;
2176
2177                 table = mono_jit_info_get_try_block_hole_table_info (jinfo);
2178                 g_assert (table);
2179
2180                 table->num_holes = (guint16)num_holes;
2181                 for (i = 0; i < num_holes; ++i) {
2182                         MonoTryBlockHoleJitInfo *hole = &table->holes [i];
2183                         hole->clause = decode_value (p, &p);
2184                         hole->length = decode_value (p, &p);
2185                         hole->offset = decode_value (p, &p);
2186                 }
2187         }
2188
2189         if (has_seq_points) {
2190                 MonoSeqPointInfo *seq_points;
2191                 int il_offset, native_offset, last_il_offset, last_native_offset, j;
2192
2193                 int len = decode_value (p, &p);
2194
2195                 seq_points = g_malloc0 (sizeof (MonoSeqPointInfo) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (SeqPoint));
2196                 seq_points->len = len;
2197                 last_il_offset = last_native_offset = 0;
2198                 for (i = 0; i < len; ++i) {
2199                         SeqPoint *sp = &seq_points->seq_points [i];
2200                         il_offset = last_il_offset + decode_value (p, &p);
2201                         native_offset = last_native_offset + decode_value (p, &p);
2202
2203                         sp->il_offset = il_offset;
2204                         sp->native_offset = native_offset;
2205                         
2206                         sp->next_len = decode_value (p, &p);
2207                         sp->next = g_new (int, sp->next_len);
2208                         for (j = 0; j < sp->next_len; ++j)
2209                                 sp->next [j] = decode_value (p, &p);
2210
2211                         last_il_offset = il_offset;
2212                         last_native_offset = native_offset;
2213                 }
2214
2215                 mono_domain_lock (domain);
2216                 g_hash_table_insert (domain_jit_info (domain)->seq_points, method, seq_points);
2217                 mono_domain_unlock (domain);
2218         }
2219
2220         /* Load debug info */
2221         buf_len = decode_value (p, &p);
2222         mono_debug_add_aot_method (domain, method, code, p, buf_len);
2223         p += buf_len;
2224
2225         if (has_gc_map) {
2226                 int map_size = decode_value (p, &p);
2227                 /* The GC map requires 4 bytes of alignment */
2228                 while ((guint64)(gsize)p % 4)
2229                         p ++;           
2230                 jinfo->gc_info = p;
2231                 p += map_size;
2232         }
2233
2234         if (amodule != jinfo->method->klass->image->aot_module) {
2235                 mono_aot_lock ();
2236                 if (!ji_to_amodule)
2237                         ji_to_amodule = g_hash_table_new (NULL, NULL);
2238                 g_hash_table_insert (ji_to_amodule, jinfo, amodule);
2239                 mono_aot_unlock ();             
2240         }
2241
2242         return jinfo;
2243 }
2244
2245 /*
2246  * mono_aot_get_unwind_info:
2247  *
2248  *   Return a pointer to the DWARF unwind info belonging to JI.
2249  */
2250 guint8*
2251 mono_aot_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
2252 {
2253         MonoAotModule *amodule = ji->method->klass->image->aot_module;
2254         guint8 *p;
2255         guint8 *code = ji->code_start;
2256
2257         g_assert (amodule);
2258         g_assert (ji->from_aot);
2259
2260         if (!(code >= amodule->code && code <= amodule->code_end)) {
2261                 /* ji belongs to a different aot module than amodule */
2262                 mono_aot_lock ();
2263                 g_assert (ji_to_amodule);
2264                 amodule = g_hash_table_lookup (ji_to_amodule, ji);
2265                 g_assert (amodule);
2266                 g_assert (code >= amodule->code && code <= amodule->code_end);
2267                 mono_aot_unlock ();
2268         }
2269
2270         p = amodule->unwind_info + ji->used_regs;
2271         *unwind_info_len = decode_value (p, &p);
2272         return p;
2273 }
2274
2275 static G_GNUC_UNUSED int
2276 compare_ints (const void *a, const void *b)
2277 {
2278         return *(gint32*)a - *(gint32*)b;
2279 }
2280
2281 static void
2282 msort_code_offsets_internal (gint32 *array, int lo, int hi, gint32 *scratch)
2283 {
2284         int mid = (lo + hi) / 2;
2285         int i, t_lo, t_hi;
2286
2287         if (lo >= hi)
2288                 return;
2289
2290         if (hi - lo < 32) {
2291                 for (i = lo; i < hi; ++i)
2292                         if (array [(i * 2)] > array [(i * 2) + 2])
2293                                 break;
2294                 if (i == hi)
2295                         /* Already sorted */
2296                         return;
2297         }
2298
2299         msort_code_offsets_internal (array, lo, mid, scratch);
2300         msort_code_offsets_internal (array, mid + 1, hi, scratch);
2301
2302         if (array [mid * 2] < array [(mid + 1) * 2])
2303                 return;
2304
2305         /* Merge */
2306         t_lo = lo;
2307         t_hi = mid + 1;
2308         for (i = lo; i <= hi; i ++) {
2309                 if (t_lo <= mid && ((t_hi > hi) || array [t_lo * 2] < array [t_hi * 2])) {
2310                         scratch [(i * 2)] = array [t_lo * 2];
2311                         scratch [(i * 2) + 1] = array [(t_lo *2) + 1];
2312                         t_lo ++;
2313                 } else {
2314                         scratch [(i * 2)] = array [t_hi * 2];
2315                         scratch [(i * 2) + 1] = array [(t_hi *2) + 1];
2316                         t_hi ++;
2317                 }
2318         }
2319         for (i = lo; i <= hi; ++i) {
2320                 array [(i * 2)] = scratch [i * 2];
2321                 array [(i * 2) + 1] = scratch [(i * 2) + 1];
2322         }
2323 }
2324
2325 static void
2326 msort_code_offsets (gint32 *array, int len)
2327 {
2328         gint32 *scratch;
2329
2330         scratch = g_new (gint32, len * 2);
2331         msort_code_offsets_internal (array, 0, len - 1, scratch);
2332         g_free (scratch);
2333 }
2334
2335 MonoJitInfo *
2336 mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
2337 {
2338         int pos, left, right, offset, offset1, offset2, code_len;
2339         int method_index, table_len, is_wrapper;
2340         guint32 token;
2341         MonoAotModule *amodule = image->aot_module;
2342         MonoMethod *method;
2343         MonoJitInfo *jinfo;
2344         guint8 *code, *ex_info, *p;
2345         guint32 *table;
2346         int nmethods = amodule->info.nmethods;
2347         gint32 *code_offsets;
2348         int offsets_len, i;
2349
2350         if (!amodule)
2351                 return NULL;
2352
2353         if (domain != mono_get_root_domain ())
2354                 /* FIXME: */
2355                 return NULL;
2356
2357         offset = (guint8*)addr - amodule->code;
2358
2359         /* Compute a sorted table mapping code offsets to method indexes. */
2360         if (!amodule->sorted_code_offsets) {
2361                 code_offsets = g_new0 (gint32, nmethods * 2);
2362                 offsets_len = 0;
2363                 for (i = 0; i < nmethods; ++i) {
2364                         /* Skip the -1 entries to speed up sorting */
2365                         if (amodule->code_offsets [i] == 0xffffffff)
2366                                 continue;
2367                         code_offsets [(offsets_len * 2)] = amodule->code_offsets [i];
2368                         code_offsets [(offsets_len *2) + 1] = i;
2369                         offsets_len ++;
2370                 }
2371                 /* Use a merge sort as this is mostly sorted */
2372                 msort_code_offsets (code_offsets, offsets_len);
2373                 //qsort (code_offsets, offsets_len, sizeof (gint32) * 2, compare_ints);
2374                 for (i = 0; i < offsets_len -1; ++i)
2375                         g_assert (code_offsets [(i * 2)] <= code_offsets [(i + 1) * 2]);
2376
2377                 if (InterlockedCompareExchangePointer ((gpointer*)&amodule->sorted_code_offsets, code_offsets, NULL) != NULL)
2378                         /* Somebody got in before us */
2379                         g_free (code_offsets);
2380                 amodule->sorted_code_offsets_len = offsets_len;
2381         }
2382
2383         code_offsets = amodule->sorted_code_offsets;
2384         offsets_len = amodule->sorted_code_offsets_len;
2385
2386         /* Binary search in the sorted_code_offsets table */
2387         left = 0;
2388         right = offsets_len;
2389         while (TRUE) {
2390                 pos = (left + right) / 2;
2391
2392                 offset1 = code_offsets [(pos * 2)];
2393                 if (pos + 1 == offsets_len)
2394                         offset2 = amodule->code_end - amodule->code;
2395                 else
2396                         offset2 = code_offsets [(pos + 1) * 2];
2397
2398                 if (offset < offset1)
2399                         right = pos;
2400                 else if (offset >= offset2)
2401                         left = pos + 1;
2402                 else
2403                         break;
2404         }
2405
2406         g_assert (offset >= code_offsets [(pos * 2)]);
2407         if (pos + 1 < offsets_len)
2408                 g_assert (offset < code_offsets [((pos + 1) * 2)]);
2409         method_index = code_offsets [(pos * 2) + 1];
2410
2411         code = &amodule->code [amodule->code_offsets [method_index]];
2412         ex_info = &amodule->blob [mono_aot_get_offset (amodule->ex_info_offsets, method_index)];
2413
2414         if (pos == offsets_len - 1)
2415                 code_len = amodule->code_end - code;
2416         else
2417                 code_len = code_offsets [(pos + 1) * 2] - code_offsets [pos * 2];
2418
2419         g_assert ((guint8*)code <= (guint8*)addr && (guint8*)addr < (guint8*)code + code_len);
2420
2421         /* Might be a wrapper/extra method */
2422         if (amodule->extra_methods) {
2423                 mono_aot_lock ();
2424                 method = g_hash_table_lookup (amodule->extra_methods, GUINT_TO_POINTER (method_index));
2425                 mono_aot_unlock ();
2426         } else {
2427                 method = NULL;
2428         }
2429
2430         if (!method) {
2431                 if (method_index >= image->tables [MONO_TABLE_METHOD].rows) {
2432                         /* 
2433                          * This is hit for extra methods which are called directly, so they are
2434                          * not in amodule->extra_methods.
2435                          */
2436                         table_len = amodule->extra_method_info_offsets [0];
2437                         table = amodule->extra_method_info_offsets + 1;
2438                         left = 0;
2439                         right = table_len;
2440                         pos = 0;
2441
2442                         /* Binary search */
2443                         while (TRUE) {
2444                                 pos = ((left + right) / 2);
2445
2446                                 g_assert (pos < table_len);
2447
2448                                 if (table [pos * 2] < method_index)
2449                                         left = pos + 1;
2450                                 else if (table [pos * 2] > method_index)
2451                                         right = pos;
2452                                 else
2453                                         break;
2454                         }
2455
2456                         p = amodule->blob + table [(pos * 2) + 1];
2457                         is_wrapper = decode_value (p, &p);
2458                         g_assert (!is_wrapper);
2459                         method = decode_resolve_method_ref (amodule, p, &p);
2460                         g_assert (method);
2461                 } else {
2462                         token = mono_metadata_make_token (MONO_TABLE_METHOD, method_index + 1);
2463                         method = mono_get_method (image, token, NULL);
2464                 }
2465         }
2466
2467         /* FIXME: */
2468         g_assert (method);
2469
2470         //printf ("F: %s\n", mono_method_full_name (method, TRUE));
2471         
2472         jinfo = decode_exception_debug_info (amodule, domain, method, ex_info, addr, code, code_len);
2473
2474         g_assert ((guint8*)addr >= (guint8*)jinfo->code_start);
2475         g_assert ((guint8*)addr < (guint8*)jinfo->code_start + jinfo->code_size);
2476
2477         /* Add it to the normal JitInfo tables */
2478         mono_jit_info_table_add (domain, jinfo);
2479         
2480         return jinfo;
2481 }
2482
2483 static gboolean
2484 decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guint8 *buf, guint8 **endbuf)
2485 {
2486         guint8 *p = buf;
2487         gpointer *table;
2488         MonoImage *image;
2489         int i;
2490
2491         switch (ji->type) {
2492         case MONO_PATCH_INFO_METHOD:
2493         case MONO_PATCH_INFO_METHOD_JUMP:
2494         case MONO_PATCH_INFO_ICALL_ADDR:
2495         case MONO_PATCH_INFO_METHOD_RGCTX: {
2496                 MethodRef ref;
2497                 gboolean res;
2498
2499                 res = decode_method_ref (aot_module, &ref, p, &p);
2500                 if (!res)
2501                         goto cleanup;
2502
2503                 if (!ref.method && !mono_aot_only && !ref.no_aot_trampoline && (ji->type == MONO_PATCH_INFO_METHOD) && (mono_metadata_token_table (ref.token) == MONO_TABLE_METHOD)) {
2504                         ji->data.target = mono_create_ftnptr (mono_domain_get (), mono_create_jit_trampoline_from_token (ref.image, ref.token));
2505                         ji->type = MONO_PATCH_INFO_ABS;
2506                 }
2507                 else {
2508                         if (ref.method)
2509                                 ji->data.method = ref.method;
2510                         else
2511                                 ji->data.method = mono_get_method (ref.image, ref.token, NULL);
2512                         g_assert (ji->data.method);
2513                         mono_class_init (ji->data.method->klass);
2514                 }
2515                 break;
2516         }
2517         case MONO_PATCH_INFO_INTERNAL_METHOD:
2518         case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
2519                 guint32 len = decode_value (p, &p);
2520
2521                 ji->data.name = (char*)p;
2522                 p += len + 1;
2523                 break;
2524         }
2525         case MONO_PATCH_INFO_METHODCONST:
2526                 /* Shared */
2527                 ji->data.method = decode_resolve_method_ref (aot_module, p, &p);
2528                 if (!ji->data.method)
2529                         goto cleanup;
2530                 break;
2531         case MONO_PATCH_INFO_VTABLE:
2532         case MONO_PATCH_INFO_CLASS:
2533         case MONO_PATCH_INFO_IID:
2534         case MONO_PATCH_INFO_ADJUSTED_IID:
2535                 /* Shared */
2536                 ji->data.klass = decode_klass_ref (aot_module, p, &p);
2537                 if (!ji->data.klass)
2538                         goto cleanup;
2539                 break;
2540         case MONO_PATCH_INFO_CLASS_INIT:
2541         case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
2542                 ji->data.klass = decode_klass_ref (aot_module, p, &p);
2543                 if (!ji->data.klass)
2544                         goto cleanup;
2545                 break;
2546         case MONO_PATCH_INFO_IMAGE:
2547                 ji->data.image = load_image (aot_module, decode_value (p, &p), TRUE);
2548                 if (!ji->data.image)
2549                         goto cleanup;
2550                 break;
2551         case MONO_PATCH_INFO_FIELD:
2552         case MONO_PATCH_INFO_SFLDA:
2553                 /* Shared */
2554                 ji->data.field = decode_field_info (aot_module, p, &p);
2555                 if (!ji->data.field)
2556                         goto cleanup;
2557                 break;
2558         case MONO_PATCH_INFO_SWITCH:
2559                 ji->data.table = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoBBTable));
2560                 ji->data.table->table_size = decode_value (p, &p);
2561                 table = mono_domain_alloc (mono_domain_get (), sizeof (gpointer) * ji->data.table->table_size);
2562                 ji->data.table->table = (MonoBasicBlock**)table;
2563                 for (i = 0; i < ji->data.table->table_size; i++)
2564                         table [i] = (gpointer)(gssize)decode_value (p, &p);
2565                 break;
2566         case MONO_PATCH_INFO_R4: {
2567                 guint32 val;
2568                 
2569                 ji->data.target = mono_domain_alloc0 (mono_domain_get (), sizeof (float));
2570                 val = decode_value (p, &p);
2571                 *(float*)ji->data.target = *(float*)&val;
2572                 break;
2573         }
2574         case MONO_PATCH_INFO_R8: {
2575                 guint32 val [2];
2576                 guint64 v;
2577
2578                 ji->data.target = mono_domain_alloc0 (mono_domain_get (), sizeof (double));
2579
2580                 val [0] = decode_value (p, &p);
2581                 val [1] = decode_value (p, &p);
2582                 v = ((guint64)val [1] << 32) | ((guint64)val [0]);
2583                 *(double*)ji->data.target = *(double*)&v;
2584                 break;
2585         }
2586         case MONO_PATCH_INFO_LDSTR:
2587                 image = load_image (aot_module, decode_value (p, &p), TRUE);
2588                 if (!image)
2589                         goto cleanup;
2590                 ji->data.token = mono_jump_info_token_new (mp, image, MONO_TOKEN_STRING + decode_value (p, &p));
2591                 break;
2592         case MONO_PATCH_INFO_RVA:
2593         case MONO_PATCH_INFO_DECLSEC:
2594         case MONO_PATCH_INFO_LDTOKEN:
2595         case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
2596                 /* Shared */
2597                 image = load_image (aot_module, decode_value (p, &p), TRUE);
2598                 if (!image)
2599                         goto cleanup;
2600                 ji->data.token = mono_jump_info_token_new (mp, image, decode_value (p, &p));
2601
2602                 ji->data.token->has_context = decode_value (p, &p);
2603                 if (ji->data.token->has_context) {
2604                         gboolean res = decode_generic_context (aot_module, &ji->data.token->context, p, &p);
2605                         if (!res)
2606                                 goto cleanup;
2607                 }
2608                 break;
2609         case MONO_PATCH_INFO_EXC_NAME:
2610                 ji->data.klass = decode_klass_ref (aot_module, p, &p);
2611                 if (!ji->data.klass)
2612                         goto cleanup;
2613                 ji->data.name = ji->data.klass->name;
2614                 break;
2615         case MONO_PATCH_INFO_METHOD_REL:
2616                 ji->data.offset = decode_value (p, &p);
2617                 break;
2618         case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
2619         case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
2620         case MONO_PATCH_INFO_MONITOR_ENTER:
2621         case MONO_PATCH_INFO_MONITOR_EXIT:
2622         case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
2623         case MONO_PATCH_INFO_CASTCLASS_CACHE:
2624                 break;
2625         case MONO_PATCH_INFO_RGCTX_FETCH: {
2626                 gboolean res;
2627                 MonoJumpInfoRgctxEntry *entry;
2628                 guint32 offset, val;
2629                 guint8 *p2;
2630
2631                 offset = decode_value (p, &p);
2632                 val = decode_value (p, &p);
2633
2634                 entry = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoRgctxEntry));
2635                 p2 = aot_module->blob + offset;
2636                 entry->method = decode_resolve_method_ref (aot_module, p2, &p2);
2637                 entry->in_mrgctx = ((val & 1) > 0) ? TRUE : FALSE;
2638                 entry->info_type = (val >> 1) & 0xff;
2639                 entry->data = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo));
2640                 entry->data->type = (val >> 9) & 0xff;
2641                 
2642                 res = decode_patch (aot_module, mp, entry->data, p, &p);
2643                 if (!res)
2644                         goto cleanup;
2645                 ji->data.rgctx_entry = entry;
2646                 break;
2647         }
2648         case MONO_PATCH_INFO_SEQ_POINT_INFO:
2649                 break;
2650         case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE: {
2651                 MonoJumpInfoImtTramp *imt_tramp = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoImtTramp));
2652
2653                 imt_tramp->method = decode_resolve_method_ref (aot_module, p, &p);
2654                 imt_tramp->vt_offset = decode_value (p, &p);
2655                 
2656                 ji->data.imt_tramp = imt_tramp;
2657                 break;
2658         }
2659         default:
2660                 g_warning ("unhandled type %d", ji->type);
2661                 g_assert_not_reached ();
2662         }
2663
2664         *endbuf = p;
2665
2666         return TRUE;
2667
2668  cleanup:
2669         return FALSE;
2670 }
2671
2672 static MonoJumpInfo*
2673 load_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, int n_patches, 
2674                                  guint32 **got_slots, 
2675                                  guint8 *buf, guint8 **endbuf)
2676 {
2677         MonoJumpInfo *patches;
2678         int pindex;
2679         guint8 *p;
2680
2681         p = buf;
2682
2683         patches = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo) * n_patches);
2684
2685         *got_slots = g_malloc (sizeof (guint32) * n_patches);
2686
2687         for (pindex = 0; pindex < n_patches; ++pindex) {
2688                 MonoJumpInfo *ji = &patches [pindex];
2689                 guint8 *shared_p;
2690                 gboolean res;
2691                 guint32 got_offset;
2692
2693                 got_offset = decode_value (p, &p);
2694
2695                 if (aot_module->got [got_offset]) {
2696                         /* Already loaded */
2697                         //printf ("HIT!\n");
2698                 } else {
2699                         shared_p = aot_module->blob + mono_aot_get_offset (aot_module->got_info_offsets, got_offset);
2700
2701                         ji->type = decode_value (shared_p, &shared_p);
2702
2703                         res = decode_patch (aot_module, mp, ji, shared_p, &shared_p);
2704                         if (!res)
2705                                 goto cleanup;
2706                 }
2707
2708                 (*got_slots) [pindex] = got_offset;
2709         }
2710
2711         *endbuf = p;
2712         return patches;
2713
2714  cleanup:
2715         g_free (*got_slots);
2716         *got_slots = NULL;
2717
2718         return NULL;
2719 }
2720
2721 static void
2722 register_jump_target_got_slot (MonoDomain *domain, MonoMethod *method, gpointer *got_slot)
2723 {
2724         /*
2725          * Jump addresses cannot be patched by the trampoline code since it
2726          * does not have access to the caller's address. Instead, we collect
2727          * the addresses of the GOT slots pointing to a method, and patch
2728          * them after the method has been compiled.
2729          */
2730         MonoJitDomainInfo *info = domain_jit_info (domain);
2731         GSList *list;
2732                 
2733         mono_domain_lock (domain);
2734         if (!info->jump_target_got_slot_hash)
2735                 info->jump_target_got_slot_hash = g_hash_table_new (NULL, NULL);
2736         list = g_hash_table_lookup (info->jump_target_got_slot_hash, method);
2737         list = g_slist_prepend (list, got_slot);
2738         g_hash_table_insert (info->jump_target_got_slot_hash, method, list);
2739         mono_domain_unlock (domain);
2740 }
2741
2742 /*
2743  * load_method:
2744  *
2745  *   Load the method identified by METHOD_INDEX from the AOT image. Return a
2746  * pointer to the native code of the method, or NULL if not found.
2747  * METHOD might not be set if the caller only has the image/token info.
2748  */
2749 static gpointer
2750 load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoMethod *method, guint32 token, int method_index)
2751 {
2752         MonoClass *klass;
2753         gboolean from_plt = method == NULL;
2754         MonoMemPool *mp;
2755         int i, pindex, n_patches, used_strings;
2756         gboolean keep_patches = TRUE;
2757         guint8 *p;
2758         MonoJitInfo *jinfo = NULL;
2759         guint8 *code, *info;
2760
2761         if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE)
2762                 return NULL;
2763
2764         if ((domain != mono_get_root_domain ()) && (!(amodule->info.opts & MONO_OPT_SHARED)))
2765                 /* Non shared AOT code can't be used in other appdomains */
2766                 return NULL;
2767
2768         if (amodule->out_of_date)
2769                 return NULL;
2770
2771         if (amodule->code_offsets [method_index] == 0xffffffff) {
2772                 if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
2773                         char *full_name;
2774
2775                         if (!method)
2776                                 method = mono_get_method (image, token, NULL);
2777                         full_name = mono_method_full_name (method, TRUE);
2778                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT NOT FOUND: %s.\n", full_name);
2779                         g_free (full_name);
2780                 }
2781                 return NULL;
2782         }
2783
2784         code = &amodule->code [amodule->code_offsets [method_index]];
2785
2786         info = &amodule->blob [mono_aot_get_offset (amodule->method_info_offsets, method_index)];
2787
2788         if (amodule->thumb_end && code < amodule->thumb_end) {
2789                 /* Convert this into a thumb address */
2790                 g_assert ((amodule->code_offsets [method_index] & 0x1) == 0);
2791                 code = &amodule->code [amodule->code_offsets [method_index] + 1];
2792         }
2793
2794         mono_aot_lock ();
2795         if (!amodule->methods_loaded)
2796                 amodule->methods_loaded = g_new0 (guint32, amodule->info.nmethods / 32 + 1);
2797         mono_aot_unlock ();
2798
2799         if ((amodule->methods_loaded [method_index / 32] >> (method_index % 32)) & 0x1)
2800                 return code;
2801
2802         if (mono_last_aot_method != -1) {
2803                 if (mono_jit_stats.methods_aot >= mono_last_aot_method)
2804                                 return NULL;
2805                 else if (mono_jit_stats.methods_aot == mono_last_aot_method - 1) {
2806                         if (!method)
2807                                 method = mono_get_method (image, token, NULL);
2808                         if (method) {
2809                                 char *name = mono_method_full_name (method, TRUE);
2810                                 printf ("LAST AOT METHOD: %s.\n", name);
2811                                 g_free (name);
2812                         } else {
2813                                 printf ("LAST AOT METHOD: %p %d\n", code, method_index);
2814                         }
2815                 }
2816         }
2817
2818         p = info;
2819
2820         if (method) {
2821                 klass = method->klass;
2822                 decode_klass_ref (amodule, p, &p);
2823         } else {
2824                 klass = decode_klass_ref (amodule, p, &p);
2825         }
2826
2827         if (amodule->info.opts & MONO_OPT_SHARED)
2828                 used_strings = decode_value (p, &p);
2829         else
2830                 used_strings = 0;
2831
2832         for (i = 0; i < used_strings; i++) {
2833                 guint token = decode_value (p, &p);
2834                 mono_ldstr (mono_get_root_domain (), image, mono_metadata_token_index (token));
2835         }
2836
2837         if (amodule->info.opts & MONO_OPT_SHARED)       
2838                 keep_patches = FALSE;
2839
2840         n_patches = decode_value (p, &p);
2841
2842         keep_patches = FALSE;
2843
2844         if (n_patches) {
2845                 MonoJumpInfo *patches;
2846                 guint32 *got_slots;
2847
2848                 if (keep_patches)
2849                         mp = domain->mp;
2850                 else
2851                         mp = mono_mempool_new ();
2852
2853                 patches = load_patch_info (amodule, mp, n_patches, &got_slots, p, &p);
2854                 if (patches == NULL)
2855                         goto cleanup;
2856
2857                 for (pindex = 0; pindex < n_patches; ++pindex) {
2858                         MonoJumpInfo *ji = &patches [pindex];
2859
2860                         if (!amodule->got [got_slots [pindex]]) {
2861                                 amodule->got [got_slots [pindex]] = mono_resolve_patch_target (method, domain, code, ji, TRUE);
2862                                 if (ji->type == MONO_PATCH_INFO_METHOD_JUMP)
2863                                         amodule->got [got_slots [pindex]] = mono_create_ftnptr (domain, amodule->got [got_slots [pindex]]);
2864                                 if (ji->type == MONO_PATCH_INFO_METHOD_JUMP)
2865                                         register_jump_target_got_slot (domain, ji->data.method, &(amodule->got [got_slots [pindex]]));
2866                         }
2867                         ji->type = MONO_PATCH_INFO_NONE;
2868                 }
2869
2870                 g_free (got_slots);
2871
2872                 if (!keep_patches)
2873                         mono_mempool_destroy (mp);
2874         }
2875
2876         if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
2877                 char *full_name;
2878
2879                 if (!method)
2880                         method = mono_get_method (image, token, NULL);
2881
2882                 full_name = mono_method_full_name (method, TRUE);
2883
2884                 if (!jinfo)
2885                         jinfo = mono_aot_find_jit_info (domain, amodule->assembly->image, code);
2886
2887                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND method %s [%p - %p %p]\n", full_name, code, code + jinfo->code_size, info);
2888                 g_free (full_name);
2889         }
2890
2891         mono_aot_lock ();
2892
2893         InterlockedIncrement (&mono_jit_stats.methods_aot);
2894
2895         amodule->methods_loaded [method_index / 32] |= 1 << (method_index % 32);
2896
2897         init_plt (amodule);
2898
2899         if (method && method->wrapper_type)
2900                 g_hash_table_insert (amodule->method_to_code, method, code);
2901
2902         mono_aot_unlock ();
2903
2904         if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION) {
2905                 MonoJitInfo *jinfo;
2906
2907                 if (!method) {
2908                         method = mono_get_method (image, token, NULL);
2909                         g_assert (method);
2910                 }
2911                 mono_profiler_method_jit (method);
2912                 jinfo = mono_jit_info_table_find (domain, (char*)code);
2913                 g_assert (jinfo);
2914                 mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
2915         }
2916
2917         if (from_plt && klass && !klass->generic_container)
2918                 mono_runtime_class_init (mono_class_vtable (domain, klass));
2919
2920         return code;
2921
2922  cleanup:
2923         /* FIXME: The space in domain->mp is wasted */  
2924         if (amodule->info.opts & MONO_OPT_SHARED)
2925                 /* No need to cache patches */
2926                 mono_mempool_destroy (mp);
2927
2928         if (jinfo)
2929                 g_free (jinfo);
2930
2931         return NULL;
2932 }
2933
2934 static guint32
2935 find_extra_method_in_amodule (MonoAotModule *amodule, MonoMethod *method, const char *name)
2936 {
2937         guint32 table_size, entry_size, hash;
2938         guint32 *table, *entry;
2939         guint32 index;
2940         static guint32 n_extra_decodes;
2941
2942         if (!amodule || amodule->out_of_date)
2943                 return 0xffffff;
2944
2945         table_size = amodule->extra_method_table [0];
2946         table = amodule->extra_method_table + 1;
2947         entry_size = 3;
2948
2949         hash = mono_aot_method_hash (method) % table_size;
2950
2951         entry = &table [hash * entry_size];
2952
2953         if (entry [0] == 0)
2954                 return 0xffffff;
2955
2956         index = 0xffffff;
2957         while (TRUE) {
2958                 guint32 key = entry [0];
2959                 guint32 value = entry [1];
2960                 guint32 next = entry [entry_size - 1];
2961                 MonoMethod *m;
2962                 guint8 *p, *orig_p;
2963
2964                 p = amodule->blob + key;
2965                 orig_p = p;
2966
2967                 mono_aot_lock ();
2968                 if (!amodule->method_ref_to_method)
2969                         amodule->method_ref_to_method = g_hash_table_new (NULL, NULL);
2970                 m = g_hash_table_lookup (amodule->method_ref_to_method, p);
2971                 mono_aot_unlock ();
2972                 if (!m) {
2973                         m = decode_resolve_method_ref_with_target (amodule, method, p, &p);
2974                         if (m) {
2975                                 mono_aot_lock ();
2976                                 g_hash_table_insert (amodule->method_ref_to_method, orig_p, m);
2977                                 mono_aot_unlock ();
2978                         }
2979                 }
2980                 if (m == method) {
2981                         index = value;
2982                         break;
2983                 }
2984
2985                 /* Special case: wrappers of shared generic methods */
2986                 if (m && method->wrapper_type && m->wrapper_type == m->wrapper_type &&
2987                         method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED) {
2988                         MonoMethod *w1 = mono_marshal_method_from_wrapper (method);
2989                         MonoMethod *w2 = mono_marshal_method_from_wrapper (m);
2990
2991                         if (w1->is_inflated && ((MonoMethodInflated *)w1)->declaring == w2) {
2992                                 index = value;
2993                                 break;
2994                         }
2995                 }
2996
2997                 /* Methods decoded needlessly */
2998                 if (m) {
2999                         //printf ("%d %s %s %p\n", n_extra_decodes, mono_method_full_name (method, TRUE), mono_method_full_name (m, TRUE), orig_p);
3000                         n_extra_decodes ++;
3001                 }
3002
3003                 if (next != 0)
3004                         entry = &table [next * entry_size];
3005                 else
3006                         break;
3007         }
3008
3009         return index;
3010 }
3011
3012 static void
3013 add_module_cb (gpointer key, gpointer value, gpointer user_data)
3014 {
3015         g_ptr_array_add ((GPtrArray*)user_data, value);
3016 }
3017
3018 /*
3019  * find_extra_method:
3020  *
3021  *   Try finding METHOD in the extra_method table in all AOT images.
3022  * Return its method index, or 0xffffff if not found. Set OUT_AMODULE to the AOT
3023  * module where the method was found.
3024  */
3025 static guint32
3026 find_extra_method (MonoMethod *method, MonoAotModule **out_amodule)
3027 {
3028         guint32 index;
3029         GPtrArray *modules;
3030         int i;
3031         char *name = NULL;
3032
3033         if (method->wrapper_type)
3034                 name = mono_aot_wrapper_name (method);
3035
3036         /* Try the method's module first */
3037         *out_amodule = method->klass->image->aot_module;
3038         index = find_extra_method_in_amodule (method->klass->image->aot_module, method, name);
3039         if (index != 0xffffff) {
3040                 g_free (name);
3041                 return index;
3042         }
3043
3044         /* 
3045          * Try all other modules.
3046          * This is needed because generic instances klass->image points to the image
3047          * containing the generic definition, but the native code is generated to the
3048          * AOT image which contains the reference.
3049          */
3050
3051         /* Make a copy to avoid doing the search inside the aot lock */
3052         modules = g_ptr_array_new ();
3053         mono_aot_lock ();
3054         g_hash_table_foreach (aot_modules, add_module_cb, modules);
3055         mono_aot_unlock ();
3056
3057         index = 0xffffff;
3058         for (i = 0; i < modules->len; ++i) {
3059                 MonoAotModule *amodule = g_ptr_array_index (modules, i);
3060
3061                 if (amodule != method->klass->image->aot_module)
3062                         index = find_extra_method_in_amodule (amodule, method, name);
3063                 if (index != 0xffffff) {
3064                         *out_amodule = amodule;
3065                         break;
3066                 }
3067         }
3068         
3069         g_ptr_array_free (modules, TRUE);
3070
3071         g_free (name);
3072         return index;
3073 }
3074
3075 /*
3076  * mono_aot_get_method:
3077  *
3078  *   Return a pointer to the AOTed native code for METHOD if it can be found,
3079  * NULL otherwise.
3080  * On platforms with function pointers, this doesn't return a function pointer.
3081  */
3082 gpointer
3083 mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
3084 {
3085         MonoClass *klass = method->klass;
3086         guint32 method_index;
3087         MonoAotModule *amodule = klass->image->aot_module;
3088         guint8 *code;
3089
3090         if (!amodule)
3091                 return NULL;
3092
3093         if (amodule->out_of_date)
3094                 return NULL;
3095
3096         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
3097                 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
3098                 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
3099                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
3100                 return NULL;
3101
3102         /*
3103          * Use the original method instead of its invoke-with-check wrapper.
3104          * This is not a problem when using full-aot, since it doesn't support
3105          * remoting.
3106          */
3107         if (mono_aot_only && method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
3108                 return mono_aot_get_method (domain, mono_marshal_method_from_wrapper (method));
3109
3110         g_assert (klass->inited);
3111
3112         /* Find method index */
3113         if (method->is_inflated && mono_method_is_generic_sharable_impl_full (method, FALSE, FALSE)) {
3114                 /* 
3115                  * For generic methods, we store the fully shared instance in place of the
3116                  * original method.
3117                  */
3118                 method = mono_method_get_declaring_generic_method (method);
3119                 method_index = mono_metadata_token_index (method->token) - 1;
3120         } else if (method->is_inflated || !method->token) {
3121                 /* This hash table is used to avoid the slower search in the extra_method_table in the AOT image */
3122                 mono_aot_lock ();
3123                 code = g_hash_table_lookup (amodule->method_to_code, method);
3124                 mono_aot_unlock ();
3125                 if (code)
3126                         return code;
3127
3128                 method_index = find_extra_method (method, &amodule);
3129                 /*
3130                  * Special case the ICollection<T> wrappers for arrays, as they cannot
3131                  * be statically enumerated, and each wrapper ends up calling the same
3132                  * method in Array.
3133                  */
3134                 if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED && method->klass->rank && strstr (method->name, "System.Collections.Generic")) {
3135                         MonoMethod *m = mono_aot_get_array_helper_from_wrapper (method);
3136
3137                         code = mono_aot_get_method (domain, m);
3138                         if (code) {
3139                                 if (mono_method_needs_static_rgctx_invoke (m, FALSE)) {
3140                                         code = mono_create_static_rgctx_trampoline (m, mono_create_ftnptr (domain, code));
3141                                         /* The call above returns an ftnptr */
3142                                         code = mono_get_addr_from_ftnptr (code);
3143                                 }
3144
3145                                 return code;
3146                         }
3147                 }
3148
3149                 /*
3150                  * Special case Array.GetGenericValueImpl which is a generic icall.
3151                  * Generic sharing currently can't handle it, but the icall returns data using
3152                  * an out parameter, so the managed-to-native wrappers can share the same code.
3153                  */
3154                 if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE && method->klass == mono_defaults.array_class && !strcmp (method->name, "GetGenericValueImpl")) {
3155                         MonoMethod *m;
3156                         MonoGenericContext ctx;
3157                         MonoType *args [16];
3158
3159                         if (mono_method_signature (method)->params [1]->type == MONO_TYPE_OBJECT)
3160                                 /* Avoid recursion */
3161                                 return NULL;
3162
3163                         m = mono_class_get_method_from_name (mono_defaults.array_class, "GetGenericValueImpl", 2);
3164                         g_assert (m);
3165
3166                         memset (&ctx, 0, sizeof (ctx));
3167                         args [0] = &mono_defaults.object_class->byval_arg;
3168                         ctx.method_inst = mono_metadata_get_generic_inst (1, args);
3169
3170                         m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method (m, &ctx), TRUE, TRUE);
3171
3172                         /* 
3173                          * Get the code for the <object> instantiation which should be emitted into
3174                          * the mscorlib aot image by the AOT compiler.
3175                          */
3176                         code = mono_aot_get_method (domain, m);
3177                         if (code)
3178                                 return code;
3179                 }
3180
3181                 /* Same for CompareExchange<T> and Exchange<T> */
3182                 if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE && method->klass->image == mono_defaults.corlib && !strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Interlocked") && (!strcmp (method->name, "CompareExchange") || !strcmp (method->name, "Exchange")) && MONO_TYPE_IS_REFERENCE (mono_method_signature (method)->params [1])) {
3183                         MonoMethod *m;
3184                         MonoGenericContext ctx;
3185                         MonoType *args [16];
3186                         gpointer iter = NULL;
3187
3188                         while ((m = mono_class_get_methods (method->klass, &iter))) {
3189                                 if (mono_method_signature (m)->generic_param_count && !strcmp (m->name, method->name))
3190                                         break;
3191                         }
3192                         g_assert (m);
3193
3194                         memset (&ctx, 0, sizeof (ctx));
3195                         args [0] = &mono_defaults.object_class->byval_arg;
3196                         ctx.method_inst = mono_metadata_get_generic_inst (1, args);
3197
3198                         m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method (m, &ctx), TRUE, TRUE);
3199
3200                         /* Avoid recursion */
3201                         if (method == m)
3202                                 return NULL;
3203
3204                         /* 
3205                          * Get the code for the <object> instantiation which should be emitted into
3206                          * the mscorlib aot image by the AOT compiler.
3207                          */
3208                         code = mono_aot_get_method (domain, m);
3209                         if (code)
3210                                 return code;
3211                 }
3212
3213                 if (method_index == 0xffffff && method->is_inflated && mono_method_is_generic_sharable_impl_full (method, FALSE, TRUE)) {
3214                         /* Partial sharing */
3215                         method_index = find_extra_method (mini_get_shared_method (method), &amodule);
3216                 }
3217
3218                 if (method_index == 0xffffff) {
3219                         if (mono_aot_only && mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
3220                                 char *full_name;
3221
3222                                 full_name = mono_method_full_name (method, TRUE);
3223                                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT NOT FOUND: %s.\n", full_name);
3224                                 g_free (full_name);
3225                         }
3226                         return NULL;
3227                 }
3228
3229                 if (method_index == 0xffffff)
3230                         return NULL;
3231
3232                 /* Needed by find_jit_info */
3233                 mono_aot_lock ();
3234                 if (!amodule->extra_methods)
3235                         amodule->extra_methods = g_hash_table_new (NULL, NULL);
3236                 g_hash_table_insert (amodule->extra_methods, GUINT_TO_POINTER (method_index), method);
3237                 mono_aot_unlock ();
3238         } else {
3239                 /* Common case */
3240                 method_index = mono_metadata_token_index (method->token) - 1;
3241         }
3242
3243         return load_method (domain, amodule, klass->image, method, method->token, method_index);
3244 }
3245
3246 /**
3247  * Same as mono_aot_get_method, but we try to avoid loading any metadata from the
3248  * method.
3249  */
3250 gpointer
3251 mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
3252 {
3253         MonoAotModule *aot_module = image->aot_module;
3254         int method_index;
3255
3256         if (!aot_module)
3257                 return NULL;
3258
3259         method_index = mono_metadata_token_index (token) - 1;
3260
3261         return load_method (domain, aot_module, image, NULL, token, method_index);
3262 }
3263
3264 typedef struct {
3265         guint8 *addr;
3266         gboolean res;
3267 } IsGotEntryUserData;
3268
3269 static void
3270 check_is_got_entry (gpointer key, gpointer value, gpointer user_data)
3271 {
3272         IsGotEntryUserData *data = (IsGotEntryUserData*)user_data;
3273         MonoAotModule *aot_module = (MonoAotModule*)value;
3274
3275         if (aot_module->got && (data->addr >= (guint8*)(aot_module->got)) && (data->addr < (guint8*)(aot_module->got + aot_module->info.got_size)))
3276                 data->res = TRUE;
3277 }
3278
3279 gboolean
3280 mono_aot_is_got_entry (guint8 *code, guint8 *addr)
3281 {
3282         IsGotEntryUserData user_data;
3283
3284         if (!aot_modules)
3285                 return FALSE;
3286
3287         user_data.addr = addr;
3288         user_data.res = FALSE;
3289         mono_aot_lock ();
3290         g_hash_table_foreach (aot_modules, check_is_got_entry, &user_data);
3291         mono_aot_unlock ();
3292         
3293         return user_data.res;
3294 }
3295
3296 typedef struct {
3297         guint8 *addr;
3298         MonoAotModule *module;
3299 } FindAotModuleUserData;
3300
3301 static void
3302 find_aot_module_cb (gpointer key, gpointer value, gpointer user_data)
3303 {
3304         FindAotModuleUserData *data = (FindAotModuleUserData*)user_data;
3305         MonoAotModule *aot_module = (MonoAotModule*)value;
3306
3307         if ((data->addr >= (guint8*)(aot_module->code)) && (data->addr < (guint8*)(aot_module->code_end)))
3308                 data->module = aot_module;
3309 }
3310
3311 static inline MonoAotModule*
3312 find_aot_module (guint8 *code)
3313 {
3314         FindAotModuleUserData user_data;
3315
3316         if (!aot_modules)
3317                 return NULL;
3318
3319         /* Reading these need no locking */
3320         if (((gsize)code < aot_code_low_addr) || ((gsize)code > aot_code_high_addr))
3321                 return NULL;
3322
3323         user_data.addr = code;
3324         user_data.module = NULL;
3325                 
3326         mono_aot_lock ();
3327         g_hash_table_foreach (aot_modules, find_aot_module_cb, &user_data);
3328         mono_aot_unlock ();
3329         
3330         return user_data.module;
3331 }
3332
3333 void
3334 mono_aot_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr)
3335 {
3336         /*
3337          * Since AOT code is only used in the root domain, 
3338          * mono_domain_get () != mono_get_root_domain () means the calling method
3339          * is AppDomain:InvokeInDomain, so this is the same check as in 
3340          * mono_method_same_domain () but without loading the metadata for the method.
3341          */
3342         if (mono_domain_get () == mono_get_root_domain ())
3343                 mono_arch_patch_plt_entry (code, got, regs, addr);
3344 }
3345
3346 /*
3347  * mono_aot_plt_resolve:
3348  *
3349  *   This function is called by the entries in the PLT to resolve the actual method that
3350  * needs to be called. It returns a trampoline to the method and patches the PLT entry.
3351  * Returns NULL if the something cannot be loaded.
3352  */
3353 gpointer
3354 mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code)
3355 {
3356 #ifdef MONO_ARCH_AOT_SUPPORTED
3357         guint8 *p, *target, *plt_entry;
3358         MonoJumpInfo ji;
3359         MonoAotModule *module = (MonoAotModule*)aot_module;
3360         gboolean res, no_ftnptr = FALSE;
3361         MonoMemPool *mp;
3362
3363         //printf ("DYN: %p %d\n", aot_module, plt_info_offset);
3364
3365         p = &module->blob [plt_info_offset];
3366
3367         ji.type = decode_value (p, &p);
3368
3369         mp = mono_mempool_new_size (512);
3370         res = decode_patch (module, mp, &ji, p, &p);
3371
3372         if (!res) {
3373                 mono_mempool_destroy (mp);
3374                 return NULL;
3375         }
3376
3377         /* 
3378          * Avoid calling resolve_patch_target in the full-aot case if possible, since
3379          * it would create a trampoline, and we don't need that.
3380          * We could do this only if the method does not need the special handling
3381          * in mono_magic_trampoline ().
3382          */
3383         if (mono_aot_only && ji.type == MONO_PATCH_INFO_METHOD && !ji.data.method->is_generic && !mono_method_check_context_used (ji.data.method) && !(ji.data.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) &&
3384                 !mono_method_needs_static_rgctx_invoke (ji.data.method, FALSE)) {
3385                 target = mono_jit_compile_method (ji.data.method);
3386                 no_ftnptr = TRUE;
3387         } else {
3388                 target = mono_resolve_patch_target (NULL, mono_domain_get (), NULL, &ji, TRUE);
3389         }
3390
3391         /*
3392          * The trampoline expects us to return a function descriptor on platforms which use
3393          * it, but resolve_patch_target returns a direct function pointer for some type of
3394          * patches, so have to translate between the two.
3395          * FIXME: Clean this up, but how ?
3396          */
3397         if (ji.type == MONO_PATCH_INFO_ABS || ji.type == MONO_PATCH_INFO_INTERNAL_METHOD || ji.type == MONO_PATCH_INFO_CLASS_INIT || ji.type == MONO_PATCH_INFO_ICALL_ADDR || ji.type == MONO_PATCH_INFO_JIT_ICALL_ADDR || ji.type == MONO_PATCH_INFO_RGCTX_FETCH) {
3398                 /* These should already have a function descriptor */
3399 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
3400                 /* Our function descriptors have a 0 environment, gcc created ones don't */
3401                 if (ji.type != MONO_PATCH_INFO_INTERNAL_METHOD && ji.type != MONO_PATCH_INFO_JIT_ICALL_ADDR && ji.type != MONO_PATCH_INFO_ICALL_ADDR)
3402                         g_assert (((gpointer*)target) [2] == 0);
3403 #endif
3404                 /* Empty */
3405         } else if (!no_ftnptr) {
3406 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
3407                 g_assert (((gpointer*)target) [2] != 0);
3408 #endif
3409                 target = mono_create_ftnptr (mono_domain_get (), target);
3410         }
3411
3412         mono_mempool_destroy (mp);
3413
3414         /* Patch the PLT entry with target which might be the actual method not a trampoline */
3415         plt_entry = mono_aot_get_plt_entry (code);
3416         g_assert (plt_entry);
3417         mono_aot_patch_plt_entry (plt_entry, module->got, NULL, target);
3418
3419         return target;
3420 #else
3421         g_assert_not_reached ();
3422         return NULL;
3423 #endif
3424 }
3425
3426 /**
3427  * init_plt:
3428  *
3429  *   Initialize the PLT table of the AOT module. Called lazily when the first AOT
3430  * method in the module is loaded to avoid committing memory by writing to it.
3431  * LOCKING: Assumes the AOT lock is held.
3432  */
3433 static void
3434 init_plt (MonoAotModule *amodule)
3435 {
3436         int i;
3437         gpointer tramp;
3438
3439         if (amodule->plt_inited)
3440                 return;
3441
3442         tramp = mono_create_specific_trampoline (amodule, MONO_TRAMPOLINE_AOT_PLT, mono_get_root_domain (), NULL);
3443
3444         /*
3445          * Initialize the PLT entries in the GOT to point to the default targets.
3446          */
3447
3448         tramp = mono_create_ftnptr (mono_domain_get (), tramp);
3449          for (i = 1; i < amodule->info.plt_size; ++i)
3450                  /* All the default entries point to the AOT trampoline */
3451                  ((gpointer*)amodule->got)[amodule->info.plt_got_offset_base + i] = tramp;
3452
3453         amodule->plt_inited = TRUE;
3454 }
3455
3456 /*
3457  * mono_aot_get_plt_entry:
3458  *
3459  *   Return the address of the PLT entry called by the code at CODE if exists.
3460  */
3461 guint8*
3462 mono_aot_get_plt_entry (guint8 *code)
3463 {
3464         MonoAotModule *amodule = find_aot_module (code);
3465         guint8 *target = NULL;
3466
3467         if (!amodule)
3468                 return NULL;
3469
3470 #ifdef TARGET_ARM
3471         if (amodule->thumb_end && code < amodule->thumb_end) {
3472                 return mono_arm_get_thumb_plt_entry (code);
3473         }
3474 #endif
3475
3476 #ifdef MONO_ARCH_AOT_SUPPORTED
3477         target = mono_arch_get_call_target (code);
3478 #else
3479         g_assert_not_reached ();
3480 #endif
3481
3482         if ((target >= (guint8*)(amodule->plt)) && (target < (guint8*)(amodule->plt_end)))
3483                 return target;
3484         else
3485                 return NULL;
3486 }
3487
3488 /*
3489  * mono_aot_get_plt_info_offset:
3490  *
3491  *   Return the PLT info offset belonging to the plt entry called by CODE.
3492  */
3493 guint32
3494 mono_aot_get_plt_info_offset (mgreg_t *regs, guint8 *code)
3495 {
3496         guint8 *plt_entry = mono_aot_get_plt_entry (code);
3497
3498         g_assert (plt_entry);
3499
3500         /* The offset is embedded inside the code after the plt entry */
3501 #ifdef MONO_ARCH_AOT_SUPPORTED
3502         return mono_arch_get_plt_info_offset (plt_entry, regs, code);
3503 #else
3504         g_assert_not_reached ();
3505         return 0;
3506 #endif
3507 }
3508
3509 static gpointer
3510 mono_create_ftnptr_malloc (guint8 *code)
3511 {
3512 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
3513         MonoPPCFunctionDescriptor *ftnptr = g_malloc0 (sizeof (MonoPPCFunctionDescriptor));
3514
3515         ftnptr->code = code;
3516         ftnptr->toc = NULL;
3517         ftnptr->env = NULL;
3518
3519         return ftnptr;
3520 #else
3521         return code;
3522 #endif
3523 }
3524
3525 /*
3526  * mono_aot_register_jit_icall:
3527  *
3528  *   Register a JIT icall which is called by trampolines in full-aot mode. This should
3529  * be called from mono_arch_init () during startup.
3530  */
3531 void
3532 mono_aot_register_jit_icall (const char *name, gpointer addr)
3533 {
3534         /* No need for locking */
3535         if (!aot_jit_icall_hash)
3536                 aot_jit_icall_hash = g_hash_table_new (g_str_hash, g_str_equal);
3537         g_hash_table_insert (aot_jit_icall_hash, (char*)name, addr);
3538 }
3539
3540 /*
3541  * load_function:
3542  *
3543  *   Load the function named NAME from the aot image. 
3544  */
3545 static gpointer
3546 load_function (MonoAotModule *amodule, const char *name)
3547 {
3548         char *symbol;
3549         guint8 *p;
3550         int n_patches, pindex;
3551         MonoMemPool *mp;
3552         gpointer code;
3553
3554         /* Load the code */
3555
3556         symbol = g_strdup_printf ("%s", name);
3557         find_symbol (amodule->sofile, amodule->globals, symbol, (gpointer *)&code);
3558         g_free (symbol);
3559         if (!code)
3560                 g_error ("Symbol '%s' not found in AOT file '%s'.\n", name, amodule->aot_name);
3561
3562         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND function '%s' in AOT file '%s'.\n", name, amodule->aot_name);
3563
3564         /* Load info */
3565
3566         symbol = g_strdup_printf ("%s_p", name);
3567         find_symbol (amodule->sofile, amodule->globals, symbol, (gpointer *)&p);
3568         g_free (symbol);
3569         if (!p)
3570                 /* Nothing to patch */
3571                 return code;
3572
3573         p = amodule->blob + *(guint32*)p;
3574
3575         /* Similar to mono_aot_load_method () */
3576
3577         n_patches = decode_value (p, &p);
3578
3579         if (n_patches) {
3580                 MonoJumpInfo *patches;
3581                 guint32 *got_slots;
3582
3583                 mp = mono_mempool_new ();
3584
3585                 patches = load_patch_info (amodule, mp, n_patches, &got_slots, p, &p);
3586                 g_assert (patches);
3587
3588                 for (pindex = 0; pindex < n_patches; ++pindex) {
3589                         MonoJumpInfo *ji = &patches [pindex];
3590                         gpointer target;
3591
3592                         if (amodule->got [got_slots [pindex]])
3593                                 continue;
3594
3595                         /*
3596                          * When this code is executed, the runtime may not be initalized yet, so
3597                          * resolve the patch info by hand.
3598                          */
3599                         if (ji->type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
3600                                 if (!strcmp (ji->data.name, "mono_get_lmf_addr")) {
3601                                         target = mono_get_lmf_addr;
3602                                 } else if (!strcmp (ji->data.name, "mono_thread_force_interruption_checkpoint")) {
3603                                         target = mono_thread_force_interruption_checkpoint;
3604                                 } else if (!strcmp (ji->data.name, "mono_exception_from_token")) {
3605                                         target = mono_exception_from_token;
3606                                 } else if (!strcmp (ji->data.name, "mono_throw_exception")) {
3607                                         target = mono_get_throw_exception ();
3608                                 } else if (strstr (ji->data.name, "trampoline_func_") == ji->data.name) {
3609                                         int tramp_type2 = atoi (ji->data.name + strlen ("trampoline_func_"));
3610                                         target = (gpointer)mono_get_trampoline_func (tramp_type2);
3611                                 } else if (strstr (ji->data.name, "specific_trampoline_lazy_fetch_") == ji->data.name) {
3612                                         /* atoll is needed because the the offset is unsigned */
3613                                         guint32 slot;
3614                                         int res;
3615
3616                                         res = sscanf (ji->data.name, "specific_trampoline_lazy_fetch_%u", &slot);
3617                                         g_assert (res == 1);
3618                                         target = mono_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL);
3619                                         target = mono_create_ftnptr_malloc (target);
3620                                 } else if (!strcmp (ji->data.name, "specific_trampoline_monitor_enter")) {
3621                                         target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER, mono_get_root_domain (), NULL);
3622                                         target = mono_create_ftnptr_malloc (target);
3623                                 } else if (!strcmp (ji->data.name, "specific_trampoline_monitor_exit")) {
3624                                         target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_EXIT, mono_get_root_domain (), NULL);
3625                                         target = mono_create_ftnptr_malloc (target);
3626                                 } else if (!strcmp (ji->data.name, "specific_trampoline_generic_class_init")) {
3627                                         target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_GENERIC_CLASS_INIT, mono_get_root_domain (), NULL);
3628                                         target = mono_create_ftnptr_malloc (target);
3629                                 } else if (!strcmp (ji->data.name, "mono_thread_get_and_clear_pending_exception")) {
3630                                         target = mono_thread_get_and_clear_pending_exception;
3631                                 } else if (strstr (ji->data.name, "generic_trampoline_")) {
3632                                         target = mono_aot_get_trampoline (ji->data.name);
3633                                 } else if (aot_jit_icall_hash && g_hash_table_lookup (aot_jit_icall_hash, ji->data.name)) {
3634                                         /* Registered by mono_arch_init () */
3635                                         target = g_hash_table_lookup (aot_jit_icall_hash, ji->data.name);
3636                                 } else {
3637                                         fprintf (stderr, "Unknown relocation '%s'\n", ji->data.name);
3638                                         g_assert_not_reached ();
3639                                         target = NULL;
3640                                 }
3641                         } else {
3642                                 /* Hopefully the code doesn't have patches which need method or 
3643                                  * domain to be set.
3644                                  */
3645                                 target = mono_resolve_patch_target (NULL, NULL, code, ji, FALSE);
3646                                 g_assert (target);
3647                         }
3648
3649                         amodule->got [got_slots [pindex]] = target;
3650                 }
3651
3652                 g_free (got_slots);
3653
3654                 mono_mempool_destroy (mp);
3655         }
3656
3657         return code;
3658 }
3659
3660 /*
3661  * Return the trampoline identified by NAME from the mscorlib AOT file.
3662  * On ppc64, this returns a function descriptor.
3663  */
3664 gpointer
3665 mono_aot_get_trampoline (const char *name)
3666 {
3667         MonoImage *image;
3668         MonoAotModule *amodule;
3669
3670         image = mono_defaults.corlib;
3671         g_assert (image);
3672
3673         amodule = image->aot_module;
3674         g_assert (amodule);
3675
3676         return mono_create_ftnptr_malloc (load_function (amodule, name));
3677 }
3678
3679 /* Return a given kind of trampoline */
3680 static gpointer
3681 get_numerous_trampoline (MonoAotTrampoline tramp_type, int n_got_slots, MonoAotModule **out_amodule, guint32 *got_offset, guint32 *out_tramp_size)
3682 {
3683         MonoAotModule *amodule;
3684         int index, tramp_size;
3685         MonoImage *image;
3686
3687         /* Currently, we keep all trampolines in the mscorlib AOT image */
3688         image = mono_defaults.corlib;
3689         g_assert (image);
3690
3691         mono_aot_lock ();
3692
3693         amodule = image->aot_module;
3694         g_assert (amodule);
3695
3696         *out_amodule = amodule;
3697
3698         if (amodule->trampoline_index [tramp_type] == amodule->info.num_trampolines [tramp_type])
3699                 g_error ("Ran out of trampolines of type %d in '%s' (%d)\n", tramp_type, image->name, amodule->info.num_trampolines [tramp_type]);
3700
3701         index = amodule->trampoline_index [tramp_type] ++;
3702
3703         mono_aot_unlock ();
3704
3705         *got_offset = amodule->info.trampoline_got_offset_base [tramp_type] + (index * n_got_slots);
3706
3707         tramp_size = amodule->info.trampoline_size [tramp_type];
3708
3709         if (out_tramp_size)
3710                 *out_tramp_size = tramp_size;
3711
3712         return amodule->trampolines [tramp_type] + (index * tramp_size);
3713 }
3714
3715 /*
3716  * Return a specific trampoline from the AOT file.
3717  */
3718 gpointer
3719 mono_aot_create_specific_trampoline (MonoImage *image, gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len)
3720 {
3721         MonoAotModule *amodule;
3722         guint32 got_offset, tramp_size;
3723         guint8 *code, *tramp;
3724         static gpointer generic_trampolines [MONO_TRAMPOLINE_NUM];
3725         static gboolean inited;
3726         static guint32 num_trampolines;
3727
3728         if (!inited) {
3729                 mono_aot_lock ();
3730
3731                 if (!inited) {
3732                         mono_counters_register ("Specific trampolines", MONO_COUNTER_JIT | MONO_COUNTER_INT, &num_trampolines);
3733                         inited = TRUE;
3734                 }
3735
3736                 mono_aot_unlock ();
3737         }
3738
3739         num_trampolines ++;
3740
3741         if (!generic_trampolines [tramp_type]) {
3742                 char *symbol;
3743
3744                 symbol = mono_get_generic_trampoline_name (tramp_type);
3745                 generic_trampolines [tramp_type] = mono_aot_get_trampoline (symbol);
3746                 g_free (symbol);
3747         }
3748
3749         tramp = generic_trampolines [tramp_type];
3750         g_assert (tramp);
3751
3752         code = get_numerous_trampoline (MONO_AOT_TRAMP_SPECIFIC, 2, &amodule, &got_offset, &tramp_size);
3753
3754         amodule->got [got_offset] = tramp;
3755         amodule->got [got_offset + 1] = arg1;
3756
3757         if (code_len)
3758                 *code_len = tramp_size;
3759
3760         return code;
3761 }
3762
3763 gpointer
3764 mono_aot_get_static_rgctx_trampoline (gpointer ctx, gpointer addr)
3765 {
3766         MonoAotModule *amodule;
3767         guint8 *code;
3768         guint32 got_offset;
3769
3770         code = get_numerous_trampoline (MONO_AOT_TRAMP_STATIC_RGCTX, 2, &amodule, &got_offset, NULL);
3771
3772         amodule->got [got_offset] = ctx;
3773         amodule->got [got_offset + 1] = addr; 
3774
3775         /* The caller expects an ftnptr */
3776         return mono_create_ftnptr (mono_domain_get (), code);
3777 }
3778
3779 gpointer
3780 mono_aot_get_unbox_trampoline (MonoMethod *method)
3781 {
3782         guint32 method_index = mono_metadata_token_index (method->token) - 1;
3783         MonoAotModule *amodule;
3784         gpointer code;
3785         guint32 *ut, *ut_end, *entry;
3786         int low, high, entry_index;
3787
3788         if (method->is_inflated && !mono_method_is_generic_sharable_impl (method, FALSE)) {
3789                 method_index = find_extra_method (method, &amodule);
3790                 g_assert (method_index != 0xffffff);
3791         } else {
3792                 amodule = method->klass->image->aot_module;
3793                 g_assert (amodule);
3794         }
3795
3796         ut = amodule->unbox_trampolines;
3797         ut_end = amodule->unbox_trampolines_end;
3798
3799         /* Do a binary search in the sorted table */
3800         code = NULL;
3801         low = 0;
3802         high = (ut_end - ut) / 2;
3803         while (low < high) {
3804                 entry_index = (low + high) / 2;
3805                 entry = &ut [(entry_index * 2)];
3806                 if (entry [0] < method_index) {
3807                         low = entry_index + 1;
3808                 } else if (entry [0] > method_index) {
3809                         high = entry_index;
3810                 } else {
3811                         code = amodule->code + entry [1];
3812                         break;
3813                 }
3814         }
3815         g_assert (code);
3816
3817         /* The caller expects an ftnptr */
3818         return mono_create_ftnptr (mono_domain_get (), code);
3819 }
3820
3821 gpointer
3822 mono_aot_get_lazy_fetch_trampoline (guint32 slot)
3823 {
3824         char *symbol;
3825         gpointer code;
3826
3827         symbol = mono_get_rgctx_fetch_trampoline_name (slot);
3828         code = load_function (mono_defaults.corlib->aot_module, symbol);
3829         g_free (symbol);
3830         /* The caller expects an ftnptr */
3831         return mono_create_ftnptr (mono_domain_get (), code);
3832 }
3833
3834 gpointer
3835 mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
3836 {
3837         guint32 got_offset;
3838         gpointer code;
3839         gpointer *buf;
3840         int i, index, real_count;
3841         MonoAotModule *amodule;
3842
3843         code = get_numerous_trampoline (MONO_AOT_TRAMP_IMT_THUNK, 1, &amodule, &got_offset, NULL);
3844
3845         real_count = 0;
3846         for (i = 0; i < count; ++i) {
3847                 MonoIMTCheckItem *item = imt_entries [i];
3848
3849                 if (item->is_equals)
3850                         real_count ++;
3851         }
3852
3853         /* Save the entries into an array */
3854         buf = mono_domain_alloc (domain, (real_count + 1) * 2 * sizeof (gpointer));
3855         index = 0;
3856         for (i = 0; i < count; ++i) {
3857                 MonoIMTCheckItem *item = imt_entries [i];               
3858
3859                 if (!item->is_equals)
3860                         continue;
3861
3862                 g_assert (item->key);
3863
3864                 buf [(index * 2)] = item->key;
3865                 if (item->has_target_code) {
3866                         gpointer *p = mono_domain_alloc (domain, sizeof (gpointer));
3867                         *p = item->value.target_code;
3868                         buf [(index * 2) + 1] = p;
3869                 } else {
3870                         buf [(index * 2) + 1] = &(vtable->vtable [item->value.vtable_slot]);
3871                 }
3872                 index ++;
3873         }
3874         buf [(index * 2)] = NULL;
3875         buf [(index * 2) + 1] = fail_tramp;
3876         
3877         amodule->got [got_offset] = buf;
3878
3879         return code;
3880 }
3881  
3882 /*
3883  * mono_aot_set_make_unreadable:
3884  *
3885  *   Set whenever to make all mmaped memory unreadable. In conjuction with a
3886  * SIGSEGV handler, this is useful to find out which pages the runtime tries to read.
3887  */
3888 void
3889 mono_aot_set_make_unreadable (gboolean unreadable)
3890 {
3891         static int inited;
3892
3893         make_unreadable = unreadable;
3894
3895         if (make_unreadable && !inited) {
3896                 mono_counters_register ("AOT pagefaults", MONO_COUNTER_JIT | MONO_COUNTER_INT, &n_pagefaults);
3897         }               
3898 }
3899
3900 typedef struct {
3901         MonoAotModule *module;
3902         guint8 *ptr;
3903 } FindMapUserData;
3904
3905 static void
3906 find_map (gpointer key, gpointer value, gpointer user_data)
3907 {
3908         MonoAotModule *module = (MonoAotModule*)value;
3909         FindMapUserData *data = (FindMapUserData*)user_data;
3910
3911         if (!data->module)
3912                 if ((data->ptr >= module->mem_begin) && (data->ptr < module->mem_end))
3913                         data->module = module;
3914 }
3915
3916 static MonoAotModule*
3917 find_module_for_addr (void *ptr)
3918 {
3919         FindMapUserData data;
3920
3921         if (!make_unreadable)
3922                 return NULL;
3923
3924         data.module = NULL;
3925         data.ptr = (guint8*)ptr;
3926
3927         mono_aot_lock ();
3928         g_hash_table_foreach (aot_modules, (GHFunc)find_map, &data);
3929         mono_aot_unlock ();
3930
3931         return data.module;
3932 }
3933
3934 /*
3935  * mono_aot_is_pagefault:
3936  *
3937  *   Should be called from a SIGSEGV signal handler to find out whenever @ptr is
3938  * within memory allocated by this module.
3939  */
3940 gboolean
3941 mono_aot_is_pagefault (void *ptr)
3942 {
3943         if (!make_unreadable)
3944                 return FALSE;
3945
3946         /* 
3947          * Not signal safe, but SIGSEGV's are synchronous, and
3948          * this is only turned on by a MONO_DEBUG option.
3949          */
3950         return find_module_for_addr (ptr) != NULL;
3951 }
3952
3953 /*
3954  * mono_aot_handle_pagefault:
3955  *
3956  *   Handle a pagefault caused by an unreadable page by making it readable again.
3957  */
3958 void
3959 mono_aot_handle_pagefault (void *ptr)
3960 {
3961 #ifndef PLATFORM_WIN32
3962         guint8* start = (guint8*)ROUND_DOWN (((gssize)ptr), mono_pagesize ());
3963         int res;
3964
3965         mono_aot_lock ();
3966         res = mono_mprotect (start, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC);
3967         g_assert (res == 0);
3968
3969         n_pagefaults ++;
3970         mono_aot_unlock ();
3971 #endif
3972 }
3973
3974 #else
3975 /* AOT disabled */
3976
3977 void
3978 mono_aot_init (void)
3979 {
3980 }
3981
3982 gpointer
3983 mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
3984 {
3985         return NULL;
3986 }
3987
3988 gboolean
3989 mono_aot_is_got_entry (guint8 *code, guint8 *addr)
3990 {
3991         return FALSE;
3992 }
3993
3994 gboolean
3995 mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
3996 {
3997         return FALSE;
3998 }
3999
4000 gboolean
4001 mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const char *name, MonoClass **klass)
4002 {
4003         return FALSE;
4004 }
4005
4006 MonoJitInfo *
4007 mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
4008 {
4009         return NULL;
4010 }
4011
4012 gpointer
4013 mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
4014 {
4015         return NULL;
4016 }
4017
4018 guint8*
4019 mono_aot_get_plt_entry (guint8 *code)
4020 {
4021         return NULL;
4022 }
4023
4024 gpointer
4025 mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code)
4026 {
4027         return NULL;
4028 }
4029
4030 void
4031 mono_aot_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr)
4032 {
4033 }
4034
4035 gpointer
4036 mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot)
4037 {
4038         return NULL;
4039 }
4040
4041 guint32
4042 mono_aot_get_plt_info_offset (mgreg_t *regs, guint8 *code)
4043 {
4044         g_assert_not_reached ();
4045
4046         return 0;
4047 }
4048
4049 gpointer
4050 mono_aot_create_specific_trampoline (MonoImage *image, gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len)
4051 {
4052         g_assert_not_reached ();
4053         return NULL;
4054 }
4055
4056 gpointer
4057 mono_aot_get_static_rgctx_trampoline (gpointer ctx, gpointer addr)
4058 {
4059         g_assert_not_reached ();
4060         return NULL;
4061 }
4062
4063 gpointer
4064 mono_aot_get_trampoline (const char *name)
4065 {
4066         g_assert_not_reached ();
4067         return NULL;
4068 }
4069
4070 gpointer
4071 mono_aot_get_unbox_trampoline (MonoMethod *method)
4072 {
4073         g_assert_not_reached ();
4074         return NULL;
4075 }
4076
4077 gpointer
4078 mono_aot_get_lazy_fetch_trampoline (guint32 slot)
4079 {
4080         g_assert_not_reached ();
4081         return NULL;
4082 }
4083
4084 gpointer
4085 mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
4086 {
4087         g_assert_not_reached ();
4088         return NULL;
4089 }       
4090
4091 guint8*
4092 mono_aot_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len)
4093 {
4094         g_assert_not_reached ();
4095         return NULL;
4096 }
4097
4098 void
4099 mono_aot_register_jit_icall (const char *name, gpointer addr)
4100 {
4101 }
4102
4103 #endif