Avoid creating plt entries for empty plt sections.
[mono.git] / mono / mini / aot-runtime.c
index 868b4fa6fbb9b77ac259fa5449a9d1f01301e181..521ff45b63dbf4808b545fe64b6b8aebb5a684a1 100644 (file)
@@ -48,7 +48,6 @@
 #include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/gc-internal.h>
-#include <mono/metadata/monitor.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/mono-endian.h>
 #include <mono/utils/mono-logger-internal.h>
@@ -69,7 +68,7 @@
 #endif
 
 /* Number of got entries shared between the JIT and LLVM GOT */
-#define N_COMMON_GOT_ENTRIES 4
+#define N_COMMON_GOT_ENTRIES 9
 
 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
@@ -99,6 +98,7 @@ typedef struct MonoAotModule {
        guint32 image_table_len;
        gboolean out_of_date;
        gboolean plt_inited;
+       gboolean got_initializing;
        guint8 *mem_begin;
        guint8 *mem_end;
        guint8 *jit_code_start;
@@ -213,11 +213,7 @@ static void
 compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **code_end);
 
 static gboolean
-init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass **klass);
-
-/*****************************************************/
-/*                 AOT RUNTIME                       */
-/*****************************************************/
+init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoGenericContext *context);
 
 static inline void
 amodule_lock (MonoAotModule *amodule)
@@ -889,10 +885,8 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
                        int atype = decode_value (p, &p);
 
                        ref->method = mono_gc_get_managed_allocator_by_type (atype, !!(mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS));
-                       if (!ref->method) {
-                               fprintf (stderr, "Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
-                               exit (1);
-                       }
+                       if (!ref->method)
+                               g_error ("Error: No managed allocator, but we need one for AOT.\nAre you using non-standard GC options?\n");
                        break;
                }
                case MONO_WRAPPER_WRITE_BARRIER:
@@ -1676,6 +1670,10 @@ check_usable (MonoAssembly *assembly, MonoAotFileInfo *info, char **out_msg)
                msg = g_strdup_printf ("compiled with --aot=full");
                usable = FALSE;
        }
+       if (mono_llvm_only && !(info->flags & MONO_AOT_FILE_FLAG_LLVM_ONLY)) {
+               msg = g_strdup_printf ("not compiled with --aot=llvmonly");
+               usable = FALSE;
+       }
 #ifdef TARGET_ARM
        /* mono_arch_find_imt_method () requires this */
        if ((info->flags & MONO_AOT_FILE_FLAG_WITH_LLVM) && !mono_use_llvm) {
@@ -1766,6 +1764,28 @@ init_gots (MonoAotModule *amodule)
        }
 }
 
+static void
+init_amodule_got (MonoAotModule *amodule)
+{
+       MonoJumpInfo ji;
+
+       /* These can't be initialized in load_aot_module () */
+       if (!amodule->shared_got [6] && !amodule->got_initializing) {
+               amodule->got_initializing = TRUE;
+
+               memset (&ji, 0, sizeof (ji));
+               ji.type = MONO_PATCH_INFO_INTERNAL_METHOD;
+               ji.data.name = "mono_aot_init_llvm_method";
+               amodule->got_initializing = TRUE;
+               amodule->shared_got [6] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
+               ji.data.name = "mono_aot_init_gshared_method_this";
+               amodule->shared_got [7] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
+               ji.data.name = "mono_aot_init_gshared_method_rgctx";
+               amodule->shared_got [8] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
+               init_gots (amodule);
+       }
+}
+
 static void
 load_aot_module (MonoAssembly *assembly, gpointer user_data)
 {
@@ -1834,10 +1854,8 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        }
 
        if (!sofile && !globals) {
-               if (mono_aot_only && assembly->image->tables [MONO_TABLE_METHOD].rows) {
-                       fprintf (stderr, "Failed to load AOT module '%s' in aot-only mode.\n", aot_name);
-                       exit (1);
-               }
+               if (mono_aot_only && assembly->image->tables [MONO_TABLE_METHOD].rows)
+                       g_error ("Failed to load AOT module '%s' in aot-only mode.\n", aot_name);
                g_free (aot_name);
                return;
        }
