2008-12-07 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Sun, 7 Dec 2008 17:18:43 +0000 (17:18 -0000)
committerZoltan Varga <vargaz@gmail.com>
Sun, 7 Dec 2008 17:18:43 +0000 (17:18 -0000)
* unwind.c: New file, move the unwind info encoding functions here from
aot-compiler.c, so they could be used at runtime too.

svn path=/trunk/mono/; revision=120960

mono/mini/ChangeLog
mono/mini/Makefile.am
mono/mini/aot-compiler.c
mono/mini/unwind.c [new file with mode: 0644]

index 2cbcead8320313e3612a348f70f4531129dd141e..b094d890bd7fb2bade0123619da0e49845f6aa28 100644 (file)
@@ -1,3 +1,8 @@
+2008-12-07  Zoltan Varga  <vargaz@gmail.com>
+
+       * unwind.c: New file, move the unwind info encoding functions here from
+       aot-compiler.c, so they could be used at runtime too.
+
 2008-12-05  Mark Mason   <mmason@upwardaccess.com>
 
        * mini-mips.c (mono_arch_lowering_pass): handle OP_IMUL_IMM as well
index 9ea2e21e7736e64c207cf5ee5ef3087f7bf6f668..c0df396fc5f4e0ad112741ad1f706cf8c3a0ccf1 100644 (file)
@@ -262,7 +262,8 @@ common_sources = \
        regalloc2.c     \
        simd-methods.h  \
        simd-intrinsics.c       \
-       unwind.h
+       unwind.h        \
+       unwind.c
 
 test_sources =                 \
        basic-calls.cs  \
index 49ceb7e727abd0232c69a43f3de76b0ad0c046cb..22bd9c4f5e7e9e296ca919fe9b51cdd9870f1a0c 100644 (file)
@@ -5316,21 +5316,6 @@ emit_dwarf_abbrev (MonoAotCompile *acfg, int code, int tag, gboolean has_child,
        emit_uleb128 (acfg, 0);
 }
 
