/* AOT RUNTIME */
/*****************************************************/
+/*
+ * load_image:
+ *
+ * Load one of the images referenced by AMODULE. Returns NULL if the image is not
+ * found, and sets the loader error if SET_ERROR is TRUE.
+ */
static MonoImage *
-load_image (MonoAotModule *module, int index)
+load_image (MonoAotModule *amodule, int index, gboolean set_error)
{
MonoAssembly *assembly;
MonoImageOpenStatus status;
- g_assert (index < module->image_table_len);
+ g_assert (index < amodule->image_table_len);
- if (module->image_table [index])
- return module->image_table [index];
- if (module->out_of_date)
+ if (amodule->image_table [index])
+ return amodule->image_table [index];
+ if (amodule->out_of_date)
return NULL;
- assembly = mono_assembly_load (&module->image_names [index], NULL, &status);
+ assembly = mono_assembly_load (&amodule->image_names [index], NULL, &status);
if (!assembly) {
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is unusable because dependency %s is not found.\n", module->aot_name, module->image_names [index].name);
- module->out_of_date = TRUE;
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is unusable because dependency %s is not found.\n", amodule->aot_name, amodule->image_names [index].name);
+ amodule->out_of_date = TRUE;
+
+ if (set_error) {
+ char *full_name = mono_stringify_assembly_name (&amodule->image_names [index]);
+ mono_loader_set_error_assembly_load (full_name, FALSE);
+ g_free (full_name);
+ }
return NULL;
}
- if (strcmp (assembly->image->guid, module->image_guids [index])) {
- 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);
- module->out_of_date = TRUE;
+ if (strcmp (assembly->image->guid, amodule->image_guids [index])) {
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module %s is out of date (Older than dependency %s).\n", amodule->aot_name, amodule->image_names [index].name);
+ amodule->out_of_date = TRUE;
return NULL;
}
- module->image_table [index] = assembly->image;
+ amodule->image_table [index] = assembly->image;
return assembly->image;
}
-
static inline gint32
decode_value (guint8 *ptr, guint8 **rptr)
{
return NULL;
}
if (mono_metadata_token_table (token) == 0) {
- image = load_image (module, 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);
MonoType *type;
gclass = decode_klass_ref (module, p, &p);
+ if (!gclass)
+ return NULL;
g_assert (gclass->generic_container);
memset (&ctx, 0, sizeof (ctx));
g_assert_not_reached ();
}
} else {
- image = load_image (module, decode_value (p, &p));
+ image = load_image (module, decode_value (p, &p), TRUE);
if (!image)
return NULL;
klass = mono_class_get (image, token);
}
} else if (token == MONO_TOKEN_TYPE_DEF) {
/* Array */
- image = load_image (module, decode_value (p, &p));
+ image = load_image (module, decode_value (p, &p), TRUE);
if (!image)
return NULL;
rank = decode_value (p, &p);
g_assert_not_reached ();
}
g_assert (klass);
- mono_class_init (klass);
*endbuf = p;
return klass;
*method = mono_marshal_get_runtime_invoke (m, FALSE);
break;
}
+ case MONO_WRAPPER_MANAGED_TO_MANAGED: {
+ int subtype = decode_value (p, &p);
+
+ if (subtype == MONO_AOT_WRAPPER_ELEMENT_ADDR) {
+ int rank = decode_value (p, &p);
+ int elem_size = decode_value (p, &p);
+
+ *method = mono_marshal_get_array_address (rank, elem_size);
+ } else {
+ g_assert_not_reached ();
+ }
+ break;
+ }
default:
g_assert_not_reached ();
}
image_index = decode_value (p, &p);
*token = decode_value (p, &p);
- image = load_image (module, image_index);
+ image = load_image (module, image_index, TRUE);
if (!image)
return NULL;
} else if (image_index == MONO_AOT_METHODREF_GINST) {
image_index = decode_value (p, &p);
*token = decode_value (p, &p);
- image = load_image (module, image_index);
+ image = load_image (module, image_index, TRUE);
if (!image)
return NULL;
g_assert (image_index < MONO_AOT_METHODREF_MIN);
*token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
- image = load_image (module, image_index);
+ image = load_image (module, image_index, TRUE);
if (!image)
return NULL;
}
table_size = table [0];
table ++;
- hash = mono_aot_str_hash (name) % table_size;
+ hash = mono_metadata_str_hash (name) % table_size;
entry = &table [hash * 2];
* referenced assemblies, we depend on the exact versions of the referenced assemblies.
* MS calls this 'hard binding'. This means we have to load all referenced assemblies
* non-lazily, since we can't handle out-of-date errors later.
+ * The cached class info also depends on the exact assemblies.
*/
for (i = 0; i < amodule->image_table_len; ++i)
- load_image (amodule, i);
+ load_image (amodule, i, FALSE);
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);
full_name = g_strdup_printf ("%s.%s", name_space, name);
}
}
- hash = mono_aot_str_hash (full_name) % table_size;
+ hash = mono_metadata_str_hash (full_name) % table_size;
if (full_name != full_name_buf)
g_free (full_name);
guint32 eh_frame_ptr;
int fde_count;
gint32 *table;
- int pos, left, right, offset, offset1, offset2;
+ int i, pos, left, right, offset, offset1, offset2;
guint32 unw_len, code_len;
+ MonoJitExceptionInfo *ei;
+ guint32 ei_len;
g_assert (amodule->eh_frame_hdr);
eh_frame = amodule->eh_frame_hdr + table [(pos * 2) + 1];
- unwind_info = mono_unwind_get_ops_from_fde (eh_frame, &unw_len, &code_len);
+ unwind_info = mono_unwind_decode_fde (eh_frame, &unw_len, &code_len, &ei, &ei_len, NULL);
jinfo->code_size = code_len;
jinfo->used_regs = mono_cache_unwind_info (unwind_info, unw_len);
jinfo->domain_neutral = 0;
/* This signals that used_regs points to a normal cached unwind info */
jinfo->from_aot = 0;
+
+ g_assert (ei_len == jinfo->num_clauses);
+ for (i = 0; i < jinfo->num_clauses; ++i) {
+ MonoJitExceptionInfo *jei = &jinfo->clauses [i];
+
+ jei->try_start = ei [i].try_start;
+ jei->try_end = ei [i].try_end;
+ jei->handler_start = ei [i].handler_start;
+ }
}
#ifdef TARGET_ARM
/* The offsets in the table are 31 bits long, have to extend them to 32 */
#define EXTEND_PREL31(val) ((((gint32)(val)) << 1) >> 1)
+static inline guint32
+decode_uleb128 (guint8 *buf, guint8 **endbuf)
+{
+ guint8 *p = buf;
+ guint32 res = 0;
+ int shift = 0;
+
+ while (TRUE) {
+ guint8 b = *p;
+ p ++;
+
+ res = res | (((int)(b & 0x7f)) << shift);
+ if (!(b & 0x80))
+ break;
+ shift += 7;
+ }
+
+ *endbuf = p;
+
+ return res;
+}
+
+static GSList*
+decode_arm_eh_ops (guint8 *unwind_ops, int nops)
+{
+ int i, vsp_reg, vsp_offset;
+ GSList *ops;
+ gint32 *reg_offsets;
+
+ /*
+ * Have to convert the ARM unwind info into DWARF unwind info.
+ * The ARM unwind info specifies a simple set of instructions which need to be
+ * executed during unwinding. It manipulates a virtual stack pointer (vsp). The
+ * connection with DWARF unwind info is the following: after all ARM unwind
+ * opcodes have been executed, the stack should be completely unwound, i.e.
+ * vsp == DWARF CFA. This allows us to construct the DWARF opcodes corresponding
+ * to the ARM opcodes.
+ * The ARM unwind info is not instruction precise, i. e. it can't handle
+ * async exceptions etc.
+ */
+ /* The reg used to compute the initial value of vsp */
+ vsp_reg = ARMREG_SP;
+ /* The offset between vsp_reg and the CFA */
+ vsp_offset = 0;
+
+ /* The register save offsets from the initial value of vsp */
+ reg_offsets = g_new0 (gint32, 16);
+ for (i = 0; i < 16; ++i)
+ reg_offsets [i] = -1;
+
+ /* section 9.3 in the ehabi doc */
+ for (i = 0; i < nops; ++i) {
+ guint8 op = unwind_ops [i];
+
+ if ((op >> 6) == 0) {
+ /* vsp = vsp + (xxxxxx << 2) + 4. */
+ vsp_offset += ((op & 0x3f) << 2) + 4;
+ } else if ((op >> 6) == 1) {
+ /* vsp = vsp - (xxxxxx << 2) - 4. */
+ vsp_offset -= ((op & 0x3f) << 2) + 4;
+ } else if (op == 0xb2) {
+ /* vsp = vsp = vsp + 0x204 + (uleb128 << 2) */
+ guint8 *p = unwind_ops + i + 1;
+ guint32 v = decode_uleb128 (p, &p);
+
+ vsp_offset += 0x204 + (v << 2);
+ i = (p - unwind_ops) - 1;
+ } else if (op >= 0x80 && op <= 0x8f) {
+ /* pop registers */
+ guint8 op2;
+ GSList *regs;
+ int j;
+
+ g_assert (i + 1 < nops);
+ op2 = unwind_ops [i + 1];
+
+ regs = NULL;
+ for (j = 0; j < 8; ++j)
+ if (op2 & (0x1 << j))
+ regs = g_slist_append (regs, GUINT_TO_POINTER (ARMREG_R4 + j));
+ for (j = 0; j < 4; ++j)
+ if (op & (0x1 << j))
+ regs = g_slist_append (regs, GUINT_TO_POINTER (ARMREG_R12 + j));
+ g_assert (regs);
+
+ for (j = 0; j < g_slist_length (regs); ++j)
+ reg_offsets [GPOINTER_TO_UINT (g_slist_nth (regs, j)->data)] = vsp_offset + (j * 4);
+
+ vsp_offset += g_slist_length (regs) * 4;
+
+ g_slist_free (regs);
+
+ i ++;
+ } else if (op >= 0xa8 && op <= 0xaf) {
+ GSList *regs;
+ int j;
+
+ /* pop r4-r[4 + nnn], r14 */
+
+ regs = NULL;
+ for (j = 0; j <= (op & 0x7); ++j)
+ regs = g_slist_append (regs, GUINT_TO_POINTER (ARMREG_R4 + j));
+ regs = g_slist_append (regs, GUINT_TO_POINTER (ARMREG_R14));
+
+ for (j = 0; j < g_slist_length (regs); ++j)
+ reg_offsets [GPOINTER_TO_UINT (g_slist_nth (regs, j)->data)] = vsp_offset + (j * 4);
+
+ vsp_offset += g_slist_length (regs) * 4;
+
+ g_slist_free (regs);
+ } else if (op == 0xb0) {
+ /* finish */
+ break;
+ } else if (op >= 0x90 && op <= 0x9f && op != 0x9d && op != 0x9f) {
+ /* vsp = <reg> */
+ vsp_reg = op & 0xf;
+ vsp_offset = 0;
+ } else {
+ int j;
+
+ for (j = 0; j < nops; ++j)
+ printf ("%x ", unwind_ops [j]);
+ printf (" / %d\n", i);
+ g_assert_not_reached ();
+ }
+ }
+
+ ops = NULL;
+
+ /* vsp_reg + vsp_offset = CFA */
+ mono_add_unwind_op_def_cfa (ops, (guint8*)NULL, (guint8*)NULL, vsp_reg, vsp_offset);
+
+ for (i = 0; i < 16; ++i) {
+ if (reg_offsets [i] != -1)
+ /* The reg is saved at vsp_reg + reg_offset [i] == CFA - (vsp_offset - reg_offset [i]) */
+ mono_add_unwind_op_offset (ops, (guint8*)NULL, (guint8*)NULL, i, - (vsp_offset - reg_offsets [i]));
+ }
+
+ return ops;
+}
+
/*
* decode_arm_exidx:
*
{
guint32 *table;
guint8 *base, *code1, *code2;
- int i, pos, left, right, offset, offset1, offset2, count, nops, cfa_reg, cfa_offset;
- int vsp_offset;
+ int i, pos, left, right, offset, offset1, offset2, count, nwords, nops;
guint32 entry;
- guint8 unwind_ops [4];
+ guint8 unwind_ops [64];
GSList *ops;
guint8 *unwind_info;
guint32 unw_len;
- gint32 *reg_offsets;
g_assert (amodule->arm_exidx);
while (TRUE) {
pos = (left + right) / 2;
+ if (left == right)
+ break;
+
offset1 = EXTEND_PREL31 (table [(pos * 2)]);
code1 = (guint8*)&(table [pos * 2]) + offset1;
if (pos + 1 == count)
break;
}
- /*
- * The linker might merge duplicate unwind table entries, so
- * offset1 and offset2 might point to another method, but this is not a problem.
- */
- code1 = (guint8*)&(table [pos * 2]) + offset1;
- code2 = (guint8*)&(table [(pos + 1) * 2]) + offset2;
-
- g_assert (code >= code1);
- if (pos < count)
- g_assert (code < code2);
-
- entry = table [(pos * 2) + 1];
-
- /* compact model, personality routine 0 */
- g_assert ((entry & 0xff000000) == 0x80000000);
-
- unwind_ops [0] = (entry & 0x00ff0000) >> 16;
- unwind_ops [1] = (entry & 0x0000ff00) >> 8;
- unwind_ops [2] = (entry & 0x000000ff) >> 0;
-
- ops = NULL;
-
- /*
- * Have to convert the ARM unwind info into DWARF unwind info.
- * The ARM unwind opcodes manipulate a virtual stack pointer (vsp). After all
- * the opcodes have been executed, vsp should be equal to the value of the
- * DWARF cfa.
- */
-
- /* The offsets from the initial value of vsp */
- reg_offsets = g_new0 (gint32, 16);
- for (i = 0; i < 16; ++i)
- reg_offsets [i] = -1;
+ if (code >= code1) {
+ /*
+ * The linker might merge duplicate unwind table entries, so
+ * offset1 and offset2 might point to another method, but this is not a problem.
+ */
+ code1 = (guint8*)&(table [pos * 2]) + offset1;
+ code2 = (guint8*)&(table [(pos + 1) * 2]) + offset2;
- /* The ARM unwind info is not instruction precise */
- cfa_reg = ARMREG_SP;
- cfa_offset = 0;
- vsp_offset = 0;
+ g_assert (code >= code1);
+ if (pos < count)
+ g_assert (code < code2);
- /* section 9.3 in the ehabi doc */
- nops = 3;
- for (i = 0; i < nops; ++i) {
- guint8 op = unwind_ops [i];
+ entry = table [(pos * 2) + 1];
- if ((op >> 6) == 0) {
- /* vsp = vsp + (xxxxxx << 2) + 4. */
- vsp_offset += ((op & 0xfff) << 2) + 4;
- } else if (op >= 0x80 && op <= 0x8f) {
- /* pop registers */
- guint8 op2;
- GSList *regs;
- int j;
+ /* inline entry, compact model, personality routine 0 */
+ if ((entry & 0xff000000) == 0x80000000) {
+ nops = 3;
+ unwind_ops [0] = (entry & 0x00ff0000) >> 16;
+ unwind_ops [1] = (entry & 0x0000ff00) >> 8;
+ unwind_ops [2] = (entry & 0x000000ff) >> 0;
- /* FIXME: */
- g_assert (i == 0 || i == 1);
+ ops = decode_arm_eh_ops (unwind_ops, nops);
+ } else if ((entry & 0x80000000) == 0) {
+ /* non-inline entry */
+ guint8 *data = (guint8*)&table [(pos * 2) + 1] + EXTEND_PREL31 (entry);
- g_assert (i + 1 < nops);
- op2 = unwind_ops [i + 1];
+ entry = ((guint32*)data) [0];
- regs = NULL;
- for (j = 0; j < 8; ++j)
- if (op2 & (0x1 << j))
- regs = g_slist_append (regs, GUINT_TO_POINTER (ARMREG_R4 + j));
- for (j = 0; j < 4; ++j)
- if (op & (0x1 << j))
- regs = g_slist_append (regs, GUINT_TO_POINTER (ARMREG_R12 + j));
- g_assert (regs);
+ /* compact model, personality routine 1 */
+ g_assert ((entry & 0xff000000) == 0x81000000);
- for (j = 0; j < g_slist_length (regs); ++j)
- reg_offsets [GPOINTER_TO_UINT (g_slist_nth (regs, j)->data)] = vsp_offset + (j * 4);
+ nwords = (entry & 0x00ff0000) >> 16;
+ nops = nwords * 4 + 2;
+ g_assert (nops < 64);
- vsp_offset += g_slist_length (regs) * 4;
+ unwind_ops [0] = (entry & 0x0000ff00) >> 8;
+ unwind_ops [1] = (entry & 0x000000ff) >> 0;
- g_slist_free (regs);
+ for (i = 0; i < nwords; ++i) {
+ entry = ((guint32*)data) [1 + i];
+ unwind_ops [(i * 4) + 2] = (entry & 0xff000000) >> 24;
+ unwind_ops [(i * 4) + 2 + 1] = (entry & 0x00ff0000) >> 16;
+ unwind_ops [(i * 4) + 2 + 2] = (entry & 0x0000ff00) >> 8;
+ unwind_ops [(i * 4) + 2 + 3] = (entry & 0x000000ff) >> 0;
+ }
- i ++;
- } else if (op == 0xb0) {
- /* finish */
- break;
+ ops = decode_arm_eh_ops (unwind_ops, nops);
} else {
- printf ("%x\n", entry & 0x00ffffff);
- g_assert_not_reached ();
+ NOT_IMPLEMENTED;
}
- }
- /* sp + vsp_offset = CFA */
- mono_add_unwind_op_def_cfa (ops, code, code, ARMREG_SP, vsp_offset);
- for (i = 0; i < 16; ++i) {
- if (reg_offsets [i] != -1)
- /* The reg is saved at sp + reg_offset [i] == CFA - (vsp_offset - reg_offset [i]) */
- mono_add_unwind_op_offset (ops, code, code, i, - (vsp_offset - reg_offsets [i]));
+ unwind_info = mono_unwind_ops_encode (ops, &unw_len);
+ } else {
+ /* The method has no unwind info */
+ unwind_info = NULL;
+ unw_len = 0;
}
- unwind_info = mono_unwind_ops_encode (ops, &unw_len);
-
jinfo->code_size = code_len;
jinfo->used_regs = mono_cache_unwind_info (unwind_info, unw_len);
jinfo->method = method;
#else
decode_eh_frame (amodule, domain, method, code, jinfo);
#endif
+ jinfo->from_llvm = 1;
} else {
jinfo->code_size = code_len;
jinfo->used_regs = used_int_regs;
}
if (has_seq_points) {
- GPtrArray *seq_points;
- int il_offset, native_offset, last_il_offset, last_native_offset;
+ MonoSeqPointInfo *seq_points;
+ int il_offset, native_offset, last_il_offset, last_native_offset, j;
int len = decode_value (p, &p);
- seq_points = g_ptr_array_new ();
+ seq_points = g_malloc0 (sizeof (MonoSeqPointInfo) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (SeqPoint));
last_il_offset = last_native_offset = 0;
- for (i = 0; i < len; i += 2) {
+ for (i = 0; i < len; ++i) {
+ SeqPoint *sp = &seq_points->seq_points [i];
il_offset = last_il_offset + decode_value (p, &p);
native_offset = last_native_offset + decode_value (p, &p);
- g_ptr_array_add (seq_points, GINT_TO_POINTER (il_offset));
- g_ptr_array_add (seq_points, GINT_TO_POINTER (native_offset));
+ sp->il_offset = il_offset;
+ sp->native_offset = native_offset;
+
+ sp->next_len = decode_value (p, &p);
+ sp->next = g_new (int, sp->next_len);
+ for (j = 0; j < sp->next_len; ++j)
+ sp->next [j] = decode_value (p, &p);
last_il_offset = il_offset;
last_native_offset = native_offset;
goto cleanup;
break;
case MONO_PATCH_INFO_IMAGE:
- ji->data.image = load_image (aot_module, decode_value (p, &p));
+ ji->data.image = load_image (aot_module, decode_value (p, &p), TRUE);
if (!ji->data.image)
goto cleanup;
break;
break;
}
case MONO_PATCH_INFO_LDSTR:
- image = load_image (aot_module, decode_value (p, &p));
+ image = load_image (aot_module, decode_value (p, &p), TRUE);
if (!image)
goto cleanup;
ji->data.token = mono_jump_info_token_new (mp, image, MONO_TOKEN_STRING + decode_value (p, &p));
case MONO_PATCH_INFO_LDTOKEN:
case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
/* Shared */
- image = load_image (aot_module, decode_value (p, &p));
+ image = load_image (aot_module, decode_value (p, &p), TRUE);
if (!image)
goto cleanup;
ji->data.token = mono_jump_info_token_new (mp, image, decode_value (p, &p));
if (mono_jit_stats.methods_aot >= mono_last_aot_method)
return NULL;
else if (mono_jit_stats.methods_aot == mono_last_aot_method - 1) {
- if (method)
- printf ("LAST AOT METHOD: %s%s%s.%s.\n", method->klass->name_space, method->klass->name_space [0] ? "." : "", method->klass->name, method->name);
- else
+ if (!method)
+ method = mono_get_method (image, token, NULL);
+ if (method) {
+ char *name = mono_method_full_name (method, TRUE);
+ printf ("LAST AOT METHOD: %s.\n", name);
+ g_free (name);
+ } else {
printf ("LAST AOT METHOD: %p %d\n", code, method_index);
+ }
}
}
full_name = mono_method_full_name (method, TRUE);
if (!jinfo)
- jinfo = mono_aot_find_jit_info (domain, method->klass->image, code);
+ jinfo = mono_aot_find_jit_info (domain, amodule->assembly->image, code);
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);
g_free (full_name);
}
static guint32
-find_extra_method_in_amodule (MonoAotModule *amodule, MonoMethod *method)
+find_extra_method_in_amodule (MonoAotModule *amodule, MonoMethod *method, const char *name)
{
guint32 table_size, entry_size, hash;
guint32 *table, *entry;
- char *name = NULL;
guint32 index;
static guint32 n_extra_decodes;
table = amodule->extra_method_table + 1;
entry_size = 3;
- if (method->wrapper_type) {
- name = mono_aot_wrapper_name (method);
- }
-
hash = mono_aot_method_hash (method) % table_size;
entry = &table [hash * entry_size];
break;
}
- g_free (name);
return index;
}
guint32 index;
GPtrArray *modules;
int i;
+ char *name = NULL;
+
+ if (method->wrapper_type)
+ name = mono_aot_wrapper_name (method);
/* Try the method's module first */
*out_amodule = method->klass->image->aot_module;
- index = find_extra_method_in_amodule (method->klass->image->aot_module, method);
- if (index != 0xffffff)
+ index = find_extra_method_in_amodule (method->klass->image->aot_module, method, name);
+ if (index != 0xffffff) {
+ g_free (name);
return index;
+ }
/*
* Try all other modules.
MonoAotModule *amodule = g_ptr_array_index (modules, i);
if (amodule != method->klass->image->aot_module)
- index = find_extra_method_in_amodule (amodule, method);
+ index = find_extra_method_in_amodule (amodule, method, name);
if (index != 0xffffff) {
*out_amodule = amodule;
break;
g_ptr_array_free (modules, TRUE);
+ g_free (name);
return index;
}
code = mono_aot_get_method (domain, m);
if (code) {
- if (mono_method_needs_static_rgctx_invoke (m, FALSE))
- code = mono_create_static_rgctx_trampoline (m, code);
+ if (mono_method_needs_static_rgctx_invoke (m, FALSE)) {
+ code = mono_create_static_rgctx_trampoline (m, mono_create_ftnptr (domain, code));
+ /* The call above returns an ftnptr */
+ code = mono_get_addr_from_ftnptr (code);
+ }
return code;
}
*
* This function is called by the entries in the PLT to resolve the actual method that
* needs to be called. It returns a trampoline to the method and patches the PLT entry.
+ * Returns NULL if the something cannot be loaded.
*/
gpointer
mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code)
mp = mono_mempool_new_size (512);
res = decode_patch (module, mp, &ji, p, &p);
- // FIXME: Error handling (how ?)
- g_assert (res);
+
+ if (!res) {
+ mono_mempool_destroy (mp);
+ return NULL;
+ }
/*
* Avoid calling resolve_patch_target in the full-aot case if possible, since
if (ji.type == MONO_PATCH_INFO_ABS || ji.type == MONO_PATCH_INFO_INTERNAL_METHOD || ji.type == MONO_PATCH_INFO_CLASS_INIT || ji.type == MONO_PATCH_INFO_ICALL_ADDR || ji.type == MONO_PATCH_INFO_JIT_ICALL_ADDR || ji.type == MONO_PATCH_INFO_RGCTX_FETCH) {
/* These should already have a function descriptor */
#ifdef PPC_USES_FUNCTION_DESCRIPTOR
- g_assert (((gpointer*)target) [2] == 0);
+ /* Our function descriptors have a 0 environment, gcc created ones don't */
+ if (ji.type != MONO_PATCH_INFO_INTERNAL_METHOD && ji.type != MONO_PATCH_INFO_JIT_ICALL_ADDR && ji.type != MONO_PATCH_INFO_ICALL_ADDR)
+ g_assert (((gpointer*)target) [2] == 0);
#endif
+ /* Empty */
} else if (!no_ftnptr) {
#ifdef PPC_USES_FUNCTION_DESCRIPTOR
g_assert (((gpointer*)target) [2] != 0);
symbol = g_strdup_printf ("rgctx_fetch_trampoline_%u", slot);
code = load_function (mono_defaults.corlib->aot_module, symbol);
g_free (symbol);
- return code;
+ /* The caller expects an ftnptr */
+ return mono_create_ftnptr (mono_domain_get (), code);
}
gpointer