guint8 *plt_end;
guint8 *blob;
gint32 *code_offsets;
+#ifdef MONOTOUCH
+ gpointer *method_addresses;
+#endif
/* This contains <offset, index> pairs sorted by offset */
/* This is needed because LLVM emitted methods can be in any order */
gint32 *sorted_code_offsets;
}
/*
- * mono_aot_get_method:
+ * mono_aot_get_offset:
*
* Decode an offset table emitted by emit_offset_table (), returning the INDEXth
* entry.
}
case MONO_AOT_TYPEREF_VAR: {
MonoType *t;
- MonoGenericContainer *container;
+ MonoGenericContainer *container = NULL;
int type = decode_value (p, &p);
int num = decode_value (p, &p);
- gboolean is_method = decode_value (p, &p);
+ gboolean has_container = decode_value (p, &p);
+ int serial = 0;
- if (is_method) {
- MonoMethod *method_def;
- g_assert (type == MONO_TYPE_MVAR);
- method_def = decode_resolve_method_ref (module, p, &p);
- if (!method_def)
- return NULL;
-
- container = mono_method_get_generic_container (method_def);
+ if (has_container) {
+ gboolean is_method = decode_value (p, &p);
+
+ if (is_method) {
+ MonoMethod *method_def;
+ g_assert (type == MONO_TYPE_MVAR);
+ method_def = decode_resolve_method_ref (module, p, &p);
+ if (!method_def)
+ return NULL;
+
+ container = mono_method_get_generic_container (method_def);
+ } else {
+ MonoClass *class_def;
+ g_assert (type == MONO_TYPE_VAR);
+ class_def = decode_klass_ref (module, p, &p);
+ if (!class_def)
+ return NULL;
+
+ container = class_def->generic_container;
+ }
} else {
- MonoClass *class_def;
- g_assert (type == MONO_TYPE_VAR);
- class_def = decode_klass_ref (module, p, &p);
- if (!class_def)
- return NULL;
-
- container = class_def->generic_container;
+ serial = decode_value (p, &p);
}
- g_assert (container);
-
// FIXME: Memory management
t = g_new0 (MonoType, 1);
t->type = type;
- t->data.generic_param = mono_generic_container_get_param (container, num);
+
+ if (container) {
+ t->data.generic_param = mono_generic_container_get_param (container, num);
+ g_assert (serial == 0);
+ } else {
+ /* Anonymous */
+ MonoGenericParam *par = (MonoGenericParam*)g_new0 (MonoGenericParamFull, 1);
+ par->num = num;
+ par->serial = serial;
+ // FIXME:
+ par->image = mono_defaults.corlib;
+ t->data.generic_param = par;
+ }
// FIXME: Maybe use types directly to avoid
// the overhead of creating MonoClass-es
kind = decode_value (p, &p);
/* Can't decode this */
- g_assert (target);
+ if (!target)
+ return FALSE;
if (target->wrapper_type == MONO_WRAPPER_STELEMREF) {
info = mono_marshal_get_wrapper_info (target);
if (!klass)
return FALSE;
- g_assert (target);
+ if (!target)
+ return FALSE;
if (klass != target->klass)
return FALSE;
return FALSE;
ref->method = mono_marshal_get_struct_to_ptr (klass);
}
+ } else if (subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER) {
+ MonoMethod *m = decode_resolve_method_ref (module, p, &p);
+
+ if (!m)
+ return FALSE;
+ ref->method = mono_marshal_get_synchronized_inner_wrapper (m);
} else {
if (subtype == WRAPPER_SUBTYPE_FAST_MONITOR_ENTER)
desc = mono_method_desc_new ("Monitor:Enter", FALSE);
if (!m)
return FALSE;
- g_assert (target);
+ if (!target)
+ return FALSE;
g_assert (target->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED);
info = mono_marshal_get_wrapper_info (target);
char *name;
if (subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
- g_assert (target);
+ if (!target)
+ return FALSE;
name = (char*)p;
if (strcmp (target->name, name) != 0)
return FALSE;
/* This should only happen when looking for an extra method */
- g_assert (target);
+ if (!target)
+ return FALSE;
if (mono_marshal_method_from_wrapper (target) == m)
ref->method = target;
else
case MONO_WRAPPER_RUNTIME_INVOKE: {
int subtype = decode_value (p, &p);
- g_assert (target);
+ if (!target)
+ return FALSE;
if (subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DYNAMIC) {
if (strcmp (target->name, "runtime_invoke_dynamic") != 0)
* These wrappers are associated with a signature, not with a method.
* Since we can't decode them into methods, they need a target method.
*/
- g_assert (target);
+ if (!target)
+ return FALSE;
if (sig_matches_target (module, target, p, &p))
ref->method = target;
gboolean usable = TRUE;
gboolean full_aot;
guint8 *blob;
+ guint32 excluded_cpu_optimizations;
if (strcmp (assembly->image->guid, info->assembly_guid)) {
msg = g_strdup_printf ("doesn't match assembly");
usable = FALSE;
}
+ mono_arch_cpu_optimizations (&excluded_cpu_optimizations);
+ if (info->opts & excluded_cpu_optimizations) {
+ msg = g_strdup_printf ("compiled with unsupported CPU optimizations");
+ usable = FALSE;
+ }
+
+ if (!mono_aot_only && (info->simd_opts & ~mono_arch_cpu_enumerate_simd_versions ())) {
+ msg = g_strdup_printf ("compiled with unsupported SIMD extensions");
+ usable = FALSE;
+ }
+
blob = info->blob;
if (info->gc_name_index != -1) {
}
if (!sofile && !globals) {
- if (mono_aot_only) {
+ 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);
}
}
amodule->code_offsets = info->code_offsets;
+#ifdef MONOTOUCH
+ amodule->method_addresses = info->method_addresses;
+#endif
amodule->code = info->methods;
#ifdef TARGET_ARM
/* Mask out thumb interop bit */
amodule->trampolines [MONO_AOT_TRAMP_IMT_THUNK] = info->imt_thunks;
amodule->thumb_end = info->thumb_end;
+#ifdef MONOTOUCH
+ if (info->flags & MONO_AOT_FILE_FLAG_DIRECT_METHOD_ADDRESSES) {
+ /* Compute code_offsets from the method addresses */
+ amodule->code_offsets = g_malloc0 (amodule->info.nmethods * sizeof (gint32));
+ for (i = 0; i < amodule->info.nmethods; ++i) {
+ if (!amodule->method_addresses [i])
+ amodule->code_offsets [i] = 0xffffffff;
+ else
+ amodule->code_offsets [i] = (char*)amodule->method_addresses [i] - (char*)amodule->code;
+ }
+ }
+#endif
+
if (make_unreadable) {
#ifndef TARGET_WIN32
guint8 *addr;
if (ref.no_aot_trampoline)
return NULL;
- if (mono_metadata_token_index (ref.token) == 0)
+ if (mono_metadata_token_index (ref.token) == 0 || mono_metadata_token_table (ref.token) != MONO_TABLE_METHOD)
return NULL;
return mono_aot_get_method_from_token (domain, ref.image, ref.token);
guint8 *fde, *cie, *code_start, *code_end;
int version, fde_count;
gint32 *table;
- int i, j, pos, left, right, offset, offset1, offset2, code_len;
+ int i, j, pos, left, right, offset, offset1, offset2, code_len, func_encoding;
MonoJitExceptionInfo *ei;
guint32 fde_len, ei_len, nested_len, nindex;
gpointer *type_info;
/* Header */
version = *p;
- g_assert (version == 1);
+ g_assert (version == 1 || version == 2);
p ++;
+ if (version == 2) {
+ func_encoding = *p;
+ p ++;
+ } else {
+ func_encoding = DW_EH_PE_pcrel;
+ }
p = ALIGN_PTR_TO (p, 4);
fde_count = *(guint32*)p;
pos = (left + right) / 2;
offset1 = table [(pos * 2)];
- if (pos + 1 == fde_count)
+ if (pos + 1 == fde_count) {
/* FIXME: */
offset2 = amodule->code_end - amodule->code;
- else
+ } else {
+ /* Encoded as DW_EH_PE_pcrel, but relative to mono_eh_frame */
offset2 = table [(pos + 1) * 2];
+ }
+
+ if (func_encoding == DW_EH_PE_absptr) {
+ /*
+ * Encoded as DW_EH_PE_absptr, because the ios linker can move functions inside object files to make thumb work,
+ * so the offsets between two symbols in the text segment are not assembler constant.
+ */
+ g_assert (sizeof(gpointer) == 4);
+ offset1 -= (gint32)(gsize)amodule->mono_eh_frame;
+ offset2 -= (gint32)(gsize)amodule->mono_eh_frame;
+ }
if (offset < offset1)
right = pos;
break;
}
- code_start = amodule->mono_eh_frame + table [(pos * 2)];
- /* This won't overflow because there is +1 entry in the table */
- code_end = amodule->mono_eh_frame + table [(pos * 2) + 2];
+ if (func_encoding == DW_EH_PE_absptr) {
+ code_start = (gpointer)(gsize)table [(pos * 2)];
+ code_end = (gpointer)(gsize)table [(pos * 2) + 2];
+ } else {
+ code_start = amodule->mono_eh_frame + table [(pos * 2)];
+ /* This won't overflow because there is +1 entry in the table */
+ code_end = amodule->mono_eh_frame + table [(pos * 2) + 2];
+ }
code_len = code_end - code_start;
g_assert (code >= code_start && code < code_end);
+ if (amodule->thumb_end && (guint8*)code_start < amodule->thumb_end)
+ /* Clear thumb flag */
+ code_start = (guint8*)(((mgreg_t)code_start) & ~1);
+
fde = amodule->mono_eh_frame + table [(pos * 2) + 1];
/* This won't overflow because there is +1 entry in the table */
fde_len = table [(pos * 2) + 2 + 1] - table [(pos * 2) + 1];
gi = mono_jit_info_get_generic_jit_info (jinfo);
g_assert (gi);
- if (from_llvm) {
- gi->has_this = this_reg != -1;
- gi->this_reg = this_reg;
- gi->this_offset = this_offset;
+ gi->nlocs = decode_value (p, &p);
+ if (gi->nlocs) {
+ gi->locations = mono_domain_alloc0 (domain, gi->nlocs * sizeof (MonoDwarfLocListEntry));
+ for (i = 0; i < gi->nlocs; ++i) {
+ MonoDwarfLocListEntry *entry = &gi->locations [i];
+
+ entry->is_reg = decode_value (p, &p);
+ entry->reg = decode_value (p, &p);
+ if (!entry->is_reg)
+ entry->offset = decode_value (p, &p);
+ if (i > 0)
+ entry->from = decode_value (p, &p);
+ entry->to = decode_value (p, &p);
+ }
} else {
- gi->has_this = decode_value (p, &p);
- gi->this_reg = decode_value (p, &p);
- gi->this_offset = decode_value (p, &p);
+ if (from_llvm) {
+ gi->has_this = this_reg != -1;
+ gi->this_reg = this_reg;
+ gi->this_offset = this_offset;
+ } else {
+ gi->has_this = decode_value (p, &p);
+ gi->this_reg = decode_value (p, &p);
+ gi->this_offset = decode_value (p, &p);
+ }
}
/* This currently contains no data */
mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
{
int pos, left, right, offset, offset1, offset2, code_len;
- int method_index, table_len, is_wrapper;
+ int method_index, table_len;
guint32 token;
MonoAotModule *amodule = image->aot_module;
MonoMethod *method;
for (i = 0; i < offsets_len -1; ++i)
g_assert (code_offsets [(i * 2)] <= code_offsets [(i + 1) * 2]);
+ amodule->sorted_code_offsets_len = offsets_len;
+ mono_memory_barrier ();
if (InterlockedCompareExchangePointer ((gpointer*)&amodule->sorted_code_offsets, code_offsets, NULL) != NULL)
/* Somebody got in before us */
g_free (code_offsets);
- amodule->sorted_code_offsets_len = offsets_len;
}
code_offsets = amodule->sorted_code_offsets;
offsets_len = amodule->sorted_code_offsets_len;
+ if (offsets_len > 0 && (offset < code_offsets [0] || offset >= (amodule->code_end - amodule->code)))
+ return NULL;
+
/* Binary search in the sorted_code_offsets table */
left = 0;
right = offsets_len;
}
p = amodule->blob + table [(pos * 2) + 1];
- is_wrapper = decode_value (p, &p);
- g_assert (!is_wrapper);
method = decode_resolve_method_ref (amodule, p, &p);
- g_assert (method);
+ if (!method)
+ /* Happens when a random address is passed in which matches a not-yey called wrapper encoded using its name */
+ return NULL;
} else {
token = mono_metadata_make_token (MONO_TABLE_METHOD, method_index + 1);
method = mono_get_method (image, token, NULL);
info = &amodule->blob [mono_aot_get_offset (amodule->method_info_offsets, method_index)];
- if (amodule->thumb_end && code < amodule->thumb_end) {
+ if (amodule->thumb_end && code < amodule->thumb_end && ((amodule->info.flags & MONO_AOT_FILE_FLAG_DIRECT_METHOD_ADDRESSES) == 0)) {
/* Convert this into a thumb address */
g_assert ((amodule->code_offsets [method_index] & 0x1) == 0);
code = &amodule->code [amodule->code_offsets [method_index] + 1];
mono_mempool_destroy (mp);
}
+ if (mini_get_debug_options ()->load_aot_jit_info_eagerly)
+ jinfo = mono_aot_find_jit_info (domain, amodule->assembly->image, code);
+
if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
char *full_name;
g_assert_not_reached ();
#endif
+#ifdef MONOTOUCH
+ while (target != NULL) {
+ if ((target >= (guint8*)(amodule->plt)) && (target < (guint8*)(amodule->plt_end)))
+ return target;
+
+ // Add 4 since mono_arch_get_call_target assumes we're passing
+ // the instruction after the actual branch instruction.
+ target = mono_arch_get_call_target (target + 4);
+ }
+
+ return NULL;
+#else
if ((target >= (guint8*)(amodule->plt)) && (target < (guint8*)(amodule->plt_end)))
return target;
else
return NULL;
+#endif
}
/*
*out_amodule = amodule;
- if (amodule->trampoline_index [tramp_type] == amodule->info.num_trampolines [tramp_type])
- g_error ("Ran out of trampolines of type %d in '%s' (%d)\n", tramp_type, image->name, amodule->info.num_trampolines [tramp_type]);
-
+ if (amodule->trampoline_index [tramp_type] == amodule->info.num_trampolines [tramp_type]) {
+ g_error ("Ran out of trampolines of type %d in '%s' (%d)%s\n",
+ tramp_type, image->name, amodule->info.num_trampolines [tramp_type],
+#ifdef MONOTOUCH
+ ". See http://docs.xamarin.com/ios/troubleshooting for instruction on how to fix this condition"
+#else
+ ""
+#endif
+ );
+ }
index = amodule->trampoline_index [tramp_type] ++;
mono_aot_unlock ();