@@ -1864,8 +1882,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
 
        if (!usable) {
                if (mono_aot_only) {
-                       fprintf (stderr, "Failed to load AOT module '%s' while running in aot-only mode: %s.\n", aot_name, msg);
-                       exit (1);
+                       g_error ("Failed to load AOT module '%s' while running in aot-only mode: %s.\n", aot_name, msg);
                } else {
                        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: module %s is unusable: %s.\n", aot_name, msg);
                }
@@ -1877,26 +1894,9 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
                return;
        }
 
-#if defined (TARGET_ARM) && defined (TARGET_MACH)
-       {
-               MonoType t;
-               int align = 0;
-
-               memset (&t, 0, sizeof (MonoType));
-               t.type = MONO_TYPE_R8;
-               mono_type_size (&t, &align);
-               align_double = align;
-
-               memset (&t, 0, sizeof (MonoType));
-               t.type = MONO_TYPE_I8;
-               align_int64 = align;
-       }
-#else
+       /* Sanity check */
        align_double = MONO_ABI_ALIGNOF (double);
        align_int64 = MONO_ABI_ALIGNOF (gint64);
-#endif
-
-       /* Sanity check */
        g_assert (info->double_align == align_double);
        g_assert (info->long_align == align_int64);
        g_assert (info->generic_tramp_num == MONO_TRAMPOLINE_NUM);
@@ -1989,6 +1989,12 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        for (i = 0; i < amodule->info.nmethods; ++i) {
                void *addr = NULL;
 
+               if (amodule->info.llvm_get_method) {
+                       gpointer (*get_method) (int) = amodule->info.llvm_get_method;
+
+                       addr = get_method (i);
+               }
+
                /* method_addresses () contains a table of branches, since the ios linker can update those correctly */
                if (!addr && amodule->info.method_addresses) {
                        addr = get_call_table_entry (amodule->info.method_addresses, i);
@@ -2076,8 +2082,25 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
                amodule->shared_got [3] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
        }
 
+       amodule->shared_got [5] = amodule;
+       /* Can't initialize the other shared got slots yet, they are initialized in init_amodule_got () */
+
        init_gots (amodule);
 
+       /*
+        * Register the plt region as a single trampoline so we can unwind from this code
+        */
+       mono_tramp_info_register (
+               mono_tramp_info_create (
+                       NULL,
+                       amodule->plt,
+                       amodule->plt_end - amodule->plt,
+                       NULL,
+                       mono_unwind_get_cie_program ()
+                       ),
+               NULL
+               );
+
        /*
         * Since we store methoddef and classdef tokens when referring to methods/classes in
         * referenced assemblies, we depend on the exact versions of the referenced assemblies.
@@ -2102,10 +2125,8 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
 
        if (amodule->out_of_date) {
                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);
-               if (mono_aot_only) {
-                       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);
-                       exit (1);
-               }
+               if (mono_aot_only)
+                       g_error ("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);
        }
        else
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: loaded AOT Module for %s.\n", assembly->image->name);
@@ -2404,6 +2425,16 @@ compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **c
        int version, fde_count;
        gint32 *table;
 
+       if (amodule->info.llvm_get_method) {
+               gpointer (*get_method) (int) = amodule->info.llvm_get_method;
+
+               *code_start = get_method (-1);
+               *code_end = get_method (-2);
+
+               g_assert (*code_end > *code_start);
+               return;
+       }
+
        g_assert (amodule->mono_eh_frame);
 
        p = amodule->mono_eh_frame;
@@ -2421,10 +2452,8 @@ compute_llvm_code_range (MonoAotModule *amodule, guint8 **code_start, guint8 **c
        p += 4;
        table = (gint32*)p;
 
-       if (fde_count > 1) {
-               /* mono_aot_personality () */
-               g_assert (table [0] == -1);
-               *code_start = amodule->methods [table [2]];
+       if (fde_count > 0) {
+               *code_start = amodule->methods [table [0]];
                *code_end = (guint8*)amodule->methods [table [(fde_count - 1) * 2]] + table [fde_count * 2];
        } else {
                *code_start = NULL;
@@ -3176,11 +3205,10 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
        }
 
        //printf ("F: %s\n", mono_method_full_name (method, TRUE));
-       
+
        jinfo = decode_exception_debug_info (amodule, domain, method, ex_info, addr, code, code_len);
 
        g_assert ((guint8*)addr >= (guint8*)jinfo->code_start);
-       g_assert ((guint8*)addr < (guint8*)jinfo->code_start + jinfo->code_size);
 
        /* Add it to the normal JitInfo tables */
        if (async) {
@@ -3212,6 +3240,10 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
        } else {
                mono_jit_info_table_add (domain, jinfo);
        }
+
+       if ((guint8*)addr >= (guint8*)jinfo->code_start + jinfo->code_size)
+               /* addr is in the padding between methods, see the adjustment of code_size in decode_exception_debug_info () */
+               return NULL;
        
        return jinfo;
 }
