X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Funwind.c;h=72f5d0d59e0b959373fcb1cb00dee5b86b4b601d;hb=ef8bc5028eb3330c102d3ef00bbb989f68207808;hp=6d60f79e7701cc5b697f276356f68f68c0fde65c;hpb=f367b437babbeb0ab45651e3fff7a4f80d7ee756;p=mono.git diff --git a/mono/mini/unwind.c b/mono/mini/unwind.c index 6d60f79e770..72f5d0d59e0 100644 --- a/mono/mini/unwind.c +++ b/mono/mini/unwind.c @@ -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); @@ -449,6 +450,13 @@ mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enab g_assert (op->val == 0); *p ++ = op->op; break; +#if defined(TARGET_WIN32) && defined(TARGET_AMD64) + case DW_CFA_mono_sp_alloc_info_win64: + case DW_CFA_mono_fp_alloc_info_win64: + // Drop Windows specific unwind op's. These op's are currently + // only used when registering unwind info with Windows OS unwinder. + break; +#endif default: g_assert_not_reached (); break; @@ -859,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; @@ -897,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; @@ -922,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; } } } @@ -1065,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); } } @@ -1108,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; @@ -1144,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 */ @@ -1175,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; } /*