Update the LLVM EH frame reader code to the latest llvm code.
authorZoltan Varga <vargaz@gmail.com>
Tue, 27 Mar 2012 20:02:28 +0000 (22:02 +0200)
committerZoltan Varga <vargaz@gmail.com>
Tue, 27 Mar 2012 20:02:28 +0000 (22:02 +0200)
mono/mini/aot-runtime.c
mono/mini/mini-unwind.h
mono/mini/unwind.c

index 21a67ba800e1a2494b7070909fae887d0a88a0f7..a5ecded6072ff540609f9ce0d111b27cae656d7f 100644 (file)
@@ -1939,7 +1939,7 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain,
        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;
@@ -1954,8 +1954,14 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain,
 
        /* 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;
@@ -1974,11 +1980,23 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain,
                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;
@@ -1988,9 +2006,14 @@ decode_llvm_mono_eh_frame (MonoAotModule *amodule, MonoDomain *domain,
                        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);
index f93e9bcefb8827927e1f5623b48c940e29f9a730..1d5be3190da6ae669686d365b8226e45ef936234 100644 (file)
@@ -92,6 +92,24 @@ typedef struct {
 #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;
 
index 55b938b9afa309476266ee7ddf4bd53eee0d79f2..11caa60166c115018f96ac558e85ac15bbdab1c2 100644 (file)
@@ -613,24 +613,6 @@ decode_cie_op (guint8 *p, guint8 **endp)
        *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)
 {