@@ -3359,9 +3391,6 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                ji->data.offset = decode_value (p, &p);
                break;
        case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
-       case MONO_PATCH_INFO_MONITOR_ENTER:
-       case MONO_PATCH_INFO_MONITOR_ENTER_V4:
-       case MONO_PATCH_INFO_MONITOR_EXIT:
        case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
        case MONO_PATCH_INFO_GC_NURSERY_START:
        case MONO_PATCH_INFO_JIT_TLS_ID:
@@ -3369,7 +3398,8 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
        case MONO_PATCH_INFO_CASTCLASS_CACHE:
                ji->data.index = decode_value (p, &p);
                break;
-       case MONO_PATCH_INFO_RGCTX_FETCH: {
+       case MONO_PATCH_INFO_RGCTX_FETCH:
+       case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
                gboolean res;
                MonoJumpInfoRgctxEntry *entry;
                guint32 offset, val;
@@ -3393,6 +3423,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
                break;
        }
        case MONO_PATCH_INFO_SEQ_POINT_INFO:
+       case MONO_PATCH_INFO_AOT_MODULE:
                break;
        case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE: {
                MonoJumpInfoImtTramp *imt_tramp = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoImtTramp));
@@ -3580,12 +3611,12 @@ register_jump_target_got_slot (MonoDomain *domain, MonoMethod *method, gpointer
 static gpointer
 load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoMethod *method, guint32 token, int method_index)
 {
-       MonoClass *klass;
-       gboolean from_plt = method == NULL;
        MonoJitInfo *jinfo = NULL;
        guint8 *code = NULL, *info;
        gboolean res;
 
+       init_amodule_got (amodule);
+
        if (mono_profiler_get_events () & MONO_PROFILE_ENTER_LEAVE) {
                if (mono_aot_only)
                        /* The caller cannot handle this */
@@ -3600,6 +3631,14 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
        if (amodule->out_of_date)
                return NULL;
 
+       if (amodule->info.llvm_get_method) {
+               /*
+                * Obtain the method address by calling a generated function in the LLVM module.
+                */
+               gpointer (*get_method) (int) = amodule->info.llvm_get_method;
+               code = get_method (method_index);
+       }
+
        if (!code) {
                if (amodule->methods [method_index] == GINT_TO_POINTER (-1)) {
                        if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
@@ -3613,10 +3652,9 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
                        }
                        return NULL;
                }
+               code = amodule->methods [method_index];
        }
 
-       code = amodule->methods [method_index];
-
        info = &amodule->blob [mono_aot_get_offset (amodule->method_info_offsets, method_index)];
 
        if (!amodule->methods_loaded) {
@@ -3650,9 +3688,11 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
                }
        }
 
-       res = init_method (amodule, method_index, method, &klass);
-       if (!res)
-               goto cleanup;
+       if (!(is_llvm_code (amodule, code) && (amodule->info.flags & MONO_AOT_FILE_FLAG_LLVM_ONLY))) {
+               res = init_method (amodule, method_index, method, NULL, NULL);
+               if (!res)
+                       goto cleanup;
+       }
 
        if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
                char *full_name;
@@ -3695,9 +3735,6 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
                mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
        }
 
-       if (from_plt && klass && !klass->generic_container)
-               mono_runtime_class_init (mono_class_vtable (domain, klass));
-
        return code;
 
  cleanup:
@@ -3746,7 +3783,11 @@ find_aot_method_in_amodule (MonoAotModule *amodule, MonoMethod *method, guint32
                amodule_unlock (amodule);
                if (!m) {
                        m = decode_resolve_method_ref_with_target (amodule, method, p, &p);
-                       if (m) {
+                       /*
+                        * Can't catche runtime invoke wrappers since it would break
+                        * the check in decode_method_ref_with_target ().
+                        */
+                       if (m && m->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) {
                                amodule_lock (amodule);
                                g_hash_table_insert (amodule->method_ref_to_method, orig_p, m);
                                amodule_unlock (amodule);
@@ -3849,10 +3890,12 @@ mono_aot_find_method_index (MonoMethod *method)
 }
 
 static gboolean
-init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass **klass)
+init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoGenericContext *context)
 {
        MonoDomain *domain = mono_domain_get ();
        MonoMemPool *mp;
+       MonoClass *klass;
+       gboolean from_plt = method == NULL;
        int pindex, n_patches;
        guint8 *p;
        MonoJitInfo *jinfo = NULL;
@@ -3864,10 +3907,10 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
        p = info;
 
        if (method) {
-               *klass = method->klass;
+               klass = method->klass;
                decode_klass_ref (amodule, p, &p);
        } else {
-               *klass = decode_klass_ref (amodule, p, &p);
+               klass = decode_klass_ref (amodule, p, &p);
        }
 
        n_patches = decode_value (p, &p);
@@ -3903,6 +3946,13 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
                         * finished executing (#23242).
                         */
                        if (!got [got_slots [pindex]] || ji->type == MONO_PATCH_INFO_SFLDA) {
+                               /* In llvm-only made, we might encounter shared methods */
+                               if (mono_llvm_only && ji->type == MONO_PATCH_INFO_METHOD && mono_method_check_context_used (ji->data.method)) {
+                                       MonoError error;
+
+                                       g_assert (context);
+                                       ji->data.method = mono_class_inflate_generic_method_checked (ji->data.method, context, &error);
+                               }
                                addr = mono_resolve_patch_target (method, domain, code, ji, TRUE);
                                if (ji->type == MONO_PATCH_INFO_METHOD_JUMP)
                                        addr = mono_create_ftnptr (domain, addr);
@@ -3922,6 +3972,11 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
        if (mini_get_debug_options ()->load_aot_jit_info_eagerly)
                jinfo = mono_aot_find_jit_info (domain, amodule->assembly->image, code);
 
+       if (init_class)
+               mono_runtime_class_init (mono_class_vtable (domain, init_class));
+       else if (from_plt && klass && !klass->generic_container)
+               mono_runtime_class_init (mono_class_vtable (domain, klass));
+
        return TRUE;
 
  cleanup:
@@ -3931,6 +3986,48 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
        return FALSE;
 }
 
+void
+mono_aot_init_llvm_method (gpointer aot_module, guint32 method_index)
+{
+       gboolean res;
+
+       // FIXME: Handle failure
+       res = init_method ((MonoAotModule*)aot_module, method_index, NULL, NULL, NULL);
+       g_assert (res);
+}
+
+void
+mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this)
+{
+       gboolean res;
+       MonoClass *klass;
+
+       // FIXME:
+       g_assert (this);
+
+       // FIXME: Handle failure
+       klass = this->vtable->klass;
+       res = init_method ((MonoAotModule*)aot_module, method_index, NULL, klass, klass->generic_class ? &klass->generic_class->context : NULL);
+       g_assert (res);
+}
+
+void
+mono_aot_init_gshared_method_rgctx  (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
+{
+       gboolean res;
+       MonoGenericContext context = { NULL, NULL };
+       MonoClass *klass = rgctx->class_vtable->klass;
+
+       if (klass->generic_class)
+               context.class_inst = klass->generic_class->context.class_inst;
+       else if (klass->generic_container)
+               context.class_inst = klass->generic_container->context.class_inst;
+       context.method_inst = rgctx->method_inst;
+
+       res = init_method ((MonoAotModule*)aot_module, method_index, NULL, rgctx->class_vtable->klass, &context);
+       g_assert (res);
+}
+
 /*
  * mono_aot_get_method:
  *
@@ -4045,9 +4142,9 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
                /* Same for CompareExchange<T> and Exchange<T> */
                /* Same for Volatile.Read<T>/Write<T> */
                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])) ||
