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);
#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)
+/* Pointer Encoding in the .eh_frame */
+enum {
+ DW_EH_PE_absptr = 0x00,
+ DW_EH_PE_omit = 0xff,
+
+ DW_EH_PE_udata4 = 0x03,
+ DW_EH_PE_sdata4 = 0x0b,
+ DW_EH_PE_sdata8 = 0x0c,
+
+ DW_EH_PE_pcrel = 0x10,
+ DW_EH_PE_textrel = 0x20,
+ DW_EH_PE_datarel = 0x30,
+ DW_EH_PE_funcrel = 0x40,
+ DW_EH_PE_aligned = 0x50,
+
+ DW_EH_PE_indirect = 0x80
+};
+
int
mono_hw_reg_to_dwarf_reg (int reg) MONO_INTERNAL;
*endp = p;
}
-/* Pointer Encoding in the .eh_frame */
-enum {
- DW_EH_PE_absptr = 0x00,
- DW_EH_PE_omit = 0xff,
-
- DW_EH_PE_udata4 = 0x03,
- DW_EH_PE_sdata4 = 0x0b,
- DW_EH_PE_sdata8 = 0x0c,
-
- DW_EH_PE_pcrel = 0x10,
- DW_EH_PE_textrel = 0x20,
- DW_EH_PE_datarel = 0x30,
- DW_EH_PE_funcrel = 0x40,
- DW_EH_PE_aligned = 0x50,
-
- DW_EH_PE_indirect = 0x80
-};
-
static gint64
read_encoded_val (guint32 encoding, guint8 *p, guint8 **endp)
{