Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / unwind.c
index 960447171e690e113129845451173abf39cbcadb..72f5d0d59e0b959373fcb1cb00dee5b86b4b601d 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * unwind.c: Stack Unwinding Interface
+/**
+ * \file
+ * Stack Unwinding Interface
  *
  * Authors:
  *   Zoltan Varga (vargaz@gmail.com)
@@ -382,14 +383,14 @@ mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enab
 
                /* Emit an advance_loc if neccesary */
                while (op->when > loc) {
-                       if (op->when - loc > 65536) {
+                       if (op->when - loc >= 65536) {
                                *p ++ = DW_CFA_advance_loc4;
                                guint32 v = (guint32)(op->when - loc);
                                memcpy (p, &v, 4);
                                g_assert (read32 (p) == (guint32)(op->when - loc));
                                p += 4;
                                loc = op->when;
-                       } else if (op->when - loc > 256) {
+                       } else if (op->when - loc >= 256) {
                                *p ++ = DW_CFA_advance_loc2;
                                guint16 v = (guint16)(op->when - loc);
                                memcpy (p, &v, 2);
@@ -866,9 +867,10 @@ read_encoded_val (guint32 encoding, guint8 *p, guint8 **endp)
  * decode_lsda:
  *
  *   Decode the Mono specific Language Specific Data Area generated by LLVM.
+ * This function is async safe.
  */
 static void
-decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo **ex_info, guint32 *ex_info_len, gpointer **type_info, int *this_reg, int *this_offset)
+decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo *ex_info, gpointer *type_info, guint32 *ex_info_len, int *this_reg, int *this_offset)
 {
        guint8 *p;
        int i, ncall_sites, this_encoding;
@@ -904,12 +906,8 @@ decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo **ex_info, guint32
        ncall_sites = decode_uleb128 (p, &p);
        p = (guint8*)ALIGN_TO ((mgreg_t)p, 4);
 
-       if (ex_info) {
-               *ex_info = (MonoJitExceptionInfo *)g_malloc0 (ncall_sites * sizeof (MonoJitExceptionInfo));
+       if (ex_info_len)
                *ex_info_len = ncall_sites;
-       }
-       if (type_info)
-               *type_info = (gpointer *)g_malloc0 (ncall_sites * sizeof (gpointer));
 
        for (i = 0; i < ncall_sites; ++i) {
                int block_start_offset, block_size, landing_pad;
@@ -929,11 +927,11 @@ decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo **ex_info, guint32
                //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
 
                if (ex_info) {
-                       if (*type_info)
-                               (*type_info) [i] = tinfo;
-                       (*ex_info)[i].try_start = code + block_start_offset;
-                       (*ex_info)[i].try_end = code + block_start_offset + block_size;
-                       (*ex_info)[i].handler_start = code + landing_pad;
+                       if (type_info)
+                               type_info [i] = tinfo;
+                       ex_info[i].try_start = code + block_start_offset;
+                       ex_info[i].try_end = code + block_start_offset + block_size;
+                       ex_info[i].handler_start = code + landing_pad;
                }
        }
 }
@@ -1072,7 +1070,16 @@ mono_unwind_decode_fde (guint8 *fde, guint32 *out_len, guint32 *code_len, MonoJi
                if (lsda_offset != 0) {
                        lsda = fde_aug + lsda_offset;
 
-                       decode_lsda (lsda, code, ex_info, ex_info_len, type_info, this_reg, this_offset);
+                       /* Get the lengths first */
+                       guint32 len;
+                       decode_lsda (lsda, code, NULL, NULL, &len, this_reg, this_offset);
+
+                       if (ex_info)
+                               *ex_info = (MonoJitExceptionInfo *)g_malloc0 (len * sizeof (MonoJitExceptionInfo));
+                       if (type_info)
+                               *type_info = (gpointer *)g_malloc0 (len * sizeof (gpointer));
+
+                       decode_lsda (lsda, code, ex_info ? *ex_info : NULL, type_info ? *type_info : NULL, ex_info_len, this_reg, this_offset);
                }
        }
 
@@ -1115,13 +1122,15 @@ mono_unwind_decode_fde (guint8 *fde, guint32 *out_len, guint32 *code_len, MonoJi
  * mono_unwind_decode_mono_fde:
  *
  *   Decode an FDE entry in the LLVM emitted mono EH frame.
- * info->ex_info is set to a malloc-ed array of MonoJitExceptionInfo structures,
- * only try_start, try_end and handler_start is set.
- * info->type_info is set to a malloc-ed array containing the ttype table from the
- * LSDA.
+ * If EI/TYPE_INFO/UNW_INFO are NULL, compute only the value of the scalar fields in INFO.
+ * Otherwise:
+ * - Fill out EX_INFO with try_start, try_end and handler_start.
+ * - Fill out TYPE_INFO with the ttype table from the LSDA.
+ * - Fill out UNW_INFO with the unwind info.
+ * This function is async safe.
  */
 void
-mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8 *code, MonoLLVMFDEInfo *res)
+mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8 *code, MonoLLVMFDEInfo *res, MonoJitExceptionInfo *ex_info, gpointer *type_info, guint8 *unw_info)
 {
        guint8 *p, *fde_aug, *cie_cfi, *fde_cfi, *buf;
        int has_aug, aug_len, cie_cfi_len, fde_cfi_len;
@@ -1151,7 +1160,10 @@ mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8
                /* The LSDA is embedded directly into the FDE */
                lsda = fde_aug;
 
-               decode_lsda (lsda, code, &res->ex_info, &res->ex_info_len, &res->type_info, &res->this_reg, &res->this_offset);
+               /* Get the lengths first */
+               decode_lsda (lsda, code, NULL, NULL, &res->ex_info_len, &res->this_reg, &res->this_offset);
+
+               decode_lsda (lsda, code, ex_info, type_info, NULL, &res->this_reg, &res->this_offset);
        }
 
        /* Decode CIE */
@@ -1182,12 +1194,13 @@ mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8
        cie_cfi_len = p - cie_cfi;
        fde_cfi_len = (fde + fde_len - fde_cfi);
 
-       buf = (guint8 *)g_malloc0 (cie_cfi_len + fde_cfi_len);
-       memcpy (buf, cie_cfi, cie_cfi_len);
-       memcpy (buf + cie_cfi_len, fde_cfi, fde_cfi_len);
+       buf = unw_info;
+       if (buf) {
+               memcpy (buf, cie_cfi, cie_cfi_len);
+               memcpy (buf + cie_cfi_len, fde_cfi, fde_cfi_len);
+       }
 
        res->unw_info_len = cie_cfi_len + fde_cfi_len;
-       res->unw_info = buf;
 }
 
 /*