#include <sys/wait.h> /* for WIFEXITED, WEXITSTATUS */
#endif
-#ifdef HAVE_DL_ITERATE_PHDR
-#include <link.h>
-#endif
-
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/class.h>
#include <mono/metadata/object.h>
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.
static MonoClass*
decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf);
+static MonoType*
+decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf);
+
static MonoGenericInst*
decode_generic_inst (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
{
static gboolean
decode_generic_context (MonoAotModule *module, MonoGenericContext *ctx, guint8 *buf, guint8 **endbuf)
{
- gboolean has_class_inst, has_method_inst;
guint8 *p = buf;
+ guint8 *p2;
+ int argc;
- has_class_inst = decode_value (p, &p);
- if (has_class_inst) {
+ p2 = p;
+ argc = decode_value (p, &p);
+ if (argc) {
+ p = p2;
ctx->class_inst = decode_generic_inst (module, p, &p);
if (!ctx->class_inst)
return FALSE;
}
- has_method_inst = decode_value (p, &p);
- if (has_method_inst) {
+ p2 = p;
+ argc = decode_value (p, &p);
+ if (argc) {
+ p = p2;
ctx->method_inst = decode_generic_inst (module, p, &p);
if (!ctx->method_inst)
return FALSE;
decode_klass_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
{
MonoImage *image;
- MonoClass *klass, *eklass;
- guint32 token, rank;
+ MonoClass *klass = NULL, *eklass;
+ guint32 token, rank, idx;
guint8 *p = buf;
+ int reftype;
- token = decode_value (p, &p);
- if (token == 0) {
+ reftype = decode_value (p, &p);
+ if (reftype == 0) {
*endbuf = p;
return NULL;
}
- if (mono_metadata_token_table (token) == 0) {
+
+ switch (reftype) {
+ case MONO_AOT_TYPEREF_TYPEDEF_INDEX:
+ idx = decode_value (p, &p);
+ image = load_image (module, 0, TRUE);
+ if (!image)
+ return NULL;
+ klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF + idx);
+ break;
+ case MONO_AOT_TYPEREF_TYPEDEF_INDEX_IMAGE:
+ idx = decode_value (p, &p);
image = load_image (module, decode_value (p, &p), TRUE);
if (!image)
return NULL;
- klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF + token);
- } else if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC) {
- if (token == MONO_TOKEN_TYPE_SPEC) {
- MonoTypeEnum type = decode_value (p, &p);
-
- if (type == MONO_TYPE_GENERICINST) {
- MonoClass *gclass;
- MonoGenericContext ctx;
- MonoType *type;
-
- gclass = decode_klass_ref (module, p, &p);
- if (!gclass)
- return NULL;
- g_assert (gclass->generic_container);
-
- memset (&ctx, 0, sizeof (ctx));
- ctx.class_inst = decode_generic_inst (module, p, &p);
- if (!ctx.class_inst)
- return NULL;
- type = mono_class_inflate_generic_type (&gclass->byval_arg, &ctx);
- klass = mono_class_from_mono_type (type);
- mono_metadata_free_type (type);
- } else if ((type == MONO_TYPE_VAR) || (type == MONO_TYPE_MVAR)) {
- MonoType *t;
- MonoGenericContainer *container;
-
- int num = decode_value (p, &p);
- 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;
- }
-
- g_assert (container);
+ klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF + idx);
+ break;
+ case MONO_AOT_TYPEREF_TYPESPEC_TOKEN:
+ token = decode_value (p, &p);
+ image = module->assembly->image;
+ if (!image)
+ return NULL;
+ klass = mono_class_get (image, token);
+ break;
+ case MONO_AOT_TYPEREF_GINST: {
+ MonoClass *gclass;
+ MonoGenericContext ctx;
+ MonoType *type;
- // FIXME: Memory management
- t = g_new0 (MonoType, 1);
- t->type = type;
- t->data.generic_param = mono_generic_container_get_param (container, num);
+ gclass = decode_klass_ref (module, p, &p);
+ if (!gclass)
+ return NULL;
+ g_assert (gclass->generic_container);
- // FIXME: Maybe use types directly to avoid
- // the overhead of creating MonoClass-es
- klass = mono_class_from_mono_type (t);
+ memset (&ctx, 0, sizeof (ctx));
+ ctx.class_inst = decode_generic_inst (module, p, &p);
+ if (!ctx.class_inst)
+ return NULL;
+ type = mono_class_inflate_generic_type (&gclass->byval_arg, &ctx);
+ klass = mono_class_from_mono_type (type);
+ mono_metadata_free_type (type);
+ break;
+ }
+ case MONO_AOT_TYPEREF_VAR: {
+ MonoType *t;
+ MonoGenericContainer *container = NULL;
+ int type = decode_value (p, &p);
+ int num = decode_value (p, &p);
+ gboolean has_container = decode_value (p, &p);
+ int serial = 0;
+
+ 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;
- g_free (t);
+ container = mono_method_get_generic_container (method_def);
} else {
- g_assert_not_reached ();
+ 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 {
- image = load_image (module, decode_value (p, &p), TRUE);
- if (!image)
- return NULL;
- klass = mono_class_get (image, token);
+ serial = decode_value (p, &p);
}
- } else if (token == MONO_TOKEN_TYPE_DEF) {
+
+ // FIXME: Memory management
+ t = g_new0 (MonoType, 1);
+ t->type = type;
+
+ 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
+ klass = mono_class_from_mono_type (t);
+
+ g_free (t);
+ break;
+ }
+ case MONO_AOT_TYPEREF_ARRAY:
/* Array */
- image = load_image (module, decode_value (p, &p), TRUE);
- if (!image)
- return NULL;
rank = decode_value (p, &p);
eklass = decode_klass_ref (module, p, &p);
klass = mono_array_class_get (eklass, rank);
- } else {
+ break;
+ case MONO_AOT_TYPEREF_PTR: {
+ MonoType *t;
+
+ t = decode_type (module, p, &p);
+ if (!t)
+ return NULL;
+ klass = mono_class_from_mono_type (t);
+ g_free (t);
+ break;
+ }
+ case MONO_AOT_TYPEREF_BLOB_INDEX: {
+ guint32 offset = decode_value (p, &p);
+ guint8 *p2;
+
+ p2 = module->blob + offset;
+ klass = decode_klass_ref (module, p2, &p2);
+ break;
+ }
+ default:
g_assert_not_reached ();
}
g_assert (klass);
-
+ //printf ("BLA: %s\n", mono_type_full_name (&klass->byval_arg));
*endbuf = p;
return klass;
}
guint8 *p = buf;
MonoType *t;
- t = g_malloc (sizeof (MonoType));
+ t = g_malloc0 (sizeof (MonoType));
while (TRUE) {
if (*p == MONO_TYPE_PINNED) {
t->data.generic_class = klass->generic_class;
break;
}
+ case MONO_TYPE_ARRAY: {
+ MonoArrayType *array;
+ int i;
+
+ // FIXME: memory management
+ array = g_new0 (MonoArrayType, 1);
+ array->eklass = decode_klass_ref (module, p, &p);
+ if (!array->eklass)
+ return NULL;
+ array->rank = decode_value (p, &p);
+ array->numsizes = decode_value (p, &p);
+
+ if (array->numsizes)
+ array->sizes = g_malloc0 (sizeof (int) * array->numsizes);
+ for (i = 0; i < array->numsizes; ++i)
+ array->sizes [i] = decode_value (p, &p);
+
+ array->numlobounds = decode_value (p, &p);
+ if (array->numlobounds)
+ array->lobounds = g_malloc0 (sizeof (int) * array->numlobounds);
+ for (i = 0; i < array->numlobounds; ++i)
+ array->lobounds [i] = decode_value (p, &p);
+ t->data.array = array;
+ break;
+ }
default:
g_assert_not_reached ();
}
g_assert (!has_gen_params);
param_count = decode_value (p, &p);
- if (param_count != target->param_count)
+ if (target && param_count != target->param_count)
return NULL;
sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + param_count * sizeof (MonoType *));
sig->param_count = param_count;
sig->call_convention = call_conv;
sig->param_count = param_count;
sig->ret = decode_type (module, p, &p);
- for (i = 0; i < param_count; ++i)
+ for (i = 0; i < param_count; ++i) {
+ if (*p == MONO_TYPE_SENTINEL) {
+ g_assert (sig->call_convention == MONO_CALL_VARARG);
+ sig->sentinelpos = i;
+ p ++;
+ }
sig->params [i] = decode_type (module, p, &p);
+ }
+
+ if (sig->call_convention == MONO_CALL_VARARG && sig->sentinelpos == -1)
+ sig->sentinelpos = sig->param_count;
*endbuf = p;
return sig;
}
+static MonoMethodSignature*
+decode_signature (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
+{
+ return decode_signature_with_target (module, NULL, buf, endbuf);
+}
+
static gboolean
sig_matches_target (MonoAotModule *module, MonoMethod *target, guint8 *buf, guint8 **endbuf)
{
return res;
}
-static gboolean
-wrapper_name_matches_target (guint8 *p, MonoMethod *target)
-{
- char *name = (char*)p;
- char *tname;
-
- tname = mono_aot_wrapper_name (target);
- if (!strcmp (name, tname))
- return TRUE;
- else
- return FALSE;
-}
-
/* Stores information returned by decode_method_ref () */
typedef struct {
MonoImage *image;
* Decode a method reference, storing the image/token into a MethodRef structure.
* This avoids loading metadata for the method if the caller does not need it. If the method has
* no token, then it is loaded from metadata and ref->method is set to the method instance.
- * If TARGET is non-NULL, abort decoding if it can be determined that the decoded method couldn't resolve to TARGET, and return FALSE. There are some kinds of method references
- * which only support a non-null TARGET.
+ * If TARGET is non-NULL, abort decoding if it can be determined that the decoded method
+ * couldn't resolve to TARGET, and return FALSE.
+ * There are some kinds of method references which only support a non-null TARGET.
+ * This means that its not possible to decode this into a method, only to check
+ * that the method reference matches a given method. This is normally not a problem
+ * as these wrappers only occur in the extra_methods table, where we already have
+ * a method we want to lookup.
*/
static gboolean
decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod *target, guint8 *buf, guint8 **endbuf)
case MONO_WRAPPER_STELEMREF: {
int subtype = decode_value (p, &p);
- if (subtype == 0) {
+ if (subtype == WRAPPER_SUBTYPE_NONE) {
ref->method = mono_marshal_get_stelemref ();
- } else {
- g_assert (subtype == MONO_AOT_WRAPPER_BY_NAME);
- g_assert (target);
- if (wrapper_name_matches_target (p, target))
- ref->method = target;
- else
+ } else if (subtype == WRAPPER_SUBTYPE_VIRTUAL_STELEMREF) {
+ int kind;
+ WrapperInfo *info;
+
+ kind = decode_value (p, &p);
+
+ /* Can't decode this */
+ if (!target)
return FALSE;
+ if (target->wrapper_type == MONO_WRAPPER_STELEMREF) {
+ info = mono_marshal_get_wrapper_info (target);
+
+ g_assert (info);
+ if (info->subtype == subtype && info->d.virtual_stelemref.kind == kind)
+ ref->method = target;
+ else
+ return FALSE;
+ } else {
+ return FALSE;
+ }
+ } else {
+ g_assert_not_reached ();
}
break;
}
MonoMethod *orig_method;
int subtype = decode_value (p, &p);
- if (subtype == MONO_AOT_WRAPPER_PTR_TO_STRUCTURE || subtype == MONO_AOT_WRAPPER_STRUCTURE_TO_PTR) {
+ if (subtype == WRAPPER_SUBTYPE_PTR_TO_STRUCTURE || subtype == WRAPPER_SUBTYPE_STRUCTURE_TO_PTR) {
MonoClass *klass = decode_klass_ref (module, p, &p);
if (!klass)
return FALSE;
- g_assert (target);
+ if (!target)
+ return FALSE;
if (klass != target->klass)
return FALSE;
- if (subtype == MONO_AOT_WRAPPER_PTR_TO_STRUCTURE) {
+ if (subtype == WRAPPER_SUBTYPE_PTR_TO_STRUCTURE) {
if (strcmp (target->name, "PtrToStructure"))
return FALSE;
ref->method = mono_marshal_get_ptr_to_struct (klass);
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 == MONO_AOT_WRAPPER_MONITOR_ENTER)
+ if (subtype == WRAPPER_SUBTYPE_FAST_MONITOR_ENTER)
desc = mono_method_desc_new ("Monitor:Enter", FALSE);
- else if (subtype == MONO_AOT_WRAPPER_MONITOR_EXIT)
+ else if (subtype == WRAPPER_SUBTYPE_FAST_MONITOR_EXIT)
desc = mono_method_desc_new ("Monitor:Exit", FALSE);
- else if (subtype == MONO_AOT_WRAPPER_MONITOR_ENTER_V4)
+ else if (subtype == WRAPPER_SUBTYPE_FAST_MONITOR_ENTER_V4)
desc = mono_method_desc_new ("Monitor:Enter(object,bool&)", FALSE);
else
g_assert_not_reached ();
case MONO_WRAPPER_MANAGED_TO_MANAGED: {
int subtype = decode_value (p, &p);
- if (subtype == MONO_AOT_WRAPPER_ELEMENT_ADDR) {
+ if (subtype == WRAPPER_SUBTYPE_ELEMENT_ADDR) {
int rank = decode_value (p, &p);
int elem_size = decode_value (p, &p);
ref->method = mono_marshal_get_array_address (rank, elem_size);
- } else {
- g_assert (subtype == MONO_AOT_WRAPPER_BY_NAME);
- g_assert (target);
- if (wrapper_name_matches_target (p, target))
+ } else if (subtype == WRAPPER_SUBTYPE_STRING_CTOR) {
+ WrapperInfo *info;
+ MonoMethod *m;
+
+ m = decode_resolve_method_ref (module, p, &p);
+ if (!m)
+ return FALSE;
+
+ if (!target)
+ return FALSE;
+ g_assert (target->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED);
+
+ info = mono_marshal_get_wrapper_info (target);
+ if (info && info->subtype == subtype && info->d.string_ctor.method == m)
ref->method = target;
else
return FALSE;
int subtype = decode_value (p, &p);
char *name;
- if (subtype == MONO_AOT_WRAPPER_JIT_ICALL) {
- g_assert (target);
+ if (subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
+ 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_CASTCLASS: {
int subtype = decode_value (p, &p);
- if (subtype == MONO_AOT_WRAPPER_CASTCLASS_WITH_CACHE)
+ if (subtype == WRAPPER_SUBTYPE_CASTCLASS_WITH_CACHE)
ref->method = mono_marshal_get_castclass_with_cache ();
- else if (subtype == MONO_AOT_WRAPPER_ISINST_WITH_CACHE)
+ else if (subtype == WRAPPER_SUBTYPE_ISINST_WITH_CACHE)
ref->method = mono_marshal_get_isinst_with_cache ();
else
g_assert_not_reached ();
case MONO_WRAPPER_RUNTIME_INVOKE: {
int subtype = decode_value (p, &p);
- g_assert (target);
+ if (!target)
+ return FALSE;
- if (subtype == MONO_AOT_WRAPPER_RUNTIME_INVOKE_DYNAMIC) {
+ if (subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DYNAMIC) {
if (strcmp (target->name, "runtime_invoke_dynamic") != 0)
return FALSE;
ref->method = target;
- } else if (subtype == MONO_AOT_WRAPPER_RUNTIME_INVOKE_DIRECT) {
+ } else if (subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT) {
/* Direct wrapper */
MonoMethod *m = decode_resolve_method_ref (module, p, &p);
if (!m)
return FALSE;
ref->method = mono_marshal_get_runtime_invoke (m, FALSE);
- } else if (subtype == MONO_AOT_WRAPPER_RUNTIME_INVOKE_VIRTUAL) {
+ } else if (subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL) {
/* Virtual direct wrapper */
MonoMethod *m = decode_resolve_method_ref (module, p, &p);
* 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];
int i, buf_len, num_clauses;
MonoJitInfo *jinfo;
guint used_int_regs, flags;
- gboolean has_generic_jit_info, has_dwarf_unwind_info, has_clauses, has_seq_points, has_try_block_holes;
+ gboolean has_generic_jit_info, has_dwarf_unwind_info, has_clauses, has_seq_points, has_try_block_holes, has_arch_eh_jit_info;
gboolean from_llvm, has_gc_map;
guint8 *p;
- int generic_info_size, try_holes_info_size, num_holes, this_reg = 0, this_offset = 0;
+ int generic_info_size, try_holes_info_size, num_holes, arch_eh_jit_info_size;
+ int this_reg = 0, this_offset = 0;
/* Load the method info from the AOT file */
from_llvm = (flags & 16) != 0;
has_try_block_holes = (flags & 32) != 0;
has_gc_map = (flags & 64) != 0;
+ has_arch_eh_jit_info = (flags & 128) != 0;
if (has_dwarf_unwind_info) {
guint32 offset;
num_clauses = decode_value (p, &p);
else
num_clauses = 0;
+ if (has_arch_eh_jit_info)
+ arch_eh_jit_info_size = sizeof (MonoArchEHJitInfo);
+ else
+ arch_eh_jit_info_size = 0;
if (from_llvm) {
MonoJitExceptionInfo *clauses;
}
}
- jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, clauses, num_clauses, generic_info_size + try_holes_info_size, nesting, &this_reg, &this_offset);
+ jinfo = decode_llvm_mono_eh_frame (amodule, domain, method, code, clauses, num_clauses, generic_info_size + try_holes_info_size + arch_eh_jit_info_size, nesting, &this_reg, &this_offset);
jinfo->from_llvm = 1;
g_free (clauses);
g_free (nesting);
} else {
jinfo =
- mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO + (sizeof (MonoJitExceptionInfo) * num_clauses) + generic_info_size + try_holes_info_size);
+ mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO + (sizeof (MonoJitExceptionInfo) * num_clauses) + generic_info_size + try_holes_info_size + arch_eh_jit_info_size);
jinfo->num_clauses = num_clauses;
for (i = 0; i < jinfo->num_clauses; ++i) {
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 */
}
}
+ if (has_arch_eh_jit_info) {
+ MonoArchEHJitInfo *eh_info;
+
+ jinfo->has_arch_eh_info = 1;
+
+ eh_info = mono_jit_info_get_arch_eh_info (jinfo);
+ eh_info->stack_size = decode_value (p, &p);
+ }
+
if (has_seq_points) {
MonoSeqPointInfo *seq_points;
int il_offset, native_offset, last_il_offset, last_native_offset, j;
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);
case MONO_PATCH_INFO_RGCTX_FETCH: {
gboolean res;
MonoJumpInfoRgctxEntry *entry;
+ guint32 offset, val;
+ guint8 *p2;
+
+ offset = decode_value (p, &p);
+ val = decode_value (p, &p);
entry = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoRgctxEntry));
- entry->method = decode_resolve_method_ref (aot_module, p, &p);
- entry->in_mrgctx = decode_value (p, &p);
- entry->info_type = decode_value (p, &p);
+ p2 = aot_module->blob + offset;
+ entry->method = decode_resolve_method_ref (aot_module, p2, &p2);
+ entry->in_mrgctx = ((val & 1) > 0) ? TRUE : FALSE;
+ entry->info_type = (val >> 1) & 0xff;
entry->data = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo));
- entry->data->type = decode_value (p, &p);
+ entry->data->type = (val >> 9) & 0xff;
res = decode_patch (aot_module, mp, entry->data, p, &p);
if (!res)
ji->data.imt_tramp = imt_tramp;
break;
}
+ case MONO_PATCH_INFO_SIGNATURE:
+ ji->data.target = decode_signature (aot_module, p, &p);
+ break;
default:
g_warning ("unhandled type %d", ji->type);
g_assert_not_reached ();
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;
guint32 index;
static guint32 n_extra_decodes;
- if (!amodule)
+ if (!amodule || amodule->out_of_date)
return 0xffffff;
table_size = amodule->extra_method_table [0];
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 ();