* exceptions-arm.c: Fix warnings.
* tramp-arm.c aot-compiler.c unwind.h unwind.c: Implement xdebug support for
ARM.
svn path=/trunk/mono/; revision=125019
2009-01-29 Zoltan Varga <vargaz@gmail.com>
+ * exceptions-arm.c: Fix warnings.
+
+ * tramp-arm.c aot-compiler.c unwind.h unwind.c: Implement xdebug support for
+ ARM.
+
* mini-x86.c: Fix --enable-minimal=jit build.
* mini.c: Really fix --enable-minimal=jit build.
fprintf (acfg->fp, "%s\n", ".data");
else
fprintf (acfg->fp, "%s\n", section_name);
-#elif defined(sparc) || defined(__arm__)
+#elif defined(sparc)
/* For solaris as, GNU as should accept the same */
fprintf (acfg->fp, ".section \"%s\"\n", section_name);
#else
guint8 *p, *buf, *debug_info;
MonoJitInfo *jinfo = cfg->jit_info;
guint32 flags;
+ gboolean use_unwind_ops = FALSE;
method = cfg->orig_method;
code = cfg->native_code;
buf_size = header->num_clauses * 256 + debug_info_size + 256;
p = buf = g_malloc (buf_size);
- flags = (jinfo->has_generic_jit_info ? 1 : 0) | ((cfg->unwind_ops != NULL) ? 2 : 0);
+#if defined(__x86_64__)
+ use_unwind_ops = cfg->unwind_ops != NULL;
+#endif
+
+ flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0);
encode_value (jinfo->code_size, p, &p);
encode_value (flags, p, &p);
- if (cfg->unwind_ops) {
+ if (use_unwind_ops) {
guint32 encoded_len;
guint8 *encoded;
static void
emit_cie (MonoAotCompile *acfg)
{
-#if defined(__x86_64__)
+#if defined(__x86_64__) || defined(__arm__)
emit_section_change (acfg, ".debug_frame", 0);
emit_alignment (acfg, 8);
#ifdef __x86_64__
emit_sleb128 (acfg, -8); /* data alignment factor */
emit_uleb128 (acfg, AMD64_RIP);
+#elif defined(__arm__)
+ emit_sleb128 (acfg, -4); /* data alignment factor */
+ emit_uleb128 (acfg, mono_hw_reg_to_dwarf_reg (ARMREG_LR));
#else
g_assert_not_reached ();
#endif
emit_uleb128 (acfg, 8); /* offset=8 */
emit_byte (acfg, DW_CFA_offset | AMD64_RIP);
emit_uleb128 (acfg, 1); /* offset=-8 */
+#elif defined(__arm__)
#else
g_assert_not_reached ();
#endif
emit_fde (MonoAotCompile *acfg, int fde_index, char *start_symbol, char *end_symbol,
guint8 *code, guint32 code_size, GSList *unwind_ops, gboolean use_cie)
{
-#if defined(__x86_64__)
+#if defined(__x86_64__) || defined(__arm__)
char symbol [128];
GSList *l;
guint8 *uw_info;
guint32 uw_info_len;
+#ifdef __arm__
+ if (!unwind_ops)
+ /*
+ * The debugger can unwind without unwind info, but gets confused by empty
+ * info.
+ */
+ return;
+#endif
+
emit_section_change (acfg, ".debug_frame", 0);
sprintf (symbol, ".Lfde%d_end", fde_index);
if (start_symbol) {
emit_pointer (acfg, start_symbol); /* initial_location */
emit_symbol_diff (acfg, end_symbol, start_symbol, 0); /* address_range */
- emit_int32 (acfg, 0);
} else {
emit_pointer_value (acfg, code);
emit_int32 (acfg, code_size);
- emit_int32 (acfg, 0);
}
+#if SIZEOF_VOID_P == 8
+ /* Upper 32 bits of code size */
+ emit_int32 (acfg, 0);
+#endif
l = unwind_ops;
#ifdef __x86_64__
/* Subprogram end */
emit_uleb128 (acfg, 0x0);
+ emit_line (acfg);
+
/* Emit unwind info */
emit_fde (acfg, acfg->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, TRUE);
acfg->fde_index ++;
void
mono_arm_throw_exception_by_token (guint32 type_token, unsigned long eip, unsigned long esp, gulong *int_regs, gdouble *fp_regs)
{
- mono_arm_throw_exception (mono_exception_from_token (mono_defaults.corlib, type_token), eip, esp, int_regs, fp_regs);
+ mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, type_token), eip, esp, int_regs, fp_regs);
}
/**
code += 4;
ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP);
} else {
- code = mono_arm_emit_load_imm (code, ARMREG_IP, GPOINTER_TO_UINT (by_token ? mono_arm_throw_exception_by_token : mono_arm_throw_exception));
+ code = mono_arm_emit_load_imm (code, ARMREG_IP, GPOINTER_TO_UINT (by_token ? (gpointer)mono_arm_throw_exception_by_token : (gpointer)mono_arm_throw_exception));
}
ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_IP);
guint8 *buf, *code = NULL;
guint8 *load_get_lmf_addr, *load_trampoline;
gpointer *constants;
+ GSList *unwind_ops = NULL, *l;
+ int cfa_offset;
*ji = NULL;
* saved as sp + LR_OFFSET by the push in the specific trampoline
*/
#define LR_OFFSET (sizeof (gpointer) * 13)
+
+ // FIXME: Finish the unwind info, the current info allows us to unwind
+ // when the trampoline is not in the epilog
+
+ // CFA = SP + (num registers pushed) * 4
+ cfa_offset = 14 * sizeof (gpointer);
+ mono_add_unwind_op_def_cfa (unwind_ops, code, buf, ARMREG_SP, cfa_offset);
+ // PC saved at sp+LR_OFFSET
+ mono_add_unwind_op_offset (unwind_ops, code, buf, ARMREG_LR, -4);
+
ARM_MOV_REG_REG (code, ARMREG_V1, ARMREG_SP);
if (aot && tramp_type != MONO_TRAMPOLINE_GENERIC_CLASS_INIT) {
/*
* the iregs array is already allocated on the stack by push.
*/
ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, sizeof (MonoLMF) - sizeof (guint) * 14);
+ cfa_offset += sizeof (MonoLMF) - sizeof (guint) * 14;
+ mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
ARM_ADD_REG_IMM8 (code, ARMREG_R1, ARMREG_SP, STACK - sizeof (MonoLMF));
/* r0 is the result from mono_get_lmf_addr () */
ARM_STR_IMM (code, ARMREG_R0, ARMREG_R1, G_STRUCT_OFFSET (MonoLMF, lmf_addr));
nullified_class_init_trampoline = mono_arch_get_nullified_class_init_trampoline (&code_len);
}
+ mono_save_trampoline_xdebug_info ("<generic_trampoline>", buf, *code_size, unwind_ops);
+
+ for (l = unwind_ops; l; l = l->next)
+ g_free (l->data);
+ g_slist_free (unwind_ops);
+
return buf;
}
/* Jump to the actual trampoline */
ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0); /* temp reg */
ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1);
- *(guint32*)code = tramp;
+ *(gpointer*)code = tramp;
code += 4;
}
/* Jump to the actual trampoline */
ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0); /* temp reg */
ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1);
- *(guint32*)code = tramp;
+ *(gpointer*)code = tramp;
code += 4;
mono_arch_flush_icache (buf, code - buf);
#ifdef __x86_64__
static int map_hw_reg_to_dwarf_reg [] = { 0, 2, 1, 3, 7, 6, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
#define NUM_REGS AMD64_NREG
+#define DWARF_DATA_ALIGN - 8
+#elif defined(__arm__)
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040a/IHI0040A_aadwarf.pdf
+static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+#define NUM_REGS 16
+#define DWARF_DATA_ALIGN - 4
#else
static int map_hw_reg_to_dwarf_reg [0];
#define NUM_REGS 0
+#define DWARF_DATA_ALIGN 0
#endif
static gboolean dwarf_reg_to_hw_reg_inited;
int
mono_hw_reg_to_dwarf_reg (int reg)
{
-#ifdef __x86_64__
- return map_hw_reg_to_dwarf_reg [reg];
-#else
- g_assert_not_reached ();
- return -1;
-#endif
+ if (NUM_REGS == 0) {
+ g_assert_not_reached ();
+ return -1;
+ } else {
+ return map_hw_reg_to_dwarf_reg [reg];
+ }
}
static void
break;
case DW_CFA_offset:
*p ++ = DW_CFA_offset | reg;
- encode_uleb128 (op->val / - 8, p, &p);
+ encode_uleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
break;
default:
g_assert_not_reached ();
/* Similar macros usable when a cfg is not available, like for trampolines */
#define mono_add_unwind_op_def_cfa(op_list,code,buf,reg,offset) do { (op_list) = g_slist_append ((op_list), mono_create_unwind_op ((code) - (buf), DW_CFA_def_cfa, (reg), (offset))); } while (0)
#define mono_add_unwind_op_def_cfa_reg(op_list,code,buf,reg) do { (op_list) = g_slist_append ((op_list), mono_create_unwind_op ((code) - (buf), DW_CFA_def_cfa_register, (reg), (0))); } while (0)
-#define mono_add_unwind_op_def_cfa_offset(op_list,code,buf,offset) do { (op_list) = g_slist_append ((op_list), mono_create_unwind_op ((code) - (buf), DW_CFA_def_cfa, 0, (offset))); } while (0)
+#define mono_add_unwind_op_def_cfa_offset(op_list,code,buf,offset) do { (op_list) = g_slist_append ((op_list), mono_create_unwind_op ((code) - (buf), DW_CFA_def_cfa_offset, 0, (offset))); } while (0)
#define mono_add_unwind_op_same_value(op_list,code,buf,reg) do { (op_list) = g_slist_append ((op_list), mono_create_unwind_op ((code) - (buf), DW_CFA_same_value, (reg), 0)); } while (0)
#define mono_add_unwind_op_offset(op_list,code,buf,reg,offset) do { (op_list) = g_slist_append ((op_list), mono_create_unwind_op ((code) - (buf), DW_CFA_offset, (reg), (offset))); } while (0)