-#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 };
-#endif
-
-static int
-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
-}
-
 static void
 emit_cie (MonoAotCompile *acfg)
 {
@@ -5354,7 +5339,7 @@ emit_cie (MonoAotCompile *acfg)
 
 #ifdef __x86_64__
        emit_byte (acfg, DW_CFA_def_cfa);
-       emit_uleb128 (acfg, hw_reg_to_dwarf_reg (AMD64_RSP));
+       emit_uleb128 (acfg, mono_hw_reg_to_dwarf_reg (AMD64_RSP));
        emit_uleb128 (acfg, 8); /* offset=8 */
        emit_byte (acfg, DW_CFA_offset | AMD64_RIP);
        emit_uleb128 (acfg, 1); /* offset=-8 */
@@ -5381,8 +5366,8 @@ emit_fde (MonoAotCompile *acfg, int fde_index, char *start_symbol, char *end_sym
 #if defined(__x86_64__)
        char symbol [128];
        GSList *l;
-       MonoUnwindOp *op;
-       int loc;
+       guint8 *uw_info;
+       guint32 uw_info_len;
 
        emit_section_change (acfg, ".debug_frame", 0);
 
@@ -5399,52 +5384,16 @@ emit_fde (MonoAotCompile *acfg, int fde_index, char *start_symbol, char *end_sym
                emit_int32 (acfg, 0);
        }
 
-       /* Convert the list of MonoUnwindOps to the format used by DWARF */
-       loc = 0;
        l = unwind_ops;
 #ifdef __x86_64__
        /* Skip the first two ops which are in the CIE */
        l = l->next->next;
 #endif
-       for (; l; l = l->next) {
-               int reg;
-
-               op = l->data;
 
-               /* Convert the register from the hw encoding to the dwarf encoding */
-               reg = hw_reg_to_dwarf_reg (op->reg);
-
-               /* Emit an advance_loc if neccesary */
-               if (op->when > loc) {
-                       g_assert (op->when - loc < 32);
-                       emit_byte (acfg, DW_CFA_advance_loc | (op->when - loc));
-               }                       
-
-               switch (op->op) {
-               case DW_CFA_def_cfa:
-                       emit_byte (acfg, op->op);
-                       emit_uleb128 (acfg, reg);
-                       emit_uleb128 (acfg, op->val);
-                       break;
-               case DW_CFA_def_cfa_offset:
-                       emit_byte (acfg, op->op);
-                       emit_uleb128 (acfg, op->val);
-                       break;
-               case DW_CFA_def_cfa_register:
-                       emit_byte (acfg, op->op);
-                       emit_uleb128 (acfg, reg);
-                       break;
-               case DW_CFA_offset:
-                       emit_byte (acfg, DW_CFA_offset | reg);
-                       emit_uleb128 (acfg, op->val / - 8);
-                       break;
-               default:
-                       g_assert_not_reached ();
-                       break;
-               }
-
-               loc = op->when;
-       }
+       /* Convert the list of MonoUnwindOps to the format used by DWARF */     
+       uw_info = mono_unwind_ops_encode (l, &uw_info_len);
+       emit_bytes (acfg, uw_info, uw_info_len);
+       g_free (uw_info);
 
        emit_alignment (acfg, sizeof (gpointer));
        sprintf (symbol, ".Lfde%d_end", fde_index);
@@ -5868,13 +5817,13 @@ emit_method_dwarf_info (MonoAotCompile *acfg, MonoMethod *method, char *start_sy
                        emit_byte (acfg, 0);
                } else if (arg->opcode == OP_REGVAR) {
                        emit_byte (acfg, 1);
-                       emit_byte (acfg, DW_OP_reg0 + hw_reg_to_dwarf_reg (arg->dreg));
+                       emit_byte (acfg, DW_OP_reg0 + mono_hw_reg_to_dwarf_reg (arg->dreg));
                } else if (arg->opcode == OP_REGOFFSET) {
                        guint8 buf [128];
                        guint8 *p;
 
                        p = buf;
-                       *p ++= DW_OP_breg0 + hw_reg_to_dwarf_reg (arg->inst_basereg);
+                       *p ++= DW_OP_breg0 + mono_hw_reg_to_dwarf_reg (arg->inst_basereg);
                        encode_sleb128 (arg->inst_offset, p, &p);
                        emit_byte (acfg, p - buf);
                        emit_bytes (acfg, buf, p - buf);
diff --git a/mono/mini/unwind.c b/mono/mini/unwind.c
new file mode 100644 (file)
index 0000000..0cd932b
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * unwind.c: Stack Unwinding Interface
+ *
+ * Authors:
+ *   Zoltan Varga (vargaz@gmail.com)
+ *
+ * (C) 2008 Novell, Inc.
+ */
+
+#include "mini.h"
+#include "unwind.h"
+
+#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 };
+#endif
+
+/*
+ * mono_hw_reg_to_dwarf_reg:
+ *
+ *   Map the hardware register number REG to the register number used by DWARF.
+ */
+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
+}
+
+static G_GNUC_UNUSED void
+encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
+{
+       guint8 *p = buf;
+
+       do {
+               guint8 b = value & 0x7f;
+               value >>= 7;
+               if (value != 0) /* more bytes to come */
+                       b |= 0x80;
+               *p ++ = b;
+       } while (value);
+
+       *endbuf = p;
+}
+
+/*
+ * mono_unwind_ops_encode:
+ *
+ *   Encode the unwind ops in UNWIND_OPS into the compact DWARF encoding.
+ * Return a pointer to malloc'ed memory.
+ */
+guint8*
+mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
+{
+       GSList *l;
+       MonoUnwindOp *op;
+       int loc;
+       guint8 *buf, *p, *res;
+
+       p = buf = g_malloc0 (256);
+
+       loc = 0;
+       l = unwind_ops;
+       for (; l; l = l->next) {
+               int reg;
+
+               op = l->data;
+
+               /* Convert the register from the hw encoding to the dwarf encoding */
+               reg = mono_hw_reg_to_dwarf_reg (op->reg);
+
+               /* Emit an advance_loc if neccesary */
+               if (op->when > loc) {
+                       g_assert (op->when - loc < 32);
+                       *p ++ = DW_CFA_advance_loc | (op->when - loc);
+               }                       
+
+               switch (op->op) {
+               case DW_CFA_def_cfa:
+                       *p ++ = op->op;
+                       encode_uleb128 (reg, p, &p);
+                       encode_uleb128 (op->val, p, &p);
+                       break;
+               case DW_CFA_def_cfa_offset:
+                       *p ++ = op->op;
+                       encode_uleb128 (op->val, p, &p);
+                       break;
+               case DW_CFA_def_cfa_register:
+                       *p ++ = op->op;
+                       encode_uleb128 (reg, p, &p);
+                       break;
+               case DW_CFA_offset:
+                       *p ++ = DW_CFA_offset | reg;
+                       encode_uleb128 (op->val / - 8, p, &p);
+                       break;
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+
+               loc = op->when;
+       }
+       
+       g_assert (p - buf < 256);
+       *out_len = p - buf;
+       res = g_malloc (p - buf);
+       memcpy (res, buf, p - buf);
+       g_free (buf);
+       return res;
+}