-                        (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Read") && MONO_TYPE_IS_REFERENCE (mono_method_signature (method)->ret))) ||
-                        (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Write") && MONO_TYPE_IS_REFERENCE (mono_method_signature (method)->params [1]))))) {
+                       ((!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Interlocked") && (!strcmp (method->name, "CompareExchange") || !strcmp (method->name, "Exchange")) && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (NULL, mono_method_signature (method)->params [1]))) ||
+                        (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Read") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (NULL, mono_method_signature (method)->ret)))) ||
+                        (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Write") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (NULL, mono_method_signature (method)->params [1])))))) {
                        MonoError error;
                        MonoMethod *m;
                        MonoGenericContext ctx;
@@ -4335,6 +4432,11 @@ init_plt (MonoAotModule *amodule)
        if (amodule->plt_inited)
                return;
 
+       if (amodule->info.plt_size <= 1) {
+               amodule->plt_inited = TRUE;
+               return;
+       }
+
        tramp = mono_create_specific_trampoline (amodule, MONO_TRAMPOLINE_AOT_PLT, mono_get_root_domain (), NULL);
 
        /*
@@ -4549,15 +4651,6 @@ load_function_full (MonoAotModule *amodule, const char *name, MonoTrampInfo **ou
                                        g_assert (res == 1);
                                        target = mono_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL);
                                        target = mono_create_ftnptr_malloc (target);
-                               } else if (!strcmp (ji->data.name, "specific_trampoline_monitor_enter")) {
-                                       target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER, mono_get_root_domain (), NULL);
-                                       target = mono_create_ftnptr_malloc (target);
-                               } else if (!strcmp (ji->data.name, "specific_trampoline_monitor_enter_v4")) {
-                                       target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_ENTER_V4, mono_get_root_domain (), NULL);
-                                       target = mono_create_ftnptr_malloc (target);
-                               } else if (!strcmp (ji->data.name, "specific_trampoline_monitor_exit")) {
-                                       target = mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_MONITOR_EXIT, mono_get_root_domain (), NULL);
-                                       target = mono_create_ftnptr_malloc (target);
                                } else if (!strcmp (ji->data.name, "mono_thread_get_and_clear_pending_exception")) {
                                        target = mono_thread_get_and_clear_pending_exception;
                                } else if (!strcmp (ji->data.name, "debugger_agent_single_step_from_context")) {
@@ -4614,6 +4707,12 @@ get_mscorlib_aot_module (void)
        return amodule;
 }
 
+static void
+no_trampolines (void)
+{
+       g_assert_not_reached ();
+}
+
 /*
  * Return the trampoline identified by NAME from the mscorlib AOT file.
  * On ppc64, this returns a function descriptor.
@@ -4623,13 +4722,47 @@ mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo)
 {
        MonoAotModule *amodule = get_mscorlib_aot_module ();
 
+       /*
+       if (mono_llvm_only)
+               return no_trampolines;
+       */
+
        return mono_create_ftnptr_malloc (load_function_full (amodule, name, out_tinfo));
 }
 
 gpointer
 mono_aot_get_trampoline (const char *name)
 {
-       return mono_aot_get_trampoline_full (name, NULL);
+       MonoTrampInfo *out_tinfo;
+       gpointer code;
+
+       code =  mono_aot_get_trampoline_full (name, &out_tinfo);
+       mono_tramp_info_register (out_tinfo, NULL);
+
+       return code;
+}
+
+static gpointer
+read_unwind_info (MonoAotModule *amodule, MonoTrampInfo *info, const char *symbol_name)
+{
+       gpointer symbol_addr;
+       guint32 uw_offset, uw_info_len;
+       guint8 *uw_info;
+
+       find_symbol (amodule->sofile, amodule->globals, symbol_name, &symbol_addr);
+
+       if (!symbol_addr)
+               return NULL;
+
+       uw_offset = *(guint32*)symbol_addr;
+       uw_info = amodule->unwind_info + uw_offset;
+       uw_info_len = decode_value (uw_info, &uw_info);
+
+       info->uw_info = uw_info;
+       info->uw_info_len = uw_info_len;
+
+       /* If successful return the address of the following data */
+       return (guint32*)symbol_addr + 1;
 }
 
 #ifdef MONOTOUCH
@@ -4637,6 +4770,25 @@ mono_aot_get_trampoline (const char *name)
 
 static TrampolinePage* trampoline_pages [MONO_AOT_TRAMP_NUM];
 
+static void
+read_page_trampoline_uwinfo (MonoTrampInfo *info, int tramp_type, gboolean is_generic)
+{
+       char symbol_name [128];
+
+       if (tramp_type == MONO_AOT_TRAMP_SPECIFIC)
+               sprintf (symbol_name, "specific_trampolines_page_%s_p", is_generic ? "gen" : "sp");
+       else if (tramp_type == MONO_AOT_TRAMP_STATIC_RGCTX)
+               sprintf (symbol_name, "rgctx_trampolines_page_%s_p", is_generic ? "gen" : "sp");
+       else if (tramp_type == MONO_AOT_TRAMP_IMT_THUNK)
+               sprintf (symbol_name, "imt_trampolines_page_%s_p", is_generic ? "gen" : "sp");
+       else if (tramp_type == MONO_AOT_TRAMP_GSHAREDVT_ARG)
+               sprintf (symbol_name, "gsharedvt_trampolines_page_%s_p", is_generic ? "gen" : "sp");
+       else
+               g_assert_not_reached ();
+
+       read_unwind_info (mono_defaults.corlib->aot_module, info, symbol_name);
+}
+
 static unsigned char*
 get_new_trampoline_from_page (int tramp_type)
 {
@@ -4688,6 +4840,8 @@ get_new_trampoline_from_page (int tramp_type)
        count = 40;
        page = NULL;
        while (page == NULL && count-- > 0) {
+               MonoTrampInfo *gen_info, *sp_info;
+
                addr = 0;
                /* allocate two contiguous pages of memory: the first page will contain the data (like a local constant pool)
                 * while the second will contain the trampolines.
@@ -4728,6 +4882,23 @@ get_new_trampoline_from_page (int tramp_type)
                code = page->trampolines;
                page->trampolines += specific_trampoline_size;
                mono_aot_page_unlock ();
+
+               /* Register the generic part at the beggining of the trampoline page */
+               gen_info = mono_tramp_info_create (NULL, (guint8*)taddr, amodule->info.tramp_page_code_offsets [tramp_type], NULL, NULL);
+               read_page_trampoline_uwinfo (gen_info, tramp_type, TRUE);
+               mono_tramp_info_register (gen_info, NULL);
+               /*
+                * FIXME
+                * Registering each specific trampoline produces a lot of
+                * MonoJitInfo structures. Jump trampolines are also registered
+                * separately.
+                */
+               if (tramp_type != MONO_AOT_TRAMP_SPECIFIC) {
+                       /* Register the rest of the page as a single trampoline */
+                       sp_info = mono_tramp_info_create (NULL, code, page->trampolines_end - code, NULL, NULL);
+                       read_page_trampoline_uwinfo (sp_info, tramp_type, FALSE);
+                       mono_tramp_info_register (sp_info, NULL);
+               }
                return code;
        }
        g_error ("Cannot allocate more trampoline pages: %d", ret);
@@ -4807,6 +4978,7 @@ get_new_gsharedvt_arg_trampoline_from_page (gpointer tramp, gpointer arg)
 }
 
 /* Return a given kind of trampoline */
+/* FIXME set unwind info for these trampolines */
 static gpointer
 get_numerous_trampoline (MonoAotTrampoline tramp_type, int n_got_slots, MonoAotModule **out_amodule, guint32 *got_offset, guint32 *out_tramp_size)
 {
@@ -4925,6 +5097,8 @@ mono_aot_get_unbox_trampoline (MonoMethod *method)
        gpointer code;
        guint32 *ut, *ut_end, *entry;
        int low, high, entry_index = 0;
+       gpointer symbol_addr;
+       MonoTrampInfo *tinfo;
 
        if (method->is_inflated && !mono_method_is_generic_sharable_full (method, FALSE, FALSE, FALSE)) {
                method_index = find_aot_method (method, &amodule);
@@ -4942,6 +5116,14 @@ mono_aot_get_unbox_trampoline (MonoMethod *method)
                g_assert (amodule);
        }
 
+       if (amodule->info.llvm_get_unbox_tramp) {
+               gpointer (*get_tramp) (int) = amodule->info.llvm_get_unbox_tramp;
+               code = get_tramp (method_index);
+
+               if (code)
+                       return code;
+       }
+
        ut = amodule->unbox_trampolines;
        ut_end = amodule->unbox_trampolines_end;
 
@@ -4964,6 +5146,17 @@ mono_aot_get_unbox_trampoline (MonoMethod *method)
        code = get_call_table_entry (amodule->unbox_trampoline_addresses, entry_index);
        g_assert (code);
 
+       tinfo = mono_tramp_info_create (NULL, code, 0, NULL, NULL);
+
+       symbol_addr = read_unwind_info (amodule, tinfo, "unbox_trampoline_p");
+       if (!symbol_addr) {
+               mono_tramp_info_free (tinfo);
+               return FALSE;
+       }
+
+       tinfo->code_size = *(guint32*)symbol_addr;
+       mono_tramp_info_register (tinfo, NULL);
+
        /* The caller expects an ftnptr */
        return mono_create_ftnptr (mono_domain_get (), code);
 }