2 * unwind.c: Stack Unwinding Interface
5 * Zoltan Varga (vargaz@gmail.com)
7 * (C) 2008 Novell, Inc.
11 #include "mini-unwind.h"
13 #include <mono/utils/mono-counters.h>
14 #include <mono/utils/freebsd-dwarf.h>
15 #include <mono/utils/hazard-pointer.h>
16 #include <mono/metadata/threads-types.h>
17 #include <mono/metadata/mono-endian.h>
31 guint8 info [MONO_ZERO_LEN_ARRAY];
34 #define ALIGN_TO(val,align) ((((size_t)val) + ((align) - 1)) & ~((align) - 1))
36 static mono_mutex_t unwind_mutex;
38 static MonoUnwindInfo **cached_info;
39 static int cached_info_next, cached_info_size;
40 static GSList *cached_info_list;
42 static int unwind_info_size;
44 #define unwind_lock() mono_os_mutex_lock (&unwind_mutex)
45 #define unwind_unlock() mono_os_mutex_unlock (&unwind_mutex)
48 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 };
49 #define NUM_DWARF_REGS AMD64_NREG
50 #define DWARF_DATA_ALIGN (-8)
51 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (AMD64_RIP))
52 #elif defined(TARGET_ARM)
53 // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040a/IHI0040A_aadwarf.pdf
54 /* Assign d8..d15 to hregs 16..24 (dwarf regs 264..271) */
55 static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 264, 265, 266, 267, 268, 269, 270, 271 };
56 #define NUM_DWARF_REGS 272
57 #define DWARF_DATA_ALIGN (-4)
58 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (ARMREG_LR))
59 #define IS_DOUBLE_REG(dwarf_reg) (((dwarf_reg) >= 264) && ((dwarf_reg) <= 271))
60 #elif defined(TARGET_ARM64)
61 #define NUM_DWARF_REGS 96
62 #define DWARF_DATA_ALIGN (-8)
64 #define DWARF_PC_REG 30
65 static int map_hw_reg_to_dwarf_reg [] = {
66 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
67 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
69 72, 73, 74, 75, 76, 77, 78, 79,
71 #elif defined (TARGET_X86)
73 * ebp and esp are swapped:
74 * http://lists.cs.uiuc.edu/pipermail/lldb-dev/2014-January/003101.html
76 static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 5, 4, 6, 7, 8 };
78 #define NUM_DWARF_REGS (X86_NREG + 1)
79 #define DWARF_DATA_ALIGN (-4)
80 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (X86_NREG))
81 #elif defined (TARGET_POWERPC)
82 // http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
83 static int map_hw_reg_to_dwarf_reg [ppc_lr + 1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,
84 9, 10, 11, 12, 13, 14, 15, 16,
85 17, 18, 19, 20, 21, 22, 23, 24,
86 25, 26, 27, 28, 29, 30, 31 };
87 #define DWARF_DATA_ALIGN (-(gint32)sizeof (mgreg_t))
89 #define DWARF_PC_REG 65
91 #define DWARF_PC_REG 108
93 #define NUM_DWARF_REGS (DWARF_PC_REG + 1)
94 #elif defined (TARGET_S390X)
95 static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
96 #define NUM_DWARF_REGS 16
97 #define DWARF_DATA_ALIGN (-8)
98 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (14))
99 #elif defined (TARGET_MIPS)
101 static int map_hw_reg_to_dwarf_reg [32] = {
102 0, 1, 2, 3, 4, 5, 6, 7,
103 8, 9, 10, 11, 12, 13, 14, 15,
104 16, 17, 18, 19, 20, 21, 22, 23,
105 24, 25, 26, 27, 28, 29, 30, 31
107 #define NUM_DWARF_REGS 32
108 #define DWARF_DATA_ALIGN (-(gint32)sizeof (mgreg_t))
109 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (mips_ra))
111 static int map_hw_reg_to_dwarf_reg [16];
112 #define NUM_DWARF_REGS 16
113 #define DWARF_DATA_ALIGN 0
114 #define DWARF_PC_REG -1
117 #define NUM_HW_REGS (sizeof (map_hw_reg_to_dwarf_reg) / sizeof (int))
119 #ifndef IS_DOUBLE_REG
120 #define IS_DOUBLE_REG(dwarf_reg) (dwarf_reg ? 0 : 0)
123 static gboolean dwarf_reg_to_hw_reg_inited;
124 static gboolean hw_reg_to_dwarf_reg_inited;
126 static int map_dwarf_reg_to_hw_reg [NUM_DWARF_REGS];
129 init_hw_reg_map (void)
131 #ifdef TARGET_POWERPC
132 map_hw_reg_to_dwarf_reg [ppc_lr] = DWARF_PC_REG;
134 mono_memory_barrier ();
135 hw_reg_to_dwarf_reg_inited = TRUE;
139 * mono_hw_reg_to_dwarf_reg:
141 * Map the hardware register number REG to the register number used by DWARF.
144 mono_hw_reg_to_dwarf_reg (int reg)
146 if (!hw_reg_to_dwarf_reg_inited)
149 if (NUM_HW_REGS == 0) {
150 g_assert_not_reached ();
153 return map_hw_reg_to_dwarf_reg [reg];
158 init_dwarf_reg_map (void)
162 g_assert (NUM_HW_REGS > 0);
163 for (i = 0; i < NUM_HW_REGS; ++i) {
164 map_dwarf_reg_to_hw_reg [mono_hw_reg_to_dwarf_reg (i)] = i;
167 mono_memory_barrier ();
168 dwarf_reg_to_hw_reg_inited = TRUE;
172 mono_dwarf_reg_to_hw_reg (int reg)
174 if (!dwarf_reg_to_hw_reg_inited)
175 init_dwarf_reg_map ();
177 return map_dwarf_reg_to_hw_reg [reg];
180 static G_GNUC_UNUSED void
181 encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
186 guint8 b = value & 0x7f;
188 if (value != 0) /* more bytes to come */
196 static G_GNUC_UNUSED void
197 encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
200 gboolean negative = (value < 0);
208 /* the following is unnecessary if the
209 * implementation of >>= uses an arithmetic rather
210 * than logical shift for a signed left operand
214 value |= - (1 <<(size - 7));
215 /* sign bit of byte is second high order bit (0x40) */
216 if ((value == 0 && !(byte & 0x40)) ||
217 (value == -1 && (byte & 0x40)))
227 static inline guint32
228 decode_uleb128 (guint8 *buf, guint8 **endbuf)
238 res = res | (((int)(b & 0x7f)) << shift);
250 decode_sleb128 (guint8 *buf, guint8 **endbuf)
260 res = res | (((int)(b & 0x7f)) << shift);
263 if (shift < 32 && (b & 0x40))
264 res |= - (1 << shift);
275 mono_print_unwind_info (guint8 *unwind_info, int unwind_info_len)
278 int pos, reg, offset, cfa_reg, cfa_offset;
282 while (p < unwind_info + unwind_info_len) {
286 case DW_CFA_advance_loc:
293 offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
294 if (reg == DWARF_PC_REG)
295 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, "pc", -offset);
297 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
304 cfa_reg = decode_uleb128 (p, &p);
305 cfa_offset = decode_uleb128 (p, &p);
306 printf ("CFA: [%x] def_cfa: %s+0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)), cfa_offset);
308 case DW_CFA_def_cfa_offset:
309 cfa_offset = decode_uleb128 (p, &p);
310 printf ("CFA: [%x] def_cfa_offset: 0x%x\n", pos, cfa_offset);
312 case DW_CFA_def_cfa_register:
313 cfa_reg = decode_uleb128 (p, &p);
314 printf ("CFA: [%x] def_cfa_reg: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)));
316 case DW_CFA_offset_extended_sf:
317 reg = decode_uleb128 (p, &p);
318 offset = decode_sleb128 (p, &p) * DWARF_DATA_ALIGN;
319 printf ("CFA: [%x] offset_extended_sf: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
321 case DW_CFA_same_value:
322 reg = decode_uleb128 (p, &p);
323 printf ("CFA: [%x] same_value: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)));
325 case DW_CFA_advance_loc4:
329 case DW_CFA_remember_state:
330 printf ("CFA: [%x] remember_state\n", pos);
332 case DW_CFA_restore_state:
333 printf ("CFA: [%x] restore_state\n", pos);
335 case DW_CFA_mono_advance_loc:
336 printf ("CFA: [%x] mono_advance_loc\n", pos);
339 g_assert_not_reached ();
344 g_assert_not_reached ();
350 * mono_unwind_ops_encode_full:
352 * Encode the unwind ops in UNWIND_OPS into the compact DWARF encoding.
353 * Return a pointer to malloc'ed memory.
354 * If ENABLE_EXTENSIONS is FALSE, avoid encoding the mono extension
355 * opcode (DW_CFA_mono_advance_loc).
358 mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enable_extensions)
370 for (; l; l = l->next) {
373 op = (MonoUnwindOp *)l->data;
375 /* Convert the register from the hw encoding to the dwarf encoding */
376 reg = mono_hw_reg_to_dwarf_reg (op->reg);
378 if (op->op == DW_CFA_mono_advance_loc) {
379 /* This advances loc to its location */
383 /* Emit an advance_loc if neccesary */
384 while (op->when > loc) {
385 if (op->when - loc >= 65536) {
386 *p ++ = DW_CFA_advance_loc4;
387 guint32 v = (guint32)(op->when - loc);
389 g_assert (read32 (p) == (guint32)(op->when - loc));
392 } else if (op->when - loc >= 256) {
393 *p ++ = DW_CFA_advance_loc2;
394 guint16 v = (guint16)(op->when - loc);
396 g_assert (read16 (p) == (guint32)(op->when - loc));
399 } else if (op->when - loc >= 32) {
400 *p ++ = DW_CFA_advance_loc1;
401 *(guint8*)p = (guint8)(op->when - loc);
404 } else if (op->when - loc < 32) {
405 *p ++ = DW_CFA_advance_loc | (op->when - loc);
408 *p ++ = DW_CFA_advance_loc | (30);
416 encode_uleb128 (reg, p, &p);
417 encode_uleb128 (op->val, p, &p);
419 case DW_CFA_def_cfa_offset:
421 encode_uleb128 (op->val, p, &p);
423 case DW_CFA_def_cfa_register:
425 encode_uleb128 (reg, p, &p);
427 case DW_CFA_same_value:
429 encode_uleb128 (reg, p, &p);
433 *p ++ = DW_CFA_offset_extended_sf;
434 encode_uleb128 (reg, p, &p);
435 encode_sleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
437 *p ++ = DW_CFA_offset | reg;
438 encode_uleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
441 case DW_CFA_remember_state:
442 case DW_CFA_restore_state:
445 case DW_CFA_mono_advance_loc:
446 if (!enable_extensions)
448 /* Only one location is supported */
449 g_assert (op->val == 0);
453 g_assert_not_reached ();
458 g_assert (p - buf < 4096);
460 res = (guint8 *)g_malloc (p - buf);
461 memcpy (res, buf, p - buf);
466 mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
468 return mono_unwind_ops_encode_full (unwind_ops, out_len, TRUE);
472 #define UNW_DEBUG(stmt) do { stmt; } while (0)
474 #define UNW_DEBUG(stmt) do { } while (0)
477 static G_GNUC_UNUSED void
478 print_dwarf_state (int cfa_reg, int cfa_offset, int ip, int nregs, Loc *locations, guint8 *reg_saved)
482 printf ("\t%x: cfa=r%d+%d ", ip, cfa_reg, cfa_offset);
484 for (i = 0; i < nregs; ++i)
485 if (reg_saved [i] && locations [i].loc_type == LOC_OFFSET)
486 printf ("r%d@%d(cfa) ", i, locations [i].offset);
491 Loc locations [NUM_HW_REGS];
492 guint8 reg_saved [NUM_HW_REGS];
493 int cfa_reg, cfa_offset;
497 * Given the state of the current frame as stored in REGS, execute the unwind
498 * operations in unwind_info until the location counter reaches POS. The result is
499 * stored back into REGS. OUT_CFA will receive the value of the CFA.
500 * If SAVE_LOCATIONS is non-NULL, it should point to an array of size SAVE_LOCATIONS_LEN.
501 * On return, the nth entry will point to the address of the stack slot where register
502 * N was saved, or NULL, if it was not saved by this frame.
503 * MARK_LOCATIONS should contain the locations marked by mono_emit_unwind_op_mark_loc (), if any.
504 * This function is signal safe.
507 mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len,
508 guint8 *start_ip, guint8 *end_ip, guint8 *ip, guint8 **mark_locations,
509 mono_unwind_reg_t *regs, int nregs,
510 mgreg_t **save_locations, int save_locations_len,
513 Loc locations [NUM_HW_REGS];
514 guint8 reg_saved [NUM_HW_REGS];
515 int pos, reg, hwreg, cfa_reg = -1, cfa_offset = 0, offset;
518 UnwindState state_stack [1];
521 memset (reg_saved, 0, sizeof (reg_saved));
522 state_stack [0].cfa_reg = -1;
523 state_stack [0].cfa_offset = 0;
530 while (pos <= ip - start_ip && p < unwind_info + unwind_info_len) {
534 case DW_CFA_advance_loc:
535 UNW_DEBUG (print_dwarf_state (cfa_reg, cfa_offset, pos, nregs, locations));
540 hwreg = mono_dwarf_reg_to_hw_reg (*p & 0x3f);
542 reg_saved [hwreg] = TRUE;
543 locations [hwreg].loc_type = LOC_OFFSET;
544 locations [hwreg].offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
551 cfa_reg = decode_uleb128 (p, &p);
552 cfa_offset = decode_uleb128 (p, &p);
554 case DW_CFA_def_cfa_offset:
555 cfa_offset = decode_uleb128 (p, &p);
557 case DW_CFA_def_cfa_register:
558 cfa_reg = decode_uleb128 (p, &p);
560 case DW_CFA_offset_extended_sf:
561 reg = decode_uleb128 (p, &p);
562 hwreg = mono_dwarf_reg_to_hw_reg (reg);
563 offset = decode_sleb128 (p, &p);
564 g_assert (reg < NUM_DWARF_REGS);
565 reg_saved [hwreg] = TRUE;
566 locations [hwreg].loc_type = LOC_OFFSET;
567 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
569 case DW_CFA_offset_extended:
570 reg = decode_uleb128 (p, &p);
571 hwreg = mono_dwarf_reg_to_hw_reg (reg);
572 offset = decode_uleb128 (p, &p);
573 g_assert (reg < NUM_DWARF_REGS);
574 reg_saved [hwreg] = TRUE;
575 locations [hwreg].loc_type = LOC_OFFSET;
576 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
578 case DW_CFA_same_value:
579 hwreg = mono_dwarf_reg_to_hw_reg (decode_uleb128 (p, &p));
580 locations [hwreg].loc_type = LOC_SAME;
582 case DW_CFA_advance_loc1:
586 case DW_CFA_advance_loc2:
590 case DW_CFA_advance_loc4:
594 case DW_CFA_remember_state:
595 g_assert (state_stack_pos == 0);
596 memcpy (&state_stack [0].locations, &locations, sizeof (locations));
597 memcpy (&state_stack [0].reg_saved, ®_saved, sizeof (reg_saved));
598 state_stack [0].cfa_reg = cfa_reg;
599 state_stack [0].cfa_offset = cfa_offset;
602 case DW_CFA_restore_state:
603 g_assert (state_stack_pos == 1);
605 memcpy (&locations, &state_stack [0].locations, sizeof (locations));
606 memcpy (®_saved, &state_stack [0].reg_saved, sizeof (reg_saved));
607 cfa_reg = state_stack [0].cfa_reg;
608 cfa_offset = state_stack [0].cfa_offset;
610 case DW_CFA_mono_advance_loc:
611 g_assert (mark_locations [0]);
612 pos = mark_locations [0] - start_ip;
615 g_assert_not_reached ();
620 g_assert_not_reached ();
625 memset (save_locations, 0, save_locations_len * sizeof (mgreg_t*));
627 g_assert (cfa_reg != -1);
628 cfa_val = (guint8*)regs [mono_dwarf_reg_to_hw_reg (cfa_reg)] + cfa_offset;
629 for (hwreg = 0; hwreg < NUM_HW_REGS; ++hwreg) {
630 if (reg_saved [hwreg] && locations [hwreg].loc_type == LOC_OFFSET) {
631 int dwarfreg = mono_hw_reg_to_dwarf_reg (hwreg);
632 g_assert (hwreg < nregs);
633 if (IS_DOUBLE_REG (dwarfreg))
634 regs [hwreg] = *(guint64*)(cfa_val + locations [hwreg].offset);
636 regs [hwreg] = *(mgreg_t*)(cfa_val + locations [hwreg].offset);
637 if (save_locations && hwreg < save_locations_len)
638 save_locations [hwreg] = (mgreg_t*)(cfa_val + locations [hwreg].offset);
646 mono_unwind_init (void)
648 mono_os_mutex_init_recursive (&unwind_mutex);
650 mono_counters_register ("Unwind info size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &unwind_info_size);
654 mono_unwind_cleanup (void)
658 mono_os_mutex_destroy (&unwind_mutex);
663 for (i = 0; i < cached_info_next; ++i) {
664 MonoUnwindInfo *cached = cached_info [i];
668 g_free (cached_info);
670 for (GSList *cursor = cached_info_list; cursor != NULL; cursor = cursor->next)
671 g_free (cursor->data);
673 g_slist_free (cached_info_list);
677 * mono_cache_unwind_info
679 * Save UNWIND_INFO in the unwind info cache and return an id which can be passed
680 * to mono_get_cached_unwind_info to get a cached copy of the info.
681 * A copy is made of the unwind info.
682 * This function is useful for two reasons:
683 * - many methods have the same unwind info
684 * - MonoJitInfo->unwind_info is an int so it can't store the pointer to the unwind info
687 mono_cache_unwind_info (guint8 *unwind_info, guint32 unwind_info_len)
690 MonoUnwindInfo *info;
694 if (cached_info == NULL) {
695 cached_info_size = 16;
696 cached_info = g_new0 (MonoUnwindInfo*, cached_info_size);
699 for (i = 0; i < cached_info_next; ++i) {
700 MonoUnwindInfo *cached = cached_info [i];
702 if (cached->len == unwind_info_len && memcmp (cached->info, unwind_info, unwind_info_len) == 0) {
708 info = (MonoUnwindInfo *)g_malloc (sizeof (MonoUnwindInfo) + unwind_info_len);
709 info->len = unwind_info_len;
710 memcpy (&info->info, unwind_info, unwind_info_len);
712 i = cached_info_next;
714 if (cached_info_next >= cached_info_size) {
715 MonoUnwindInfo **new_table;
718 * Avoid freeing the old table so mono_get_cached_unwind_info ()
719 * doesn't need locks/hazard pointers.
722 new_table = g_new0 (MonoUnwindInfo*, cached_info_size * 2);
724 memcpy (new_table, cached_info, cached_info_size * sizeof (MonoUnwindInfo*));
726 mono_memory_barrier ();
728 cached_info_list = g_slist_prepend (cached_info_list, cached_info);
730 cached_info = new_table;
732 cached_info_size *= 2;
735 cached_info [cached_info_next ++] = info;
737 unwind_info_size += sizeof (MonoUnwindInfo) + unwind_info_len;
744 * This function is signal safe.
747 mono_get_cached_unwind_info (guint32 index, guint32 *unwind_info_len)
749 MonoUnwindInfo **table;
750 MonoUnwindInfo *info;
754 * This doesn't need any locks/hazard pointers,
755 * since new tables are copies of the old ones.
759 info = table [index];
761 *unwind_info_len = info->len;
768 * mono_unwind_get_dwarf_data_align:
770 * Return the data alignment used by the encoded unwind information.
773 mono_unwind_get_dwarf_data_align (void)
775 return DWARF_DATA_ALIGN;
779 * mono_unwind_get_dwarf_pc_reg:
781 * Return the dwarf register number of the register holding the ip of the
785 mono_unwind_get_dwarf_pc_reg (void)
791 decode_cie_op (guint8 *p, guint8 **endp)
796 case DW_CFA_advance_loc:
801 decode_uleb128 (p, &p);
808 decode_uleb128 (p, &p);
809 decode_uleb128 (p, &p);
811 case DW_CFA_def_cfa_offset:
812 decode_uleb128 (p, &p);
814 case DW_CFA_def_cfa_register:
815 decode_uleb128 (p, &p);
817 case DW_CFA_advance_loc4:
820 case DW_CFA_offset_extended_sf:
821 decode_uleb128 (p, &p);
822 decode_uleb128 (p, &p);
825 g_assert_not_reached ();
830 g_assert_not_reached ();
837 read_encoded_val (guint32 encoding, guint8 *p, guint8 **endp)
841 switch (encoding & 0xf) {
842 case DW_EH_PE_sdata8:
846 case DW_EH_PE_sdata4:
851 g_assert_not_reached ();
861 * Decode the Mono specific Language Specific Data Area generated by LLVM.
864 decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo **ex_info, guint32 *ex_info_len, gpointer **type_info, int *this_reg, int *this_offset)
867 int i, ncall_sites, this_encoding;
868 guint32 mono_magic, version;
872 /* This is the modified LSDA generated by the LLVM mono branch */
873 mono_magic = decode_uleb128 (p, &p);
874 g_assert (mono_magic == 0x4d4fef4f);
875 version = decode_uleb128 (p, &p);
876 g_assert (version == 1);
879 if (this_encoding == DW_EH_PE_udata4) {
880 gint32 op, reg, offset;
882 /* 'this' location */
884 g_assert (op == DW_OP_bregx);
886 reg = decode_uleb128 (p, &p);
887 offset = decode_sleb128 (p, &p);
889 *this_reg = mono_dwarf_reg_to_hw_reg (reg);
890 *this_offset = offset;
892 g_assert (this_encoding == DW_EH_PE_omit);
897 ncall_sites = decode_uleb128 (p, &p);
898 p = (guint8*)ALIGN_TO ((mgreg_t)p, 4);
901 *ex_info = (MonoJitExceptionInfo *)g_malloc0 (ncall_sites * sizeof (MonoJitExceptionInfo));
902 *ex_info_len = ncall_sites;
905 *type_info = (gpointer *)g_malloc0 (ncall_sites * sizeof (gpointer));
907 for (i = 0; i < ncall_sites; ++i) {
908 int block_start_offset, block_size, landing_pad;
911 block_start_offset = read32 (p);
912 p += sizeof (gint32);
913 block_size = read32 (p);
914 p += sizeof (gint32);
915 landing_pad = read32 (p);
916 p += sizeof (gint32);
918 p += sizeof (gint32);
920 g_assert (landing_pad);
921 g_assert (((size_t)tinfo % 4) == 0);
922 //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
926 (*type_info) [i] = tinfo;
927 (*ex_info)[i].try_start = code + block_start_offset;
928 (*ex_info)[i].try_end = code + block_start_offset + block_size;
929 (*ex_info)[i].handler_start = code + landing_pad;
935 * mono_unwind_decode_fde:
937 * Decode a DWARF FDE entry, returning the unwind opcodes.
938 * If not NULL, EX_INFO is set to a malloc-ed array of MonoJitExceptionInfo structures,
939 * only try_start, try_end and handler_start is set.
940 * If not NULL, TYPE_INFO is set to a malloc-ed array containing the ttype table from the
944 mono_unwind_decode_fde (guint8 *fde, guint32 *out_len, guint32 *code_len, MonoJitExceptionInfo **ex_info, guint32 *ex_info_len, gpointer **type_info, int *this_reg, int *this_offset)
946 guint8 *p, *cie, *fde_current, *fde_aug = NULL, *code, *fde_cfi, *cie_cfi;
947 gint32 fde_len, cie_offset, pc_begin, pc_range, aug_len;
948 gint32 cie_len, cie_id, cie_version, code_align, data_align, return_reg;
949 gint32 i, cie_aug_len, buf_len;
952 gboolean has_fde_augmentation = FALSE;
955 * http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
958 /* This is generated by JITDwarfEmitter::EmitEHFrame () */
967 // FIXME: Endianess ?
968 fde_len = *(guint32*)p;
969 g_assert (fde_len != 0xffffffff && fde_len != 0);
971 cie_offset = *(guint32*)p;
972 cie = p - cie_offset;
978 cie_len = *(guint32*)p;
980 cie_id = *(guint32*)p;
981 g_assert (cie_id == 0);
984 g_assert (cie_version == 1);
986 cie_aug_str = (char*)p;
987 p += strlen (cie_aug_str) + 1;
988 code_align = decode_uleb128 (p, &p);
989 data_align = decode_sleb128 (p, &p);
990 return_reg = decode_uleb128 (p, &p);
991 if (strstr (cie_aug_str, "z")) {
995 cie_aug_len = decode_uleb128 (p, &p);
997 has_fde_augmentation = TRUE;
1000 for (i = 0; cie_aug_str [i] != '\0'; ++i) {
1001 switch (cie_aug_str [i]) {
1007 read_encoded_val (p_encoding, p, &p);
1010 g_assert ((*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel)) || (*p == (DW_EH_PE_sdata8|DW_EH_PE_pcrel)));
1014 g_assert (*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel));
1018 g_assert_not_reached ();
1028 /* Continue decoding FDE */
1030 /* DW_EH_PE_sdata4|DW_EH_PE_pcrel encoding */
1031 pc_begin = *(gint32*)p;
1032 code = p + pc_begin;
1034 pc_range = *(guint32*)p;
1036 if (has_fde_augmentation) {
1037 aug_len = decode_uleb128 (p, &p);
1046 *code_len = pc_range;
1053 /* Decode FDE augmention */
1058 /* sdata|pcrel encoding */
1060 lsda_offset = read32 (fde_aug);
1061 else if (aug_len == 8)
1062 lsda_offset = *(gint64*)fde_aug;
1064 g_assert_not_reached ();
1065 if (lsda_offset != 0) {
1066 lsda = fde_aug + lsda_offset;
1068 decode_lsda (lsda, code, ex_info, ex_info_len, type_info, this_reg, this_offset);
1072 /* Make sure the FDE uses the same constants as we do */
1073 g_assert (code_align == 1);
1074 g_assert (data_align == DWARF_DATA_ALIGN);
1075 g_assert (return_reg == DWARF_PC_REG);
1077 buf_len = (cie + cie_len + 4 - cie_cfi) + (fde + fde_len + 4 - fde_cfi);
1078 buf = (guint8 *)g_malloc0 (buf_len);
1082 while (p < cie + cie_len + 4) {
1083 if (*p == DW_CFA_nop)
1086 decode_cie_op (p, &p);
1088 memcpy (buf + i, cie_cfi, p - cie_cfi);
1092 while (p < fde + fde_len + 4) {
1093 if (*p == DW_CFA_nop)
1096 decode_cie_op (p, &p);
1098 memcpy (buf + i, fde_cfi, p - fde_cfi);
1100 g_assert (i <= buf_len);
1104 return (guint8 *)g_realloc (buf, i);
1108 * mono_unwind_decode_mono_fde:
1110 * Decode an FDE entry in the LLVM emitted mono EH frame.
1111 * info->ex_info is set to a malloc-ed array of MonoJitExceptionInfo structures,
1112 * only try_start, try_end and handler_start is set.
1113 * info->type_info is set to a malloc-ed array containing the ttype table from the
1117 mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8 *code, MonoLLVMFDEInfo *res)
1119 guint8 *p, *fde_aug, *cie_cfi, *fde_cfi, *buf;
1120 int has_aug, aug_len, cie_cfi_len, fde_cfi_len;
1121 gint32 code_align, data_align, return_reg, pers_encoding;
1123 memset (res, 0, sizeof (*res));
1125 res->this_offset = -1;
1127 /* fde points to data emitted by LLVM in DwarfMonoException::EmitMonoEHFrame () */
1132 aug_len = read32 (p);
1144 /* The LSDA is embedded directly into the FDE */
1147 decode_lsda (lsda, code, &res->ex_info, &res->ex_info_len, &res->type_info, &res->this_reg, &res->this_offset);
1152 code_align = decode_uleb128 (p, &p);
1153 data_align = decode_sleb128 (p, &p);
1154 return_reg = decode_uleb128 (p, &p);
1157 if (pers_encoding != DW_EH_PE_omit)
1158 read_encoded_val (pers_encoding, p, &p);
1162 /* Make sure the FDE uses the same constants as we do */
1163 g_assert (code_align == 1);
1164 g_assert (data_align == DWARF_DATA_ALIGN);
1165 g_assert (return_reg == DWARF_PC_REG);
1167 /* Compute size of CIE unwind info it is DW_CFA_nop terminated */
1170 if (*p == DW_CFA_nop)
1173 decode_cie_op (p, &p);
1175 cie_cfi_len = p - cie_cfi;
1176 fde_cfi_len = (fde + fde_len - fde_cfi);
1178 buf = (guint8 *)g_malloc0 (cie_cfi_len + fde_cfi_len);
1179 memcpy (buf, cie_cfi, cie_cfi_len);
1180 memcpy (buf + cie_cfi_len, fde_cfi, fde_cfi_len);
1182 res->unw_info_len = cie_cfi_len + fde_cfi_len;
1183 res->unw_info = buf;
1187 * mono_unwind_get_cie_program:
1189 * Get the unwind bytecode for the DWARF CIE.
1192 mono_unwind_get_cie_program (void)
1194 #if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_POWERPC) || defined(TARGET_ARM)
1195 return mono_arch_get_cie_program ();