2007-09-30 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mono / mini / aot-runtime.c
1 /*
2  * aot.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  */
10
11 #include "config.h"
12 #include <sys/types.h>
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif
16 #include <fcntl.h>
17 #include <string.h>
18 #ifndef PLATFORM_WIN32
19 #include <sys/mman.h>
20 #else
21 #include <winsock2.h>
22 #include <windows.h>
23 #endif
24
25 #ifdef HAVE_EXECINFO_H
26 #include <execinfo.h>
27 #endif
28
29 #include <errno.h>
30 #include <sys/stat.h>
31 #include <limits.h>    /* for PAGESIZE */
32 #ifndef PAGESIZE
33 #define PAGESIZE 4096
34 #endif
35
36 #ifdef HAVE_SYS_WAIT_H
37 #include <sys/wait.h>  /* for WIFEXITED, WEXITSTATUS */
38 #endif
39
40 #include <mono/metadata/tabledefs.h>
41 #include <mono/metadata/class.h>
42 #include <mono/metadata/object.h>
43 #include <mono/metadata/tokentype.h>
44 #include <mono/metadata/appdomain.h>
45 #include <mono/metadata/debug-helpers.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/marshal.h>
49 #include <mono/metadata/gc-internal.h>
50 #include <mono/utils/mono-logger.h>
51 #include "mono/utils/mono-compiler.h"
52
53 #include "mini.h"
54
55 #ifndef DISABLE_AOT
56
57 #ifdef PLATFORM_WIN32
58 #define SHARED_EXT ".dll"
59 #elif defined(__ppc__) && defined(__MACH__)
60 #define SHARED_EXT ".dylib"
61 #else
62 #define SHARED_EXT ".so"
63 #endif
64
65 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
66 #define ROUND_DOWN(VALUE,SIZE)  ((VALUE) & ~((SIZE) - 1))
67
68 typedef struct MonoAotModule {
69         char *aot_name;
70         /* Optimization flags used to compile the module */
71         guint32 opts;
72         /* Pointer to the Global Offset Table */
73         gpointer *got;
74         guint32 got_size;
75         GHashTable *name_cache;
76         MonoAssemblyName *image_names;
77         char **image_guids;
78         MonoImage **image_table;
79         guint32 image_table_len;
80         gboolean out_of_date;
81         gboolean plt_inited;
82         guint8 *mem_begin;
83         guint8 *mem_end;
84         guint8 *code;
85         guint8 *code_end;
86         guint8 *plt;
87         guint8 *plt_end;
88         guint8 *plt_info;
89         guint8 *plt_jump_table;
90         guint32 plt_jump_table_size;
91         guint32 *code_offsets;
92         guint8 *method_info;
93         guint32 *method_info_offsets;
94         guint8 *got_info;
95         guint32 *got_info_offsets;
96         guint8 *ex_info;
97         guint32 *ex_info_offsets;
98         guint32 *method_order;
99         guint32 *method_order_end;
100         guint8 *class_info;
101         guint32 *class_info_offsets;
102         guint32 *methods_loaded;
103         guint16 *class_name_table;
104 } MonoAotModule;
105
106 static GHashTable *aot_modules;
107 #define mono_aot_lock() EnterCriticalSection (&aot_mutex)
108 #define mono_aot_unlock() LeaveCriticalSection (&aot_mutex)
109 static CRITICAL_SECTION aot_mutex;
110
111 /*
112  * Disabling this will make a copy of the loaded code and use the copy instead 
113  * of the original. This will place the caller and the callee close to each 
114  * other in memory, possibly improving cache behavior. Since the original
115  * code is in copy-on-write memory, this will not increase the memory usage
116  * of the runtime.
117  */
118 static gboolean use_loaded_code = TRUE;
119
120 /*
121  * Whenever to AOT compile loaded assemblies on demand and store them in
122  * a cache under $HOME/.mono/aot-cache.
123  */
124 static gboolean use_aot_cache = FALSE;
125
126 /*
127  * Whenever to spawn a new process to AOT a file or do it in-process. Only relevant if
128  * use_aot_cache is TRUE.
129  */
130 static gboolean spawn_compiler = TRUE;
131
132 /* For debugging */
133 static gint32 mono_last_aot_method = -1;
134
135 static gboolean make_unreadable = FALSE;
136 static guint32 n_pagefaults = 0;
137 static guint32 name_table_accesses = 0;
138
139 /* Used to speed-up find_aot_module () */
140 static gsize aot_code_low_addr = (gssize)-1;
141 static gsize aot_code_high_addr = 0;
142
143 static gpointer
144 mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod *method, guint8 *code, guint8 *info);
145
146 static void
147 init_plt (MonoAotModule *info);
148
149 static inline gboolean 
150 is_got_patch (MonoJumpInfoType patch_type)
151 {
152 #ifdef __x86_64__
153         return TRUE;
154 #elif defined(__i386__)
155         return TRUE;
156 #else
157         return FALSE;
158 #endif
159 }
160
161 /*****************************************************/
162 /*                 AOT RUNTIME                       */
163 /*****************************************************/
164
165 static MonoImage *
166 load_image (MonoAotModule *module, int index)
167 {
168         MonoAssembly *assembly;
169         MonoImageOpenStatus status;
170
171         g_assert (index < module->image_table_len);
172
173         if (module->image_table [index])
174                 return module->image_table [index];
175         if (module->out_of_date)
176                 return NULL;
177
178         assembly = mono_assembly_load (&module->image_names [index], NULL, &status);
179         if (!assembly) {
180                 module->out_of_date = TRUE;
181                 return NULL;
182         }
183
184         if (strcmp (assembly->image->guid, module->image_guids [index])) {
185                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is out of date (Older than dependency %s).\n", module->aot_name, module->image_names [index].name);
186                 module->out_of_date = TRUE;
187                 return NULL;
188         }
189
190         module->image_table [index] = assembly->image;
191         return assembly->image;
192 }
193
194
195 static inline gint32
196 decode_value (guint8 *ptr, guint8 **rptr)
197 {
198         guint8 b = *ptr;
199         gint32 len;
200         
201         if ((b & 0x80) == 0){
202                 len = b;
203                 ++ptr;
204         } else if ((b & 0x40) == 0){
205                 len = ((b & 0x3f) << 8 | ptr [1]);
206                 ptr += 2;
207         } else if (b != 0xff) {
208                 len = ((b & 0x1f) << 24) |
209                         (ptr [1] << 16) |
210                         (ptr [2] << 8) |
211                         ptr [3];
212                 ptr += 4;
213         }
214         else {
215                 len = (ptr [1] << 24) | (ptr [2] << 16) | (ptr [3] << 8) | ptr [4];
216                 ptr += 5;
217         }
218         if (rptr)
219                 *rptr = ptr;
220
221         //printf ("DECODE: %d.\n", len);
222         return len;
223 }
224
225 static MonoClass*
226 decode_klass_info (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
227 {
228         MonoImage *image;
229         MonoClass *klass;
230         guint32 token, rank, image_index;
231
232         token = decode_value (buf, &buf);
233         if (token == 0) {
234                 *endbuf = buf;
235                 return NULL;
236         }
237         image_index = decode_value (buf, &buf);
238         image = load_image (module, image_index);
239         if (!image)
240                 return NULL;
241         if (mono_metadata_token_table (token) == 0) {
242                 klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF + token);
243         } else if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC) {
244                 klass = mono_class_get (image, token);
245         } else {
246                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF);
247                 token = MONO_TOKEN_TYPE_DEF + decode_value (buf, &buf);
248                 rank = decode_value (buf, &buf);
249                 if (token == MONO_TOKEN_TYPE_DEF) {
250                         /* <Type>[][] */
251                         token = MONO_TOKEN_TYPE_DEF + decode_value (buf, &buf);
252                         klass = mono_class_get (image, token);
253                         g_assert (klass);
254                         klass = mono_array_class_get (klass, rank);
255
256                         rank = decode_value (buf, &buf);
257                         klass = mono_array_class_get (klass, rank);
258                 } else {
259                         klass = mono_class_get (image, token);
260                         g_assert (klass);
261                         klass = mono_array_class_get (klass, rank);
262                 }
263         }
264         g_assert (klass);
265         mono_class_init (klass);
266
267         *endbuf = buf;
268         return klass;
269 }
270
271 static MonoClassField*
272 decode_field_info (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
273 {
274         MonoClass *klass = decode_klass_info (module, buf, &buf);
275         guint32 token;
276
277         if (!klass)
278                 return NULL;
279
280         token = MONO_TOKEN_FIELD_DEF + decode_value (buf, &buf);
281
282         *endbuf = buf;
283
284         return mono_class_get_field (klass, token);
285 }
286
287 static inline MonoImage*
288 decode_method_ref (MonoAotModule *module, guint32 *token, guint8 *buf, guint8 **endbuf)
289 {
290         guint32 image_index, value;
291         MonoImage *image;
292
293         value = decode_value (buf, &buf);
294         *endbuf = buf;
295         image_index = value >> 24;
296         *token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
297
298         if (image_index == 255) {
299                 /* Methodspec */
300                 image_index = decode_value (buf, &buf);
301                 *token = decode_value (buf, &buf);
302         }
303
304         image = load_image (module, image_index);
305         if (!image)
306                 return NULL;
307         else
308                 return image;
309 }
310
311 G_GNUC_UNUSED
312 static void
313 make_writable (guint8* addr, guint32 len)
314 {
315 #ifndef PLATFORM_WIN32
316         guint8 *page_start;
317         int pages, err;
318
319         page_start = (guint8 *) (((gssize) (addr)) & ~ (PAGESIZE - 1));
320         pages = (addr + len - page_start + PAGESIZE - 1) / PAGESIZE;
321         err = mprotect (page_start, pages * PAGESIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
322         g_assert (err == 0);
323 #else
324         {
325                 DWORD oldp;
326                 g_assert (VirtualProtect (addr, len, PAGE_EXECUTE_READWRITE, &oldp) != 0);
327         }
328 #endif
329 }
330
331 static void
332 create_cache_structure (void)
333 {
334         const char *home;
335         char *tmp;
336         int err;
337
338         home = g_get_home_dir ();
339         if (!home)
340                 return;
341
342         tmp = g_build_filename (home, ".mono", NULL);
343         if (!g_file_test (tmp, G_FILE_TEST_IS_DIR)) {
344                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT creating directory %s", tmp);
345 #ifdef PLATFORM_WIN32
346                 err = mkdir (tmp);
347 #else
348                 err = mkdir (tmp, 0777);
349 #endif
350                 if (err) {
351                         mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT failed: %s", g_strerror (errno));
352                         g_free (tmp);
353                         return;
354                 }
355         }
356         g_free (tmp);
357         tmp = g_build_filename (home, ".mono", "aot-cache", NULL);
358         if (!g_file_test (tmp, G_FILE_TEST_IS_DIR)) {
359                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT creating directory %s", tmp);
360 #ifdef PLATFORM_WIN32
361                 err = mkdir (tmp);
362 #else
363                 err = mkdir (tmp, 0777);
364 #endif
365                 if (err) {
366                         mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT failed: %s", g_strerror (errno));
367                         g_free (tmp);
368                         return;
369                 }
370         }
371         g_free (tmp);
372 }
373
374 /*
375  * load_aot_module_from_cache:
376  *
377  *  Experimental code to AOT compile loaded assemblies on demand. 
378  *
379  * FIXME: 
380  * - Add environment variable MONO_AOT_CACHE_OPTIONS
381  * - Add options for controlling the cache size
382  * - Handle full cache by deleting old assemblies lru style
383  * - Add options for excluding assemblies during development
384  * - Maybe add a threshold after an assembly is AOT compiled
385  * - invoking a new mono process is a security risk
386  * - recompile the AOT module if one of its dependencies changes
387  */
388 static MonoDl*
389 load_aot_module_from_cache (MonoAssembly *assembly, char **aot_name)
390 {
391         char *fname, *cmd, *tmp2, *aot_options;
392         const char *home;
393         MonoDl *module;
394         gboolean res;
395         gchar *out, *err;
396         gint exit_status;
397
398         *aot_name = NULL;
399
400         if (assembly->image->dynamic)
401                 return NULL;
402
403         create_cache_structure ();
404
405         home = g_get_home_dir ();
406
407         tmp2 = g_strdup_printf ("%s-%s%s", assembly->image->assembly_name, assembly->image->guid, SHARED_EXT);
408         fname = g_build_filename (home, ".mono", "aot-cache", tmp2, NULL);
409         *aot_name = fname;
410         g_free (tmp2);
411
412         mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT trying to load from cache: '%s'.", fname);
413         module = mono_dl_open (fname, MONO_DL_LAZY, NULL);
414
415         if (!module) {
416                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT not found.");
417
418                 mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT precompiling assembly '%s'... ", assembly->image->name);
419
420                 aot_options = g_strdup_printf ("outfile=%s", fname);
421
422                 if (spawn_compiler) {
423                         /* FIXME: security */
424                         /* FIXME: Has to pass the assembly loading path to the child process */
425                         cmd = g_strdup_printf ("mono -O=all --aot=%s %s", aot_options, assembly->image->name);
426
427                         res = g_spawn_command_line_sync (cmd, &out, &err, &exit_status, NULL);
428
429 #if !defined(PLATFORM_WIN32) && !defined(__ppc__) && !defined(__powerpc__)
430                         if (res) {
431                                 if (!WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) == 0))
432                                         mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT failed: %s.", err);
433                                 else
434                                         mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT succeeded.");
435                                 g_free (out);
436                                 g_free (err);
437                         }
438 #endif
439                         g_free (cmd);
440                 } else {
441                         res = mono_compile_assembly (assembly, mono_parse_default_optimizations (NULL), aot_options);
442                         if (!res) {
443                                 mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT failed.");
444                         } else {
445                                 mono_trace (G_LOG_LEVEL_MESSAGE, MONO_TRACE_AOT, "AOT succeeded.");
446                         }
447                 }
448
449                 module = mono_dl_open (fname, MONO_DL_LAZY, NULL);
450
451                 g_free (aot_options);
452         }
453
454         return module;
455 }
456
457 static void
458 load_aot_module (MonoAssembly *assembly, gpointer user_data)
459 {
460         char *aot_name;
461         MonoAotModule *info;
462         gboolean usable = TRUE;
463         char *saved_guid = NULL;
464         char *aot_version = NULL;
465         char *opt_flags = NULL;
466         gpointer *plt_jump_table_addr = NULL;
467         guint32 *plt_jump_table_size = NULL;
468         gpointer *got_addr = NULL;
469         gpointer *got = NULL;
470         guint32 *got_size_ptr = NULL;
471         int i;
472
473         if (mono_compile_aot)
474                 return;
475
476         if (assembly->aot_module)
477                 /* 
478                  * Already loaded. This can happen because the assembly loading code might invoke
479                  * the assembly load hooks multiple times for the same assembly.
480                  */
481                 return;
482
483         if (use_aot_cache)
484                 assembly->aot_module = load_aot_module_from_cache (assembly, &aot_name);
485         else {
486                 char *err;
487                 aot_name = g_strdup_printf ("%s%s", assembly->image->name, SHARED_EXT);
488
489                 assembly->aot_module = mono_dl_open (aot_name, MONO_DL_LAZY, &err);
490
491                 if (!assembly->aot_module) {
492                         mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT failed to load AOT module %s: %s\n", aot_name, err);
493                         g_free (err);
494                 }
495         }
496
497         if (!assembly->aot_module) {
498                 g_free (aot_name);
499                 return;
500         }
501
502         mono_dl_symbol (assembly->aot_module, "mono_assembly_guid", (gpointer *) &saved_guid);
503         mono_dl_symbol (assembly->aot_module, "mono_aot_version", (gpointer *) &aot_version);
504         mono_dl_symbol (assembly->aot_module, "mono_aot_opt_flags", (gpointer *)&opt_flags);
505
506         if (!aot_version || strcmp (aot_version, MONO_AOT_FILE_VERSION)) {
507                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s has wrong file format version (expected %s got %s)\n", aot_name, MONO_AOT_FILE_VERSION, aot_version);
508                 usable = FALSE;
509         }
510         else {
511                 if (!saved_guid || strcmp (assembly->image->guid, saved_guid)) {
512                         mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is out of date.\n", aot_name);
513                         usable = FALSE;
514                 }
515         }
516
517         if (!usable) {
518                 g_free (aot_name);
519                 mono_dl_close (assembly->aot_module);
520                 assembly->aot_module = NULL;
521                 return;
522         }
523
524         mono_dl_symbol (assembly->aot_module, "got_addr", (gpointer *)&got_addr);
525         g_assert (got_addr);
526         got = (gpointer*)*got_addr;
527         g_assert (got);
528         mono_dl_symbol (assembly->aot_module, "got_size", (gpointer *)&got_size_ptr);
529         g_assert (got_size_ptr);
530
531         info = g_new0 (MonoAotModule, 1);
532         info->aot_name = aot_name;
533         info->got = got;
534         info->got_size = *got_size_ptr;
535         info->got [0] = assembly->image;
536
537         sscanf (opt_flags, "%d", &info->opts);
538
539         /* Read image table */
540         {
541                 guint32 table_len, i;
542                 char *table = NULL;
543
544                 mono_dl_symbol (assembly->aot_module, "mono_image_table", (gpointer *)&table);
545                 g_assert (table);
546
547                 table_len = *(guint32*)table;
548                 table += sizeof (guint32);
549                 info->image_table = g_new0 (MonoImage*, table_len);
550                 info->image_names = g_new0 (MonoAssemblyName, table_len);
551                 info->image_guids = g_new0 (char*, table_len);
552                 info->image_table_len = table_len;
553                 for (i = 0; i < table_len; ++i) {
554                         MonoAssemblyName *aname = &(info->image_names [i]);
555
556                         aname->name = g_strdup (table);
557                         table += strlen (table) + 1;
558                         info->image_guids [i] = g_strdup (table);
559                         table += strlen (table) + 1;
560                         if (table [0] != 0)
561                                 aname->culture = g_strdup (table);
562                         table += strlen (table) + 1;
563                         memcpy (aname->public_key_token, table, strlen (table) + 1);
564                         table += strlen (table) + 1;                    
565
566                         table = ALIGN_PTR_TO (table, 8);
567                         aname->flags = *(guint32*)table;
568                         table += 4;
569                         aname->major = *(guint32*)table;
570                         table += 4;
571                         aname->minor = *(guint32*)table;
572                         table += 4;
573                         aname->build = *(guint32*)table;
574                         table += 4;
575                         aname->revision = *(guint32*)table;
576                         table += 4;
577                 }
578         }
579
580         /* Read method and method_info tables */
581         mono_dl_symbol (assembly->aot_module, "method_offsets", (gpointer*)&info->code_offsets);
582         mono_dl_symbol (assembly->aot_module, "methods", (gpointer*)&info->code);
583         mono_dl_symbol (assembly->aot_module, "methods_end", (gpointer*)&info->code_end);
584         mono_dl_symbol (assembly->aot_module, "method_info_offsets", (gpointer*)&info->method_info_offsets);
585         mono_dl_symbol (assembly->aot_module, "method_info", (gpointer*)&info->method_info);
586         mono_dl_symbol (assembly->aot_module, "ex_info_offsets", (gpointer*)&info->ex_info_offsets);
587         mono_dl_symbol (assembly->aot_module, "ex_info", (gpointer*)&info->ex_info);
588         mono_dl_symbol (assembly->aot_module, "method_order", (gpointer*)&info->method_order);
589         mono_dl_symbol (assembly->aot_module, "method_order_end", (gpointer*)&info->method_order_end);
590         mono_dl_symbol (assembly->aot_module, "class_info", (gpointer*)&info->class_info);
591         mono_dl_symbol (assembly->aot_module, "class_info_offsets", (gpointer*)&info->class_info_offsets);
592         mono_dl_symbol (assembly->aot_module, "class_name_table", (gpointer *)&info->class_name_table);
593         mono_dl_symbol (assembly->aot_module, "got_info", (gpointer*)&info->got_info);
594         mono_dl_symbol (assembly->aot_module, "got_info_offsets", (gpointer*)&info->got_info_offsets);
595         mono_dl_symbol (assembly->aot_module, "mem_end", (gpointer*)&info->mem_end);
596
597         info->mem_begin = info->code;
598
599         mono_dl_symbol (assembly->aot_module, "plt", (gpointer*)&info->plt);
600         mono_dl_symbol (assembly->aot_module, "plt_end", (gpointer*)&info->plt_end);
601         mono_dl_symbol (assembly->aot_module, "plt_info", (gpointer*)&info->plt_info);
602
603         mono_dl_symbol (assembly->aot_module, "plt_jump_table_addr", (gpointer *)&plt_jump_table_addr);
604         g_assert (plt_jump_table_addr);
605         info->plt_jump_table = (guint8*)*plt_jump_table_addr;
606         g_assert (info->plt_jump_table);
607
608         mono_dl_symbol (assembly->aot_module, "plt_jump_table_size", (gpointer *)&plt_jump_table_size);
609         g_assert (plt_jump_table_size);
610         info->plt_jump_table_size = *plt_jump_table_size;
611
612         if (make_unreadable) {
613 #ifndef PLATFORM_WIN32
614                 guint8 *addr;
615                 guint8 *page_start;
616                 int pages, err, len;
617
618                 addr = info->mem_begin;
619                 len = info->mem_end - info->mem_begin;
620
621                 /* Round down in both directions to avoid modifying data which is not ours */
622                 page_start = (guint8 *) (((gssize) (addr)) & ~ (PAGESIZE - 1)) + PAGESIZE;
623                 pages = ((addr + len - page_start + PAGESIZE - 1) / PAGESIZE) - 1;
624                 err = mprotect (page_start, pages * PAGESIZE, 0);
625                 g_assert (err == 0);
626 #endif
627         }
628
629         mono_aot_lock ();
630
631         aot_code_low_addr = MIN (aot_code_low_addr, (gsize)info->code);
632         aot_code_high_addr = MAX (aot_code_high_addr, (gsize)info->code_end);
633
634         g_hash_table_insert (aot_modules, assembly, info);
635         mono_aot_unlock ();
636
637         mono_jit_info_add_aot_module (assembly->image, info->code, info->code_end);
638
639         /*
640          * Since we store methoddef and classdef tokens when referring to methods/classes in
641          * referenced assemblies, we depend on the exact versions of the referenced assemblies.
642          * MS calls this 'hard binding'. This means we have to load all referenced assemblies
643          * non-lazily, since we can't handle out-of-date errors later.
644          */
645         for (i = 0; i < info->image_table_len; ++i)
646                 load_image (info, i);
647
648         if (info->out_of_date)
649                 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);
650         else
651                 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT loaded AOT Module for %s.\n", assembly->image->name);
652 }
653
654 void
655 mono_aot_init (void)
656 {
657         InitializeCriticalSection (&aot_mutex);
658         aot_modules = g_hash_table_new (NULL, NULL);
659
660         mono_install_assembly_load_hook (load_aot_module, NULL);
661
662         if (getenv ("MONO_LASTAOT"))
663                 mono_last_aot_method = atoi (getenv ("MONO_LASTAOT"));
664         if (getenv ("MONO_AOT_CACHE"))
665                 use_aot_cache = TRUE;
666 }
667
668 static gboolean
669 decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guint8 *buf, guint8 **endbuf)
670 {
671         guint32 flags;
672
673         info->vtable_size = decode_value (buf, &buf);
674         if (info->vtable_size == -1)
675                 /* Generic type */
676                 return FALSE;
677         flags = decode_value (buf, &buf);
678         info->ghcimpl = (flags >> 0) & 0x1;
679         info->has_finalize = (flags >> 1) & 0x1;
680         info->has_cctor = (flags >> 2) & 0x1;
681         info->has_nested_classes = (flags >> 3) & 0x1;
682         info->blittable = (flags >> 4) & 0x1;
683         info->has_references = (flags >> 5) & 0x1;
684         info->has_static_refs = (flags >> 6) & 0x1;
685         info->no_special_static_fields = (flags >> 7) & 0x1;
686
687         if (info->has_cctor) {
688                 MonoImage *cctor_image = decode_method_ref (module, &info->cctor_token, buf, &buf);
689                 if (!cctor_image)
690                         return FALSE;
691         }
692         if (info->has_finalize) {
693                 info->finalize_image = decode_method_ref (module, &info->finalize_token, buf, &buf);
694                 if (!info->finalize_image)
695                         return FALSE;
696         }
697
698         info->instance_size = decode_value (buf, &buf);
699         info->class_size = decode_value (buf, &buf);
700         info->packing_size = decode_value (buf, &buf);
701         info->min_align = decode_value (buf, &buf);
702
703         *endbuf = buf;
704
705         return TRUE;
706 }       
707
708 gboolean
709 mono_aot_init_vtable (MonoVTable *vtable)
710 {
711         int i;
712         MonoAotModule *aot_module;
713         MonoClass *klass = vtable->klass;
714         guint8 *info, *p;
715         MonoCachedClassInfo class_info;
716         gboolean err;
717
718         if (MONO_CLASS_IS_INTERFACE (klass) || klass->rank || !klass->image->assembly->aot_module)
719                 return FALSE;
720
721         mono_aot_lock ();
722
723         aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, klass->image->assembly);
724         if (!aot_module) {
725                 mono_aot_unlock ();
726                 return FALSE;
727         }
728
729         info = &aot_module->class_info [aot_module->class_info_offsets [mono_metadata_token_index (klass->type_token) - 1]];
730         p = info;
731
732         err = decode_cached_class_info (aot_module, &class_info, p, &p);
733         if (!err) {
734                 mono_aot_unlock ();
735                 return FALSE;
736         }
737
738         //printf ("VT0: %s.%s %d\n", klass->name_space, klass->name, vtable_size);
739         for (i = 0; i < class_info.vtable_size; ++i) {
740                 guint32 image_index, token, value;
741                 MonoImage *image;
742 #ifndef MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN
743                 MonoMethod *m;
744 #endif
745
746                 vtable->vtable [i] = 0;
747
748                 value = decode_value (p, &p);
749                 if (!value)
750                         continue;
751
752                 image_index = value >> 24;
753                 token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
754
755                 image = load_image (aot_module, image_index);
756                 if (!image) {
757                         mono_aot_unlock ();
758                         return FALSE;
759                 }
760
761 #ifdef MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN
762                 vtable->vtable [i] = mono_create_jit_trampoline_from_token (image, token);
763 #else
764                 m = mono_get_method (image, token, NULL);
765                 g_assert (m);
766
767                 //printf ("M: %d %p %s\n", i, &(vtable->vtable [i]), mono_method_full_name (m, TRUE));
768                 vtable->vtable [i] = mono_create_jit_trampoline (m);
769 #endif
770         }
771
772         mono_aot_unlock ();
773
774         return TRUE;
775 }
776
777 gboolean
778 mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
779 {
780         MonoAotModule *aot_module;
781         guint8 *p;
782         gboolean err;
783
784         if (klass->rank || !klass->image->assembly->aot_module)
785                 return FALSE;
786
787         mono_aot_lock ();
788
789         aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, klass->image->assembly);
790         if (!aot_module) {
791                 mono_aot_unlock ();
792                 return FALSE;
793         }
794
795         p = (guint8*)&aot_module->class_info [aot_module->class_info_offsets [mono_metadata_token_index (klass->type_token) - 1]];
796
797         err = decode_cached_class_info (aot_module, res, p, &p);
798         if (!err) {
799                 mono_aot_unlock ();
800                 return FALSE;
801         }
802
803         mono_aot_unlock ();
804
805         return TRUE;
806 }
807
808 /**
809  * mono_aot_get_class_from_name:
810  *
811  *  Obtains a MonoClass with a given namespace and a given name which is located in IMAGE,
812  * using a cache stored in the AOT file.
813  * Stores the resulting class in *KLASS if found, stores NULL otherwise.
814  *
815  * Returns: TRUE if the klass was found/not found in the cache, FALSE if no aot file was 
816  * found.
817  */
818 gboolean
819 mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const char *name, MonoClass **klass)
820 {
821         MonoAotModule *aot_module;
822         guint16 *table, *entry;
823         guint16 table_size;
824         guint32 hash;
825         char full_name_buf [1024];
826         char *full_name;
827         const char *name2, *name_space2;
828         MonoTableInfo  *t;
829         guint32 cols [MONO_TYPEDEF_SIZE];
830         GHashTable *nspace_table;
831
832         if (!aot_modules)
833                 return FALSE;
834
835         mono_aot_lock ();
836
837         aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, image->assembly);
838         if (!aot_module || !aot_module->class_name_table) {
839                 mono_aot_unlock ();
840                 return FALSE;
841         }
842
843         *klass = NULL;
844
845         /* First look in the cache */
846         if (!aot_module->name_cache)
847                 aot_module->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
848         nspace_table = g_hash_table_lookup (aot_module->name_cache, name_space);
849         if (nspace_table) {
850                 *klass = g_hash_table_lookup (nspace_table, name);
851                 if (*klass) {
852                         mono_aot_unlock ();
853                         return TRUE;
854                 }
855         }
856
857         table_size = aot_module->class_name_table [0];
858         table = aot_module->class_name_table + 1;
859
860         if (name_space [0] == '\0')
861                 full_name = g_strdup_printf ("%s", name);
862         else {
863                 if (strlen (name_space) + strlen (name) < 1000) {
864                         sprintf (full_name_buf, "%s.%s", name_space, name);
865                         full_name = full_name_buf;
866                 } else {
867                         full_name = g_strdup_printf ("%s.%s", name_space, name);
868                 }
869         }
870         hash = g_str_hash (full_name) % table_size;
871         if (full_name != full_name_buf)
872                 g_free (full_name);
873
874         entry = &table [hash * 2];
875
876         if (entry [0] != 0) {
877                 t = &image->tables [MONO_TABLE_TYPEDEF];
878
879                 while (TRUE) {
880                         guint32 index = entry [0];
881                         guint32 next = entry [1];
882                         guint32 token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, index);
883
884                         name_table_accesses ++;
885
886                         mono_metadata_decode_row (t, index - 1, cols, MONO_TYPEDEF_SIZE);
887
888                         name2 = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
889                         name_space2 = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
890
891                         if (!strcmp (name, name2) && !strcmp (name_space, name_space2)) {
892                                 mono_aot_unlock ();
893                                 *klass = mono_class_get (image, token);
894
895                                 /* Add to cache */
896                                 if (*klass) {
897                                         mono_aot_lock ();
898                                         nspace_table = g_hash_table_lookup (aot_module->name_cache, name_space);
899                                         if (!nspace_table) {
900                                                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
901                                                 g_hash_table_insert (aot_module->name_cache, (char*)name_space2, nspace_table);
902                                         }
903                                         g_hash_table_insert (nspace_table, (char*)name2, *klass);
904                                         mono_aot_unlock ();
905                                 }
906                                 return TRUE;
907                         }
908
909                         if (next != 0) {
910                                 entry = &table [next * 2];
911                         } else {
912                                 break;
913                         }
914                 }
915         }
916
917         mono_aot_unlock ();
918         
919         return TRUE;
920 }
921
922 static MonoJitInfo*
923 decode_exception_debug_info (MonoAotModule *aot_module, MonoDomain *domain, 
924                                                          MonoMethod *method, guint8* ex_info, guint8 *code)
925 {
926         int i, buf_len;
927         MonoJitInfo *jinfo;
928         guint code_len, used_int_regs;
929         guint8 *p;
930         MonoMethodHeader *header;
931
932         header = mono_method_get_header (method);
933
934         /* Load the method info from the AOT file */
935
936         p = ex_info;
937         code_len = decode_value (p, &p);
938         used_int_regs = decode_value (p, &p);
939
940         /* Exception table */
941         if (header->num_clauses) {
942                 jinfo = 
943                         mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo) + (sizeof (MonoJitExceptionInfo) * header->num_clauses));
944                 jinfo->num_clauses = header->num_clauses;
945
946                 for (i = 0; i < header->num_clauses; ++i) {
947                         MonoExceptionClause *ec = &header->clauses [i];                         
948                         MonoJitExceptionInfo *ei = &jinfo->clauses [i];
949
950                         ei->flags = ec->flags;
951                         ei->exvar_offset = decode_value (p, &p);
952
953                         if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
954                                 ei->data.filter = code + decode_value (p, &p);
955                         else
956                                 ei->data.catch_class = ec->data.catch_class;
957
958                         ei->try_start = code + decode_value (p, &p);
959                         ei->try_end = code + decode_value (p, &p);
960                         ei->handler_start = code + decode_value (p, &p);
961                 }
962         }
963         else
964                 jinfo = mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo));
965
966         jinfo->code_size = code_len;
967         jinfo->used_regs = used_int_regs;
968         jinfo->method = method;
969         jinfo->code_start = code;
970         jinfo->domain_neutral = 0;
971
972         /* Load debug info */
973         buf_len = decode_value (p, &p);
974         mono_debug_add_aot_method (domain, method, code, p, buf_len);
975         
976         return jinfo;
977 }
978
979 MonoJitInfo *
980 mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
981 {
982         MonoAssembly *ass = image->assembly;
983         MonoDl *module = ass->aot_module;
984         int pos, left, right, offset, offset1, offset2, last_offset, new_offset, page_index, method_index, table_len;
985         guint32 token;
986         MonoAotModule *aot_module;
987         MonoMethod *method;
988         MonoJitInfo *jinfo;
989         guint8 *code, *ex_info;
990         guint32 *table, *ptr;
991         gboolean found;
992
993         if (!module)
994                 return NULL;
995
996         aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, ass);
997
998         if (domain != mono_get_root_domain ())
999                 /* FIXME: */
1000                 return NULL;
1001
1002         offset = (guint8*)addr - aot_module->code;
1003
1004         /* First search through the index */
1005         ptr = aot_module->method_order;
1006         last_offset = 0;
1007         page_index = 0;
1008         found = FALSE;
1009
1010         if (*ptr == 0xffffff)
1011                 return NULL;
1012         ptr ++;
1013
1014         while (*ptr != 0xffffff) {
1015                 guint32 method_index = ptr [0];
1016                 new_offset = aot_module->code_offsets [method_index];
1017
1018                 if (offset >= last_offset && offset < new_offset) {
1019                         found = TRUE;
1020                         break;
1021                 }
1022
1023                 ptr ++;
1024                 last_offset = new_offset;
1025                 page_index ++;
1026         }
1027
1028         /* Skip rest of index */
1029         while (*ptr != 0xffffff)
1030                 ptr ++;
1031         ptr ++;
1032
1033         table = ptr;
1034         table_len = aot_module->method_order_end - table;
1035
1036         g_assert (table <= aot_module->method_order_end);
1037
1038         if (found) {
1039                 left = (page_index * 1024);
1040                 right = left + 1024;
1041
1042                 if (right > table_len)
1043                         right = table_len;
1044
1045                 offset1 = aot_module->code_offsets [table [left]];
1046                 g_assert (offset1 <= offset);
1047
1048                 //printf ("Found in index: 0x%x 0x%x 0x%x\n", offset, last_offset, new_offset);
1049         }
1050         else {
1051                 //printf ("Not found in index: 0x%x\n", offset);
1052                 left = 0;
1053                 right = table_len;
1054         }
1055
1056         /* Binary search inside the method_order table to find the method */
1057         while (TRUE) {
1058                 pos = (left + right) / 2;
1059
1060                 g_assert (table + pos <= aot_module->method_order_end);
1061
1062                 //printf ("Pos: %5d < %5d < %5d Offset: 0x%05x < 0x%05x < 0x%05x\n", left, pos, right, aot_module->code_offsets [table [left]], offset, aot_module->code_offsets [table [right]]);
1063
1064                 offset1 = aot_module->code_offsets [table [pos]];
1065                 if (table + pos + 1 >= aot_module->method_order_end)
1066                         offset2 = aot_module->code_end - aot_module->code;
1067                 else
1068                         offset2 = aot_module->code_offsets [table [pos + 1]];
1069
1070                 if (offset < offset1)
1071                         right = pos;
1072                 else if (offset >= offset2)
1073                         left = pos + 1;
1074                 else
1075                         break;
1076         }
1077
1078         method_index = table [pos];
1079
1080         token = mono_metadata_make_token (MONO_TABLE_METHOD, method_index + 1);
1081         method = mono_get_method (image, token, NULL);
1082
1083         /* FIXME: */
1084         g_assert (method);
1085
1086         //printf ("F: %s\n", mono_method_full_name (method, TRUE));
1087
1088         code = &aot_module->code [aot_module->code_offsets [method_index]];
1089         ex_info = &aot_module->ex_info [aot_module->ex_info_offsets [method_index]];
1090
1091         jinfo = decode_exception_debug_info (aot_module, domain, method, ex_info, code);
1092
1093         g_assert ((guint8*)addr >= (guint8*)jinfo->code_start);
1094         g_assert ((guint8*)addr < (guint8*)jinfo->code_start + jinfo->code_size);
1095
1096         /* Add it to the normal JitInfo tables */
1097         mono_jit_info_table_add (domain, jinfo);
1098         
1099         return jinfo;
1100 }
1101
1102 static gboolean
1103 decode_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guint8 *buf, guint8 **endbuf, guint32 *got_offset)
1104 {
1105         guint8 *p = buf;
1106         gpointer *table;
1107         MonoImage *image;
1108         int i;
1109
1110         switch (ji->type) {
1111         case MONO_PATCH_INFO_METHOD:
1112         case MONO_PATCH_INFO_METHODCONST:
1113         case MONO_PATCH_INFO_METHOD_JUMP: {
1114                 guint32 token;
1115
1116                 image = decode_method_ref (aot_module, &token, p, &p);
1117                 if (!image)
1118                         goto cleanup;
1119
1120 #ifdef MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN
1121                 if ((ji->type == MONO_PATCH_INFO_METHOD) && (mono_metadata_token_table (token) == MONO_TABLE_METHOD)) {
1122                         ji->data.target = mono_create_jit_trampoline_from_token (image, token);
1123                         ji->type = MONO_PATCH_INFO_ABS;
1124                 }
1125                 else {
1126                         ji->data.method = mono_get_method (image, token, NULL);
1127                         g_assert (ji->data.method);
1128                         mono_class_init (ji->data.method->klass);
1129                 }
1130 #else
1131                 ji->data.method = mono_get_method (image, token, NULL);
1132                 g_assert (ji->data.method);
1133                 mono_class_init (ji->data.method->klass);
1134 #endif
1135
1136                 break;
1137         }
1138         case MONO_PATCH_INFO_WRAPPER: {
1139                 guint32 wrapper_type;
1140
1141                 wrapper_type = decode_value (p, &p);
1142
1143                 switch (wrapper_type) {
1144                 case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: {
1145                         guint32 image_index, token, value;
1146
1147                         value = decode_value (p, &p);
1148                         image_index = value >> 24;
1149                         token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
1150
1151                         image = load_image (aot_module, image_index);
1152                         if (!image)
1153                                 goto cleanup;
1154                         ji->data.method = mono_get_method (image, token, NULL);
1155                         g_assert (ji->data.method);
1156                         mono_class_init (ji->data.method->klass);
1157
1158                         ji->type = MONO_PATCH_INFO_METHOD;
1159                         ji->data.method = mono_marshal_get_remoting_invoke_with_check (ji->data.method);
1160                         break;
1161                 }
1162                 case MONO_WRAPPER_PROXY_ISINST: {
1163                         MonoClass *klass = decode_klass_info (aot_module, p, &p);
1164                         if (!klass)
1165                                 goto cleanup;
1166                         ji->type = MONO_PATCH_INFO_METHOD;
1167                         ji->data.method = mono_marshal_get_proxy_cancast (klass);
1168                         break;
1169                 }
1170                 case MONO_WRAPPER_LDFLD:
1171                 case MONO_WRAPPER_LDFLDA:
1172                 case MONO_WRAPPER_STFLD:
1173                 case MONO_WRAPPER_LDFLD_REMOTE:
1174                 case MONO_WRAPPER_STFLD_REMOTE:
1175                 case MONO_WRAPPER_ISINST: {
1176                         MonoClass *klass = decode_klass_info (aot_module, p, &p);
1177                         if (!klass)
1178                                 goto cleanup;
1179                         ji->type = MONO_PATCH_INFO_METHOD;
1180                         if (wrapper_type == MONO_WRAPPER_LDFLD)
1181                                 ji->data.method = mono_marshal_get_ldfld_wrapper (&klass->byval_arg);
1182                         else if (wrapper_type == MONO_WRAPPER_LDFLDA)
1183                                 ji->data.method = mono_marshal_get_ldflda_wrapper (&klass->byval_arg);
1184                         else if (wrapper_type == MONO_WRAPPER_STFLD)
1185                                 ji->data.method = mono_marshal_get_stfld_wrapper (&klass->byval_arg);
1186                         else if (wrapper_type == MONO_WRAPPER_LDFLD_REMOTE)
1187                                 ji->data.method = mono_marshal_get_ldfld_remote_wrapper (klass);
1188                         else if (wrapper_type == MONO_WRAPPER_STFLD_REMOTE)
1189                                 ji->data.method = mono_marshal_get_stfld_remote_wrapper (klass);
1190                         else if (wrapper_type == MONO_WRAPPER_ISINST)
1191                                 ji->data.method = mono_marshal_get_isinst (klass);
1192                         else
1193                                 g_assert_not_reached ();
1194                         break;
1195                 }
1196                 case MONO_WRAPPER_ALLOC: {
1197                         int atype = decode_value (p, &p);
1198
1199                         ji->type = MONO_PATCH_INFO_METHOD;
1200                         ji->data.method = mono_gc_get_managed_allocator_by_type (atype);
1201                         break;
1202                 }
1203                 case MONO_WRAPPER_STELEMREF:
1204                         ji->type = MONO_PATCH_INFO_METHOD;
1205                         ji->data.method = mono_marshal_get_stelemref ();
1206                         break;
1207                 default:
1208                         g_assert_not_reached ();
1209                 }
1210                 break;
1211         }
1212         case MONO_PATCH_INFO_INTERNAL_METHOD: {
1213                 guint32 len = decode_value (p, &p);
1214
1215                 ji->data.name = (char*)p;
1216                 p += len + 1;
1217                 break;
1218         }
1219         case MONO_PATCH_INFO_VTABLE:
1220         case MONO_PATCH_INFO_CLASS:
1221         case MONO_PATCH_INFO_IID:
1222         case MONO_PATCH_INFO_ADJUSTED_IID:
1223                 *got_offset = decode_value (p, &p);
1224
1225                 if (aot_module->got [*got_offset]) {
1226                         /* Already loaded */
1227                         //printf ("HIT!\n");
1228                 } else {
1229                         guint8 *tmp = aot_module->got_info + aot_module->got_info_offsets [*got_offset];
1230                         ji->data.klass = decode_klass_info (aot_module, tmp, &tmp);
1231                         if (!ji->data.klass)
1232                                 goto cleanup;
1233                 }
1234                 break;
1235         case MONO_PATCH_INFO_CLASS_INIT:
1236                 ji->data.klass = decode_klass_info (aot_module, p, &p);
1237                 if (!ji->data.klass)
1238                         goto cleanup;
1239                 break;
1240         case MONO_PATCH_INFO_IMAGE:
1241                 ji->data.image = load_image (aot_module, decode_value (p, &p));
1242                 if (!ji->data.image)
1243                         goto cleanup;
1244                 break;
1245         case MONO_PATCH_INFO_FIELD:
1246         case MONO_PATCH_INFO_SFLDA:
1247                 *got_offset = decode_value (p, &p);
1248
1249                 if (aot_module->got [*got_offset]) {
1250                         /* Already loaded */
1251                         //printf ("HIT2!\n");
1252                 } else {
1253                         guint8 *tmp = aot_module->got_info + aot_module->got_info_offsets [*got_offset];
1254                         ji->data.field = decode_field_info (aot_module, tmp, &tmp);
1255                         if (!ji->data.field)
1256                                 goto cleanup;
1257                 }
1258                 break;
1259         case MONO_PATCH_INFO_SWITCH:
1260                 ji->data.table = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoBBTable));
1261                 ji->data.table->table_size = decode_value (p, &p);
1262                 table = g_new (gpointer, ji->data.table->table_size);
1263                 ji->data.table->table = (MonoBasicBlock**)table;
1264                 for (i = 0; i < ji->data.table->table_size; i++)
1265                         table [i] = (gpointer)(gssize)decode_value (p, &p);
1266                 break;
1267         case MONO_PATCH_INFO_R4: {
1268                 guint32 val;
1269                 
1270                 ji->data.target = mono_mempool_alloc0 (mp, sizeof (float));
1271                 val = decode_value (p, &p);
1272                 *(float*)ji->data.target = *(float*)&val;
1273                 break;
1274         }
1275         case MONO_PATCH_INFO_R8: {
1276                 guint32 val [2];
1277
1278                 ji->data.target = mono_mempool_alloc0 (mp, sizeof (double));
1279
1280                 val [0] = decode_value (p, &p);
1281                 val [1] = decode_value (p, &p);
1282                 *(double*)ji->data.target = *(double*)val;
1283                 break;
1284         }
1285         case MONO_PATCH_INFO_LDSTR:
1286                 image = load_image (aot_module, decode_value (p, &p));
1287                 if (!image)
1288                         goto cleanup;
1289                 ji->data.token = mono_jump_info_token_new (mp, image, MONO_TOKEN_STRING + decode_value (p, &p));
1290                 break;
1291         case MONO_PATCH_INFO_RVA:
1292         case MONO_PATCH_INFO_DECLSEC:
1293         case MONO_PATCH_INFO_LDTOKEN:
1294         case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1295                 *got_offset = decode_value (p, &p);
1296
1297                 if (aot_module->got [*got_offset]) {
1298                         /* Already loaded */
1299                 } else {
1300                         guint8 *tmp = aot_module->got_info + aot_module->got_info_offsets [*got_offset];
1301                         image = load_image (aot_module, decode_value (tmp, &tmp));
1302                         if (!image)
1303                                 goto cleanup;
1304                         ji->data.token = mono_jump_info_token_new (mp, image, decode_value (tmp, &tmp));
1305                 }
1306                 break;
1307         case MONO_PATCH_INFO_EXC_NAME:
1308                 ji->data.klass = decode_klass_info (aot_module, p, &p);
1309                 if (!ji->data.klass)
1310                         goto cleanup;
1311                 ji->data.name = ji->data.klass->name;
1312                 break;
1313         case MONO_PATCH_INFO_METHOD_REL:
1314                 ji->data.offset = decode_value (p, &p);
1315                 break;
1316         default:
1317                 g_warning ("unhandled type %d", ji->type);
1318                 g_assert_not_reached ();
1319         }
1320
1321         *endbuf = p;
1322
1323         return TRUE;
1324
1325  cleanup:
1326         return FALSE;
1327 }
1328
1329 static MonoJumpInfo*
1330 load_patch_info (MonoAotModule *aot_module, MonoMemPool *mp, int n_patches, 
1331                                  guint32 got_index, guint32 **got_slots, 
1332                                  guint8 *buf, guint8 **endbuf)
1333 {
1334         MonoJumpInfo *patches;
1335         MonoJumpInfo *patch_info = NULL;
1336         int pindex;
1337         guint32 last_offset;
1338         guint8 *p;
1339
1340         p = buf;
1341
1342         /* First load the type + offset table */
1343         last_offset = 0;
1344         patches = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo) * n_patches);
1345
1346         for (pindex = 0; pindex < n_patches; ++pindex) {                
1347                 MonoJumpInfo *ji = &patches [pindex];
1348
1349                 ji->type = *p;
1350                 p ++;
1351
1352                 //printf ("T: %d O: %d.\n", ji->type, ji->ip.i);
1353                 ji->next = patch_info;
1354                 patch_info = ji;
1355         }
1356
1357         *got_slots = g_malloc (sizeof (guint32) * n_patches);
1358         memset (*got_slots, 0xff, sizeof (guint32) * n_patches);
1359
1360         /* Then load the other data */
1361         for (pindex = 0; pindex < n_patches; ++pindex) {
1362                 MonoJumpInfo *ji = &patches [pindex];
1363
1364                 if (!decode_patch_info (aot_module, mp, ji, p, &p, (*got_slots) + pindex))
1365                         goto cleanup;
1366
1367                 if ((*got_slots) [pindex] == 0xffffffff)
1368                         (*got_slots) [pindex] = got_index ++;
1369         }
1370
1371         *endbuf = p;
1372         return patches;
1373
1374  cleanup:
1375         g_free (*got_slots);
1376         *got_slots = NULL;
1377
1378         return NULL;
1379 }
1380  
1381 static gpointer
1382 mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
1383 {
1384         MonoClass *klass = method->klass;
1385         MonoAssembly *ass = klass->image->assembly;
1386         MonoDl *module = ass->aot_module;
1387         guint32 method_index = mono_metadata_token_index (method->token) - 1;
1388         guint8 *code, *info;
1389         MonoAotModule *aot_module;
1390
1391         if (!module)
1392                 return NULL;
1393
1394         if (!method->token)
1395                 return NULL;
1396
1397         if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE)
1398                 return NULL;
1399
1400         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
1401                 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
1402                 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
1403                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
1404                 return NULL;
1405         
1406         aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, ass);
1407
1408         g_assert (klass->inited);
1409
1410         if ((domain != mono_get_root_domain ()) && (!(aot_module->opts & MONO_OPT_SHARED)))
1411                 /* Non shared AOT code can't be used in other appdomains */
1412                 return NULL;
1413
1414         if (aot_module->out_of_date)
1415                 return NULL;
1416
1417         if (aot_module->code_offsets [method_index] == 0xffffffff) {
1418                 if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
1419                         char *full_name = mono_method_full_name (method, TRUE);
1420                         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT NOT FOUND: %s.\n", full_name);
1421                         g_free (full_name);
1422                 }
1423                 return NULL;
1424         }
1425
1426         code = &aot_module->code [aot_module->code_offsets [method_index]];
1427         info = &aot_module->method_info [aot_module->method_info_offsets [method_index]];
1428
1429         if (!aot_module->methods_loaded)
1430                 aot_module->methods_loaded = g_new0 (guint32, klass->image->tables [MONO_TABLE_METHOD].rows + 1);
1431
1432         if ((aot_module->methods_loaded [method_index / 32] >> (method_index % 32)) & 0x1)
1433                 return code;
1434
1435         if (mono_last_aot_method != -1) {
1436                 if (mono_jit_stats.methods_aot > mono_last_aot_method)
1437                                 return NULL;
1438                 else
1439                         if (mono_jit_stats.methods_aot == mono_last_aot_method)
1440                                 printf ("LAST AOT METHOD: %s.%s.%s.\n", klass->name_space, klass->name, method->name);
1441         }
1442
1443         return mono_aot_load_method (domain, aot_module, method, code, info);
1444 }
1445
1446 static gpointer
1447 mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod *method, guint8 *code, guint8 *info)
1448 {
1449         MonoClass *klass = method->klass;
1450         MonoJumpInfo *patch_info = NULL;
1451         MonoMemPool *mp;
1452         int i, pindex, got_index = 0, n_patches, used_strings;
1453         gboolean non_got_patches, keep_patches = TRUE;
1454         guint32 method_index = mono_metadata_token_index (method->token) - 1;
1455         guint8 *p, *ex_info;
1456         MonoJitInfo *jinfo = NULL;
1457
1458         p = info;
1459         decode_klass_info (aot_module, p, &p);
1460
1461         if (!use_loaded_code) {
1462                 guint8 *code2;
1463
1464                 if (!jinfo) {
1465                         ex_info = &aot_module->ex_info [aot_module->ex_info_offsets [mono_metadata_token_index (method->token) - 1]];
1466                         jinfo = decode_exception_debug_info (aot_module, domain, method, ex_info, code);
1467                 }
1468
1469                 code2 = mono_code_manager_reserve (domain->code_mp, jinfo->code_size);
1470                 memcpy (code2, code, jinfo->code_size);
1471                 mono_arch_flush_icache (code2, jinfo->code_size);
1472                 code = code2;
1473         }
1474
1475         if (aot_module->opts & MONO_OPT_SHARED)
1476                 used_strings = decode_value (p, &p);
1477         else
1478                 used_strings = 0;
1479
1480         for (i = 0; i < used_strings; i++) {
1481                 guint token = decode_value (p, &p);
1482                 mono_ldstr (mono_get_root_domain (), klass->image, mono_metadata_token_index (token));
1483         }
1484
1485         if (aot_module->opts & MONO_OPT_SHARED) 
1486                 keep_patches = FALSE;
1487
1488         n_patches = decode_value (p, &p);
1489
1490         keep_patches = FALSE;
1491
1492         if (n_patches) {
1493                 MonoJumpInfo *patches;
1494                 guint32 *got_slots;
1495
1496                 if (keep_patches)
1497                         mp = domain->mp;
1498                 else
1499                         mp = mono_mempool_new ();
1500
1501                 got_index = decode_value (p, &p);
1502
1503                 patches = load_patch_info (aot_module, mp, n_patches, got_index, &got_slots, p, &p);
1504                 if (patches == NULL)
1505                         goto cleanup;
1506
1507                 /* Do this outside the lock to avoid deadlocks */
1508                 mono_aot_unlock ();
1509                 non_got_patches = FALSE;
1510                 for (pindex = 0; pindex < n_patches; ++pindex) {
1511                         MonoJumpInfo *ji = &patches [pindex];
1512
1513                         if (is_got_patch (ji->type)) {
1514                                 if (!aot_module->got [got_slots [pindex]])
1515                                         aot_module->got [got_slots [pindex]] = mono_resolve_patch_target (method, domain, code, ji, TRUE);
1516                                 ji->type = MONO_PATCH_INFO_NONE;
1517                         }
1518                         else
1519                                 non_got_patches = TRUE;
1520                 }
1521                 if (non_got_patches) {
1522                         if (!jinfo) {
1523                                 ex_info = &aot_module->ex_info [aot_module->ex_info_offsets [mono_metadata_token_index (method->token) - 1]];
1524                                 jinfo = decode_exception_debug_info (aot_module, domain, method, ex_info, code);
1525                         }
1526
1527                         mono_arch_flush_icache (code, jinfo->code_size);
1528                         make_writable (code, jinfo->code_size);
1529                         mono_arch_patch_code (method, domain, code, patch_info, TRUE);
1530                 }
1531                 mono_aot_lock ();
1532
1533                 g_free (got_slots);
1534
1535                 if (!keep_patches)
1536                         mono_mempool_destroy (mp);
1537         }
1538
1539         mono_jit_stats.methods_aot++;
1540
1541         if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
1542                 char *full_name = mono_method_full_name (method, TRUE);
1543
1544                 if (!jinfo) {
1545                         ex_info = &aot_module->ex_info [aot_module->ex_info_offsets [mono_metadata_token_index (method->token) - 1]];
1546                         jinfo = decode_exception_debug_info (aot_module, domain, method, ex_info, code);
1547                 }
1548
1549                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND AOT compiled code for %s %p - %p %p\n", full_name, code, code + jinfo->code_size, info);
1550                 g_free (full_name);
1551         }
1552
1553         aot_module->methods_loaded [method_index / 32] |= 1 << (method_index % 32);
1554
1555         init_plt (aot_module);
1556
1557         return code;
1558
1559  cleanup:
1560         /* FIXME: The space in domain->mp is wasted */  
1561         if (aot_module->opts & MONO_OPT_SHARED)
1562                 /* No need to cache patches */
1563                 mono_mempool_destroy (mp);
1564
1565         if (jinfo)
1566                 g_free (jinfo);
1567
1568         return NULL;
1569 }
1570
1571 gpointer
1572 mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
1573 {
1574         gpointer code;
1575
1576         mono_aot_lock ();
1577         code = mono_aot_get_method_inner (domain, method);
1578         mono_aot_unlock ();
1579
1580         return code;
1581 }
1582
1583 static gpointer
1584 mono_aot_get_method_from_token_inner (MonoDomain *domain, MonoImage *image, guint32 token, MonoClass **klass)
1585 {
1586         MonoAssembly *ass = image->assembly;
1587         MonoMemPool *mp;
1588         int i, method_index, pindex, got_index, n_patches, used_strings;
1589         gboolean keep_patches = TRUE;
1590         guint8 *p;
1591         MonoDl *module = ass->aot_module;
1592         guint8 *code = NULL;
1593         guint8 *info;
1594         MonoAotModule *aot_module;
1595
1596         *klass = NULL;
1597
1598         if (!module)
1599                 return NULL;
1600
1601         if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE)
1602                 return NULL;
1603
1604         aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, ass);
1605
1606         if (domain != mono_get_root_domain ())
1607                 return NULL;
1608
1609         if (aot_module->out_of_date)
1610                 return NULL;
1611
1612         if (aot_module->code_offsets [mono_metadata_token_index (token) - 1] == 0xffffffff) {
1613                 return NULL;
1614         }
1615
1616         method_index = mono_metadata_token_index (token) - 1;
1617         code = &aot_module->code [aot_module->code_offsets [method_index]];
1618         info = &aot_module->method_info [aot_module->method_info_offsets [method_index]];
1619
1620         if (!aot_module->methods_loaded)
1621                 aot_module->methods_loaded = g_new0 (guint32, image->tables [MONO_TABLE_METHOD].rows + 1);
1622
1623         if ((aot_module->methods_loaded [method_index / 32] >> (method_index % 32)) & 0x1)
1624                 return code;
1625
1626         if (mono_last_aot_method != -1) {
1627                 if (mono_jit_stats.methods_aot > mono_last_aot_method)
1628                                 return NULL;
1629                 else
1630                         if (mono_jit_stats.methods_aot == mono_last_aot_method) {
1631                                 MonoMethod *method = mono_get_method (image, token, NULL);
1632                                 printf ("LAST AOT METHOD: %s.%s.%s.\n", method->klass->name_space, method->klass->name, method->name);
1633                         }
1634         }
1635
1636         p = info;
1637         *klass = decode_klass_info (aot_module, p, &p);
1638
1639         if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
1640                 MonoMethod *method = mono_get_method (image, token, NULL);
1641                 char *full_name = mono_method_full_name (method, TRUE);
1642                 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND AOT compiled code for %s %p %p\n", full_name, code, info);
1643                 g_free (full_name);
1644         }
1645
1646         if (aot_module->opts & MONO_OPT_SHARED)
1647                 used_strings = decode_value (p, &p);
1648         else
1649                 used_strings = 0;
1650
1651         for (i = 0; i < used_strings; i++) {
1652                 guint string_token = decode_value (p, &p);
1653                 mono_ldstr (mono_get_root_domain (), image, mono_metadata_token_index (string_token));
1654         }
1655
1656         if (aot_module->opts & MONO_OPT_SHARED) 
1657                 keep_patches = FALSE;
1658
1659         keep_patches = FALSE;
1660
1661         n_patches = decode_value (p, &p);
1662
1663         if (n_patches) {
1664                 MonoJumpInfo *patches;
1665                 guint32 *got_slots;
1666
1667                 if (keep_patches)
1668                         mp = domain->mp;
1669                 else
1670                         mp = mono_mempool_new ();
1671
1672                 got_index = decode_value (p, &p);
1673
1674                 patches = load_patch_info (aot_module, mp, n_patches, got_index, &got_slots, p, &p);
1675                 if (patches == NULL)
1676                         goto cleanup;
1677
1678                 /* Do this outside the lock to avoid deadlocks */
1679                 mono_aot_unlock ();
1680
1681                 for (pindex = 0; pindex < n_patches; ++pindex) {
1682                         MonoJumpInfo *ji = &patches [pindex];
1683
1684                         if (is_got_patch (ji->type)) {
1685                                 if (!aot_module->got [got_slots [pindex]])
1686                                         aot_module->got [got_slots [pindex]] = mono_resolve_patch_target (NULL, domain, code, ji, TRUE);
1687                                 ji->type = MONO_PATCH_INFO_NONE;
1688                         }
1689                 }
1690
1691                 mono_aot_lock ();
1692
1693                 g_free (got_slots);
1694
1695                 if (!keep_patches)
1696                         mono_mempool_destroy (mp);
1697         }
1698
1699         mono_jit_stats.methods_aot++;
1700
1701         aot_module->methods_loaded [method_index / 32] |= 1 << (method_index % 32);
1702
1703         init_plt (aot_module);
1704
1705         return code;
1706
1707  cleanup:
1708         /* FIXME: The space in domain->mp is wasted */  
1709         if (aot_module->opts & MONO_OPT_SHARED)
1710                 /* No need to cache patches */
1711                 mono_mempool_destroy (mp);
1712
1713         return NULL;
1714 }
1715
1716 /**
1717  * Same as mono_aot_get_method, but we try to avoid loading any metadata from the
1718  * method.
1719  */
1720 gpointer
1721 mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1722 {
1723         gpointer res;   
1724         MonoClass *klass;
1725
1726         mono_aot_lock ();
1727         res = mono_aot_get_method_from_token_inner (domain, image, token, &klass);
1728         mono_aot_unlock ();
1729
1730         if (!res)
1731                 return NULL;
1732
1733         if (klass)
1734                 mono_runtime_class_init (mono_class_vtable (domain, klass));
1735
1736         return res;
1737 }
1738
1739 typedef struct {
1740         guint8 *addr;
1741         gboolean res;
1742 } IsGotEntryUserData;
1743
1744 static void
1745 check_is_got_entry (gpointer key, gpointer value, gpointer user_data)
1746 {
1747         IsGotEntryUserData *data = (IsGotEntryUserData*)user_data;
1748         MonoAotModule *aot_module = (MonoAotModule*)value;
1749
1750         if (aot_module->got && (data->addr >= (guint8*)(aot_module->got)) && (data->addr < (guint8*)(aot_module->got + aot_module->got_size)))
1751                 data->res = TRUE;
1752 }
1753
1754 gboolean
1755 mono_aot_is_got_entry (guint8 *code, guint8 *addr)
1756 {
1757         IsGotEntryUserData user_data;
1758
1759         if (!aot_modules)
1760                 return FALSE;
1761
1762         user_data.addr = addr;
1763         user_data.res = FALSE;
1764         mono_aot_lock ();
1765         g_hash_table_foreach (aot_modules, check_is_got_entry, &user_data);
1766         mono_aot_unlock ();
1767         
1768         return user_data.res;
1769 }
1770
1771 typedef struct {
1772         guint8 *addr;
1773         MonoAotModule *module;
1774 } FindAotModuleUserData;
1775
1776 static void
1777 find_aot_module_cb (gpointer key, gpointer value, gpointer user_data)
1778 {
1779         FindAotModuleUserData *data = (FindAotModuleUserData*)user_data;
1780         MonoAotModule *aot_module = (MonoAotModule*)value;
1781
1782         if ((data->addr >= (guint8*)(aot_module->code)) && (data->addr < (guint8*)(aot_module->code_end)))
1783                 data->module = aot_module;
1784 }
1785
1786 static inline MonoAotModule*
1787 find_aot_module (guint8 *code)
1788 {
1789         FindAotModuleUserData user_data;
1790
1791         if (!aot_modules)
1792                 return NULL;
1793
1794         /* Reading these need no locking */
1795         if (((gsize)code < aot_code_low_addr) || ((gsize)code > aot_code_high_addr))
1796                 return NULL;
1797
1798         user_data.addr = code;
1799         user_data.module = NULL;
1800                 
1801         mono_aot_lock ();
1802         g_hash_table_foreach (aot_modules, find_aot_module_cb, &user_data);
1803         mono_aot_unlock ();
1804         
1805         return user_data.module;
1806 }
1807
1808 /*
1809  * mono_aot_set_make_unreadable:
1810  *
1811  *   Set whenever to make all mmaped memory unreadable. In conjuction with a
1812  * SIGSEGV handler, this is useful to find out which pages the runtime tries to read.
1813  */
1814 void
1815 mono_aot_set_make_unreadable (gboolean unreadable)
1816 {
1817         make_unreadable = unreadable;
1818 }
1819
1820 typedef struct {
1821         MonoAotModule *module;
1822         guint8 *ptr;
1823 } FindMapUserData;
1824
1825 static void
1826 find_map (gpointer key, gpointer value, gpointer user_data)
1827 {
1828         MonoAotModule *module = (MonoAotModule*)value;
1829         FindMapUserData *data = (FindMapUserData*)user_data;
1830
1831         if (!data->module)
1832                 if ((data->ptr >= module->mem_begin) && (data->ptr < module->mem_end))
1833                         data->module = module;
1834 }
1835
1836 static MonoAotModule*
1837 find_module_for_addr (void *ptr)
1838 {
1839         FindMapUserData data;
1840
1841         if (!make_unreadable)
1842                 return NULL;
1843
1844         data.module = NULL;
1845         data.ptr = (guint8*)ptr;
1846
1847         mono_aot_lock ();
1848         g_hash_table_foreach (aot_modules, (GHFunc)find_map, &data);
1849         mono_aot_unlock ();
1850
1851         return data.module;
1852 }
1853
1854 /*
1855  * mono_aot_is_pagefault:
1856  *
1857  *   Should be called from a SIGSEGV signal handler to find out whenever @ptr is
1858  * within memory allocated by this module.
1859  */
1860 gboolean
1861 mono_aot_is_pagefault (void *ptr)
1862 {
1863         if (!make_unreadable)
1864                 return FALSE;
1865
1866         return find_module_for_addr (ptr) != NULL;
1867 }
1868
1869 /*
1870  * mono_aot_handle_pagefault:
1871  *
1872  *   Handle a pagefault caused by an unreadable page by making it readable again.
1873  */
1874 void
1875 mono_aot_handle_pagefault (void *ptr)
1876 {
1877 #ifndef PLATFORM_WIN32
1878         guint8* start = (guint8*)ROUND_DOWN (((gssize)ptr), PAGESIZE);
1879         int res;
1880
1881         mono_aot_lock ();
1882         res = mprotect (start, PAGESIZE, PROT_READ|PROT_WRITE|PROT_EXEC);
1883         g_assert (res == 0);
1884
1885         n_pagefaults ++;
1886         mono_aot_unlock ();
1887
1888 #if 0
1889  {
1890         void *array [256];
1891         char **names;
1892         int i, size;
1893
1894         printf ("\nNative stacktrace:\n\n");
1895
1896         size = backtrace (array, 256);
1897         names = backtrace_symbols (array, size);
1898         for (i =0; i < size; ++i) {
1899                 printf ("\t%s\n", names [i]);
1900         }
1901         free (names);
1902  }
1903 #endif
1904
1905 #endif
1906 }
1907
1908 /*
1909  * mono_aot_plt_resolve:
1910  *
1911  *   This function is called by the entries in the PLT to resolve the actual method that
1912  * needs to be called. It returns a trampoline to the method and patches the PLT entry.
1913  */
1914 gpointer
1915 mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code)
1916 {
1917 #ifdef MONO_ARCH_HAVE_PIC_AOT
1918         guint8 *p, *target, *plt_entry;
1919         MonoJumpInfo ji;
1920         MonoAotModule *module = (MonoAotModule*)aot_module;
1921         gboolean res;
1922
1923         //printf ("DYN: %p %d\n", aot_module, plt_info_offset);
1924
1925         p = &module->plt_info [plt_info_offset];
1926
1927         ji.type = decode_value (p, &p);
1928
1929         res = decode_patch_info (module, NULL, &ji, p, &p, NULL);
1930         // FIXME: Error handling (how ?)
1931         g_assert (res);
1932
1933         target = mono_resolve_patch_target (NULL, mono_domain_get (), NULL, &ji, TRUE);
1934
1935         /* Patch the PLT entry with target which might be the actual method not a trampoline */
1936         plt_entry = mono_aot_get_plt_entry (code);
1937         g_assert (plt_entry);
1938         mono_arch_patch_plt_entry (plt_entry, target);
1939
1940         return target;
1941 #else
1942         g_assert_not_reached ();
1943         return NULL;
1944 #endif
1945 }
1946
1947 /**
1948  * init_plt:
1949  *
1950  *   Initialize the PLT table of the AOT module. Called lazily when the first AOT
1951  * method in the module is loaded to avoid committing memory by writing to it.
1952  * LOCKING: Assumes the AOT lock is held.
1953  */
1954 static void
1955 init_plt (MonoAotModule *info)
1956 {
1957 #ifdef MONO_ARCH_HAVE_PIC_AOT
1958 #ifdef __i386__
1959         guint8 *buf = info->plt;
1960 #endif
1961 #if defined(__x86_64__)
1962         int i, n_entries;
1963 #endif
1964         gpointer tramp;
1965
1966         if (info->plt_inited)
1967                 return;
1968
1969         tramp = mono_arch_create_specific_trampoline (info, MONO_TRAMPOLINE_AOT_PLT, mono_get_root_domain (), NULL);
1970
1971 #ifdef __i386__
1972         /* Initialize the first PLT entry */
1973         make_writable (info->plt, info->plt_end - info->plt);
1974         x86_jump_code (buf, tramp);
1975 #elif defined(__x86_64__)
1976         /*
1977          * Initialize the entries in the plt_jump_table to point to the default targets.
1978          */
1979          n_entries = info->plt_jump_table_size / sizeof (gpointer);
1980
1981          /* The first entry points to the AOT trampoline */
1982          ((gpointer*)info->plt_jump_table)[0] = tramp;
1983          for (i = 1; i < n_entries; ++i)
1984                  /* Each PLT entry is 16 bytes long, the default entry begins at offset 6 */
1985                  ((gpointer*)info->plt_jump_table)[i] = info->plt + (i * 16) + 6;
1986 #else
1987         g_assert_not_reached ();
1988 #endif
1989
1990         info->plt_inited = TRUE;
1991 #endif
1992 }
1993
1994 /*
1995  * mono_aot_get_plt_entry:
1996  *
1997  *   Return the address of the PLT entry called by the code at CODE if exists.
1998  */
1999 guint8*
2000 mono_aot_get_plt_entry (guint8 *code)
2001 {
2002         MonoAotModule *aot_module = find_aot_module (code);
2003
2004         if (!aot_module)
2005                 return NULL;
2006
2007 #if defined(__i386__) || defined(__x86_64__)
2008         if (code [-5] == 0xe8) {
2009                 guint32 disp = *(guint32*)(code - 4);
2010                 guint8 *target = code + disp;
2011
2012                 if ((target >= (guint8*)(aot_module->plt)) && (target < (guint8*)(aot_module->plt_end)))
2013                         return target;
2014         }
2015 #endif
2016
2017         return NULL;
2018 }
2019
2020 /*
2021  * mono_aot_get_n_pagefaults:
2022  *
2023  *   Return the number of times handle_pagefault is called.
2024  */
2025 guint32
2026 mono_aot_get_n_pagefaults (void)
2027 {
2028         return n_pagefaults;
2029 }
2030
2031 #else
2032 /* AOT disabled */
2033
2034 void
2035 mono_aot_init (void)
2036 {
2037 }
2038
2039 gpointer
2040 mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
2041 {
2042         return NULL;
2043 }
2044
2045 gboolean
2046 mono_aot_is_got_entry (guint8 *code, guint8 *addr)
2047 {
2048         return FALSE;
2049 }
2050
2051 gboolean
2052 mono_aot_init_vtable (MonoVTable *vtable)
2053 {
2054         return FALSE;
2055 }
2056
2057 gboolean
2058 mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
2059 {
2060         return FALSE;
2061 }
2062
2063 gboolean
2064 mono_aot_get_class_from_name (MonoImage *image, const char *name_space, const char *name, MonoClass **klass)
2065 {
2066         return FALSE;
2067 }
2068
2069 MonoJitInfo *
2070 mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
2071 {
2072         return NULL;
2073 }
2074
2075 gpointer
2076 mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
2077 {
2078         return NULL;
2079 }
2080
2081 gboolean
2082 mono_aot_is_pagefault (void *ptr)
2083 {
2084         return FALSE;
2085 }
2086
2087 void
2088 mono_aot_set_make_unreadable (gboolean unreadable)
2089 {
2090 }
2091
2092 guint32
2093 mono_aot_get_n_pagefaults (void)
2094 {
2095         return 0;
2096 }
2097
2098 void
2099 mono_aot_handle_pagefault (void *ptr)
2100 {
2101 }
2102
2103 guint8*
2104 mono_aot_get_plt_entry (guint8 *code)
2105 {
2106         return NULL;
2107 }
2108
2109 gpointer
2110 mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code)
2111 {
2112         return NULL;
2113 }
2114
2115 #endif