3 * Stack Unwinding Interface
6 * Zoltan Varga (vargaz@gmail.com)
8 * (C) 2008 Novell, Inc.
12 #include "mini-unwind.h"
14 #include <mono/utils/mono-counters.h>
15 #include <mono/utils/freebsd-dwarf.h>
16 #include <mono/utils/hazard-pointer.h>
17 #include <mono/metadata/threads-types.h>
18 #include <mono/metadata/mono-endian.h>
32 guint8 info [MONO_ZERO_LEN_ARRAY];
35 #define ALIGN_TO(val,align) ((((size_t)val) + ((align) - 1)) & ~((align) - 1))
37 static mono_mutex_t unwind_mutex;
39 static MonoUnwindInfo **cached_info;
40 static int cached_info_next, cached_info_size;
41 static GSList *cached_info_list;
43 static int unwind_info_size;
45 #define unwind_lock() mono_os_mutex_lock (&unwind_mutex)
46 #define unwind_unlock() mono_os_mutex_unlock (&unwind_mutex)
49 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 };
50 #define NUM_DWARF_REGS AMD64_NREG
51 #define DWARF_DATA_ALIGN (-8)
52 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (AMD64_RIP))
53 #elif defined(TARGET_ARM)
54 // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040a/IHI0040A_aadwarf.pdf
55 /* Assign d8..d15 to hregs 16..24 (dwarf regs 264..271) */
56 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 };
57 #define NUM_DWARF_REGS 272
58 #define DWARF_DATA_ALIGN (-4)
59 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (ARMREG_LR))
60 #define IS_DOUBLE_REG(dwarf_reg) (((dwarf_reg) >= 264) && ((dwarf_reg) <= 271))
61 #elif defined(TARGET_ARM64)
62 #define NUM_DWARF_REGS 96
63 #define DWARF_DATA_ALIGN (-8)
65 #define DWARF_PC_REG 30
66 static int map_hw_reg_to_dwarf_reg [] = {
67 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
68 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
70 72, 73, 74, 75, 76, 77, 78, 79,
72 #elif defined (TARGET_X86)
74 * ebp and esp are swapped:
75 * http://lists.cs.uiuc.edu/pipermail/lldb-dev/2014-January/003101.html
77 static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 5, 4, 6, 7, 8 };
79 #define NUM_DWARF_REGS (X86_NREG + 1)
80 #define DWARF_DATA_ALIGN (-4)
81 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (X86_NREG))
82 #elif defined (TARGET_POWERPC)
83 // http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
84 static int map_hw_reg_to_dwarf_reg [ppc_lr + 1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,
85 9, 10, 11, 12, 13, 14, 15, 16,
86 17, 18, 19, 20, 21, 22, 23, 24,
87 25, 26, 27, 28, 29, 30, 31 };
88 #define DWARF_DATA_ALIGN (-(gint32)sizeof (mgreg_t))
90 #define DWARF_PC_REG 65
92 #define DWARF_PC_REG 108
94 #define NUM_DWARF_REGS (DWARF_PC_REG + 1)
95 #elif defined (TARGET_S390X)
96 static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
97 #define NUM_DWARF_REGS 16
98 #define DWARF_DATA_ALIGN (-8)
99 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (14))
100 #elif defined (TARGET_MIPS)
102 static int map_hw_reg_to_dwarf_reg [32] = {
103 0, 1, 2, 3, 4, 5, 6, 7,
104 8, 9, 10, 11, 12, 13, 14, 15,
105 16, 17, 18, 19, 20, 21, 22, 23,
106 24, 25, 26, 27, 28, 29, 30, 31
108 #define NUM_DWARF_REGS 32
109 #define DWARF_DATA_ALIGN (-(gint32)sizeof (mgreg_t))
110 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (mips_ra))
112 static int map_hw_reg_to_dwarf_reg [16];
113 #define NUM_DWARF_REGS 16
114 #define DWARF_DATA_ALIGN 0
115 #define DWARF_PC_REG -1
118 #define NUM_HW_REGS (sizeof (map_hw_reg_to_dwarf_reg) / sizeof (int))
120 #ifndef IS_DOUBLE_REG
121 #define IS_DOUBLE_REG(dwarf_reg) (dwarf_reg ? 0 : 0)
124 static gboolean dwarf_reg_to_hw_reg_inited;
125 static gboolean hw_reg_to_dwarf_reg_inited;
127 static int map_dwarf_reg_to_hw_reg [NUM_DWARF_REGS];
130 init_hw_reg_map (void)
132 #ifdef TARGET_POWERPC
133 map_hw_reg_to_dwarf_reg [ppc_lr] = DWARF_PC_REG;
135 mono_memory_barrier ();
136 hw_reg_to_dwarf_reg_inited = TRUE;
140 * mono_hw_reg_to_dwarf_reg:
142 * Map the hardware register number REG to the register number used by DWARF.
145 mono_hw_reg_to_dwarf_reg (int reg)
147 if (!hw_reg_to_dwarf_reg_inited)
150 if (NUM_HW_REGS == 0) {
151 g_assert_not_reached ();
154 return map_hw_reg_to_dwarf_reg [reg];
159 init_dwarf_reg_map (void)
163 g_assert (NUM_HW_REGS > 0);
164 for (i = 0; i < NUM_HW_REGS; ++i) {
165 map_dwarf_reg_to_hw_reg [mono_hw_reg_to_dwarf_reg (i)] = i;
168 mono_memory_barrier ();
169 dwarf_reg_to_hw_reg_inited = TRUE;
173 mono_dwarf_reg_to_hw_reg (int reg)
175 if (!dwarf_reg_to_hw_reg_inited)
176 init_dwarf_reg_map ();
178 return map_dwarf_reg_to_hw_reg [reg];
181 static G_GNUC_UNUSED void
182 encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
187 guint8 b = value & 0x7f;
189 if (value != 0) /* more bytes to come */
197 static G_GNUC_UNUSED void
198 encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
201 gboolean negative = (value < 0);
209 /* the following is unnecessary if the
210 * implementation of >>= uses an arithmetic rather
211 * than logical shift for a signed left operand
215 value |= - (1 <<(size - 7));
216 /* sign bit of byte is second high order bit (0x40) */
217 if ((value == 0 && !(byte & 0x40)) ||
218 (value == -1 && (byte & 0x40)))
228 static inline guint32
229 decode_uleb128 (guint8 *buf, guint8 **endbuf)
239 res = res | (((int)(b & 0x7f)) << shift);
251 decode_sleb128 (guint8 *buf, guint8 **endbuf)
261 res = res | (((int)(b & 0x7f)) << shift);
264 if (shift < 32 && (b & 0x40))
265 res |= - (1 << shift);
276 mono_print_unwind_info (guint8 *unwind_info, int unwind_info_len)
279 int pos, reg, offset, cfa_reg, cfa_offset;
283 while (p < unwind_info + unwind_info_len) {
287 case DW_CFA_advance_loc:
294 offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
295 if (reg == DWARF_PC_REG)
296 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, "pc", -offset);
298 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
305 cfa_reg = decode_uleb128 (p, &p);
306 cfa_offset = decode_uleb128 (p, &p);
307 printf ("CFA: [%x] def_cfa: %s+0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)), cfa_offset);
309 case DW_CFA_def_cfa_offset:
310 cfa_offset = decode_uleb128 (p, &p);
311 printf ("CFA: [%x] def_cfa_offset: 0x%x\n", pos, cfa_offset);
313 case DW_CFA_def_cfa_register:
314 cfa_reg = decode_uleb128 (p, &p);
315 printf ("CFA: [%x] def_cfa_reg: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)));
317 case DW_CFA_offset_extended_sf:
318 reg = decode_uleb128 (p, &p);
319 offset = decode_sleb128 (p, &p) * DWARF_DATA_ALIGN;
320 printf ("CFA: [%x] offset_extended_sf: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
322 case DW_CFA_same_value:
323 reg = decode_uleb128 (p, &p);
324 printf ("CFA: [%x] same_value: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)));
326 case DW_CFA_advance_loc4:
330 case DW_CFA_remember_state:
331 printf ("CFA: [%x] remember_state\n", pos);
333 case DW_CFA_restore_state:
334 printf ("CFA: [%x] restore_state\n", pos);
336 case DW_CFA_mono_advance_loc:
337 printf ("CFA: [%x] mono_advance_loc\n", pos);
340 g_assert_not_reached ();
345 g_assert_not_reached ();
351 * mono_unwind_ops_encode_full:
353 * Encode the unwind ops in UNWIND_OPS into the compact DWARF encoding.
354 * Return a pointer to malloc'ed memory.
355 * If ENABLE_EXTENSIONS is FALSE, avoid encoding the mono extension
356 * opcode (DW_CFA_mono_advance_loc).
359 mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enable_extensions)
371 for (; l; l = l->next) {
374 op = (MonoUnwindOp *)l->data;
376 /* Convert the register from the hw encoding to the dwarf encoding */
377 reg = mono_hw_reg_to_dwarf_reg (op->reg);
379 if (op->op == DW_CFA_mono_advance_loc) {
380 /* This advances loc to its location */
384 /* Emit an advance_loc if neccesary */
385 while (op->when > loc) {
386 if (op->when - loc >= 65536) {
387 *p ++ = DW_CFA_advance_loc4;
388 guint32 v = (guint32)(op->when - loc);
390 g_assert (read32 (p) == (guint32)(op->when - loc));
393 } else if (op->when - loc >= 256) {
394 *p ++ = DW_CFA_advance_loc2;
395 guint16 v = (guint16)(op->when - loc);
397 g_assert (read16 (p) == (guint32)(op->when - loc));
400 } else if (op->when - loc >= 32) {
401 *p ++ = DW_CFA_advance_loc1;
402 *(guint8*)p = (guint8)(op->when - loc);
405 } else if (op->when - loc < 32) {
406 *p ++ = DW_CFA_advance_loc | (op->when - loc);
409 *p ++ = DW_CFA_advance_loc | (30);
417 encode_uleb128 (reg, p, &p);
418 encode_uleb128 (op->val, p, &p);
420 case DW_CFA_def_cfa_offset:
422 encode_uleb128 (op->val, p, &p);
424 case DW_CFA_def_cfa_register:
426 encode_uleb128 (reg, p, &p);
428 case DW_CFA_same_value:
430 encode_uleb128 (reg, p, &p);
434 *p ++ = DW_CFA_offset_extended_sf;
435 encode_uleb128 (reg, p, &p);
436 encode_sleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
438 *p ++ = DW_CFA_offset | reg;
439 encode_uleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
442 case DW_CFA_remember_state:
443 case DW_CFA_restore_state:
446 case DW_CFA_mono_advance_loc:
447 if (!enable_extensions)
449 /* Only one location is supported */
450 g_assert (op->val == 0);
453 #if defined(TARGET_WIN32) && defined(TARGET_AMD64)
454 case DW_CFA_mono_sp_alloc_info_win64:
455 case DW_CFA_mono_fp_alloc_info_win64:
456 // Drop Windows specific unwind op's. These op's are currently
457 // only used when registering unwind info with Windows OS unwinder.
461 g_assert_not_reached ();
466 g_assert (p - buf < 4096);
468 res = (guint8 *)g_malloc (p - buf);
469 memcpy (res, buf, p - buf);
474 mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
476 return mono_unwind_ops_encode_full (unwind_ops, out_len, TRUE);
480 #define UNW_DEBUG(stmt) do { stmt; } while (0)
482 #define UNW_DEBUG(stmt) do { } while (0)
485 static G_GNUC_UNUSED void
486 print_dwarf_state (int cfa_reg, int cfa_offset, int ip, int nregs, Loc *locations, guint8 *reg_saved)
490 printf ("\t%x: cfa=r%d+%d ", ip, cfa_reg, cfa_offset);
492 for (i = 0; i < nregs; ++i)
493 if (reg_saved [i] && locations [i].loc_type == LOC_OFFSET)
494 printf ("r%d@%d(cfa) ", i, locations [i].offset);
499 Loc locations [NUM_HW_REGS];
500 guint8 reg_saved [NUM_HW_REGS];
501 int cfa_reg, cfa_offset;
505 * Given the state of the current frame as stored in REGS, execute the unwind
506 * operations in unwind_info until the location counter reaches POS. The result is
507 * stored back into REGS. OUT_CFA will receive the value of the CFA.
508 * If SAVE_LOCATIONS is non-NULL, it should point to an array of size SAVE_LOCATIONS_LEN.
509 * On return, the nth entry will point to the address of the stack slot where register
510 * N was saved, or NULL, if it was not saved by this frame.
511 * MARK_LOCATIONS should contain the locations marked by mono_emit_unwind_op_mark_loc (), if any.
512 * This function is signal safe.
515 mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len,
516 guint8 *start_ip, guint8 *end_ip, guint8 *ip, guint8 **mark_locations,
517 mono_unwind_reg_t *regs, int nregs,
518 mgreg_t **save_locations, int save_locations_len,
521 Loc locations [NUM_HW_REGS];
522 guint8 reg_saved [NUM_HW_REGS];
523 int pos, reg, hwreg, cfa_reg = -1, cfa_offset = 0, offset;
526 UnwindState state_stack [1];
529 memset (reg_saved, 0, sizeof (reg_saved));
530 state_stack [0].cfa_reg = -1;
531 state_stack [0].cfa_offset = 0;
538 while (pos <= ip - start_ip && p < unwind_info + unwind_info_len) {
542 case DW_CFA_advance_loc:
543 UNW_DEBUG (print_dwarf_state (cfa_reg, cfa_offset, pos, nregs, locations));
548 hwreg = mono_dwarf_reg_to_hw_reg (*p & 0x3f);
550 reg_saved [hwreg] = TRUE;
551 locations [hwreg].loc_type = LOC_OFFSET;
552 locations [hwreg].offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
559 cfa_reg = decode_uleb128 (p, &p);
560 cfa_offset = decode_uleb128 (p, &p);
562 case DW_CFA_def_cfa_offset:
563 cfa_offset = decode_uleb128 (p, &p);
565 case DW_CFA_def_cfa_register:
566 cfa_reg = decode_uleb128 (p, &p);
568 case DW_CFA_offset_extended_sf:
569 reg = decode_uleb128 (p, &p);
570 hwreg = mono_dwarf_reg_to_hw_reg (reg);
571 offset = decode_sleb128 (p, &p);
572 g_assert (reg < NUM_DWARF_REGS);
573 reg_saved [hwreg] = TRUE;
574 locations [hwreg].loc_type = LOC_OFFSET;
575 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
577 case DW_CFA_offset_extended:
578 reg = decode_uleb128 (p, &p);
579 hwreg = mono_dwarf_reg_to_hw_reg (reg);
580 offset = decode_uleb128 (p, &p);
581 g_assert (reg < NUM_DWARF_REGS);
582 reg_saved [hwreg] = TRUE;
583 locations [hwreg].loc_type = LOC_OFFSET;
584 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
586 case DW_CFA_same_value:
587 hwreg = mono_dwarf_reg_to_hw_reg (decode_uleb128 (p, &p));
588 locations [hwreg].loc_type = LOC_SAME;
590 case DW_CFA_advance_loc1:
594 case DW_CFA_advance_loc2:
598 case DW_CFA_advance_loc4:
602 case DW_CFA_remember_state:
603 g_assert (state_stack_pos == 0);
604 memcpy (&state_stack [0].locations, &locations, sizeof (locations));
605 memcpy (&state_stack [0].reg_saved, ®_saved, sizeof (reg_saved));
606 state_stack [0].cfa_reg = cfa_reg;
607 state_stack [0].cfa_offset = cfa_offset;
610 case DW_CFA_restore_state:
611 g_assert (state_stack_pos == 1);
613 memcpy (&locations, &state_stack [0].locations, sizeof (locations));
614 memcpy (®_saved, &state_stack [0].reg_saved, sizeof (reg_saved));
615 cfa_reg = state_stack [0].cfa_reg;
616 cfa_offset = state_stack [0].cfa_offset;
618 case DW_CFA_mono_advance_loc:
619 g_assert (mark_locations [0]);
620 pos = mark_locations [0] - start_ip;
623 g_assert_not_reached ();
628 g_assert_not_reached ();
633 memset (save_locations, 0, save_locations_len * sizeof (mgreg_t*));
635 g_assert (cfa_reg != -1);
636 cfa_val = (guint8*)regs [mono_dwarf_reg_to_hw_reg (cfa_reg)] + cfa_offset;
637 for (hwreg = 0; hwreg < NUM_HW_REGS; ++hwreg) {
638 if (reg_saved [hwreg] && locations [hwreg].loc_type == LOC_OFFSET) {
639 int dwarfreg = mono_hw_reg_to_dwarf_reg (hwreg);
640 g_assert (hwreg < nregs);
641 if (IS_DOUBLE_REG (dwarfreg))
642 regs [hwreg] = *(guint64*)(cfa_val + locations [hwreg].offset);
644 regs [hwreg] = *(mgreg_t*)(cfa_val + locations [hwreg].offset);
645 if (save_locations && hwreg < save_locations_len)
646 save_locations [hwreg] = (mgreg_t*)(cfa_val + locations [hwreg].offset);
654 mono_unwind_init (void)
656 mono_os_mutex_init_recursive (&unwind_mutex);
658 mono_counters_register ("Unwind info size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &unwind_info_size);
662 mono_unwind_cleanup (void)
666 mono_os_mutex_destroy (&unwind_mutex);
671 for (i = 0; i < cached_info_next; ++i) {
672 MonoUnwindInfo *cached = cached_info [i];
676 g_free (cached_info);
678 for (GSList *cursor = cached_info_list; cursor != NULL; cursor = cursor->next)
679 g_free (cursor->data);
681 g_slist_free (cached_info_list);
685 * mono_cache_unwind_info
687 * Save UNWIND_INFO in the unwind info cache and return an id which can be passed
688 * to mono_get_cached_unwind_info to get a cached copy of the info.
689 * A copy is made of the unwind info.
690 * This function is useful for two reasons:
691 * - many methods have the same unwind info
692 * - MonoJitInfo->unwind_info is an int so it can't store the pointer to the unwind info
695 mono_cache_unwind_info (guint8 *unwind_info, guint32 unwind_info_len)
698 MonoUnwindInfo *info;
702 if (cached_info == NULL) {
703 cached_info_size = 16;
704 cached_info = g_new0 (MonoUnwindInfo*, cached_info_size);
707 for (i = 0; i < cached_info_next; ++i) {
708 MonoUnwindInfo *cached = cached_info [i];
710 if (cached->len == unwind_info_len && memcmp (cached->info, unwind_info, unwind_info_len) == 0) {
716 info = (MonoUnwindInfo *)g_malloc (sizeof (MonoUnwindInfo) + unwind_info_len);
717 info->len = unwind_info_len;
718 memcpy (&info->info, unwind_info, unwind_info_len);
720 i = cached_info_next;
722 if (cached_info_next >= cached_info_size) {
723 MonoUnwindInfo **new_table;
726 * Avoid freeing the old table so mono_get_cached_unwind_info ()
727 * doesn't need locks/hazard pointers.
730 new_table = g_new0 (MonoUnwindInfo*, cached_info_size * 2);
732 memcpy (new_table, cached_info, cached_info_size * sizeof (MonoUnwindInfo*));
734 mono_memory_barrier ();
736 cached_info_list = g_slist_prepend (cached_info_list, cached_info);
738 cached_info = new_table;
740 cached_info_size *= 2;
743 cached_info [cached_info_next ++] = info;
745 unwind_info_size += sizeof (MonoUnwindInfo) + unwind_info_len;
752 * This function is signal safe.
755 mono_get_cached_unwind_info (guint32 index, guint32 *unwind_info_len)
757 MonoUnwindInfo **table;
758 MonoUnwindInfo *info;
762 * This doesn't need any locks/hazard pointers,
763 * since new tables are copies of the old ones.
767 info = table [index];
769 *unwind_info_len = info->len;
776 * mono_unwind_get_dwarf_data_align:
778 * Return the data alignment used by the encoded unwind information.
781 mono_unwind_get_dwarf_data_align (void)
783 return DWARF_DATA_ALIGN;
787 * mono_unwind_get_dwarf_pc_reg:
789 * Return the dwarf register number of the register holding the ip of the
793 mono_unwind_get_dwarf_pc_reg (void)
799 decode_cie_op (guint8 *p, guint8 **endp)
804 case DW_CFA_advance_loc:
809 decode_uleb128 (p, &p);
816 decode_uleb128 (p, &p);
817 decode_uleb128 (p, &p);
819 case DW_CFA_def_cfa_offset:
820 decode_uleb128 (p, &p);
822 case DW_CFA_def_cfa_register:
823 decode_uleb128 (p, &p);
825 case DW_CFA_advance_loc4:
828 case DW_CFA_offset_extended_sf:
829 decode_uleb128 (p, &p);
830 decode_uleb128 (p, &p);
833 g_assert_not_reached ();
838 g_assert_not_reached ();
845 read_encoded_val (guint32 encoding, guint8 *p, guint8 **endp)
849 switch (encoding & 0xf) {
850 case DW_EH_PE_sdata8:
854 case DW_EH_PE_sdata4:
859 g_assert_not_reached ();
869 * Decode the Mono specific Language Specific Data Area generated by LLVM.
872 decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo **ex_info, guint32 *ex_info_len, gpointer **type_info, int *this_reg, int *this_offset)
875 int i, ncall_sites, this_encoding;
876 guint32 mono_magic, version;
880 /* This is the modified LSDA generated by the LLVM mono branch */
881 mono_magic = decode_uleb128 (p, &p);
882 g_assert (mono_magic == 0x4d4fef4f);
883 version = decode_uleb128 (p, &p);
884 g_assert (version == 1);
887 if (this_encoding == DW_EH_PE_udata4) {
888 gint32 op, reg, offset;
890 /* 'this' location */
892 g_assert (op == DW_OP_bregx);
894 reg = decode_uleb128 (p, &p);
895 offset = decode_sleb128 (p, &p);
897 *this_reg = mono_dwarf_reg_to_hw_reg (reg);
898 *this_offset = offset;
900 g_assert (this_encoding == DW_EH_PE_omit);
905 ncall_sites = decode_uleb128 (p, &p);
906 p = (guint8*)ALIGN_TO ((mgreg_t)p, 4);
909 *ex_info = (MonoJitExceptionInfo *)g_malloc0 (ncall_sites * sizeof (MonoJitExceptionInfo));
910 *ex_info_len = ncall_sites;
913 *type_info = (gpointer *)g_malloc0 (ncall_sites * sizeof (gpointer));
915 for (i = 0; i < ncall_sites; ++i) {
916 int block_start_offset, block_size, landing_pad;
919 block_start_offset = read32 (p);
920 p += sizeof (gint32);
921 block_size = read32 (p);
922 p += sizeof (gint32);
923 landing_pad = read32 (p);
924 p += sizeof (gint32);
926 p += sizeof (gint32);
928 g_assert (landing_pad);
929 g_assert (((size_t)tinfo % 4) == 0);
930 //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
934 (*type_info) [i] = tinfo;
935 (*ex_info)[i].try_start = code + block_start_offset;
936 (*ex_info)[i].try_end = code + block_start_offset + block_size;
937 (*ex_info)[i].handler_start = code + landing_pad;
943 * mono_unwind_decode_fde:
945 * Decode a DWARF FDE entry, returning the unwind opcodes.
946 * If not NULL, EX_INFO is set to a malloc-ed array of MonoJitExceptionInfo structures,
947 * only try_start, try_end and handler_start is set.
948 * If not NULL, TYPE_INFO is set to a malloc-ed array containing the ttype table from the
952 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)
954 guint8 *p, *cie, *fde_current, *fde_aug = NULL, *code, *fde_cfi, *cie_cfi;
955 gint32 fde_len, cie_offset, pc_begin, pc_range, aug_len;
956 gint32 cie_len, cie_id, cie_version, code_align, data_align, return_reg;
957 gint32 i, cie_aug_len, buf_len;
960 gboolean has_fde_augmentation = FALSE;
963 * http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
966 /* This is generated by JITDwarfEmitter::EmitEHFrame () */
975 // FIXME: Endianess ?
976 fde_len = *(guint32*)p;
977 g_assert (fde_len != 0xffffffff && fde_len != 0);
979 cie_offset = *(guint32*)p;
980 cie = p - cie_offset;
986 cie_len = *(guint32*)p;
988 cie_id = *(guint32*)p;
989 g_assert (cie_id == 0);
992 g_assert (cie_version == 1);
994 cie_aug_str = (char*)p;
995 p += strlen (cie_aug_str) + 1;
996 code_align = decode_uleb128 (p, &p);
997 data_align = decode_sleb128 (p, &p);
998 return_reg = decode_uleb128 (p, &p);
999 if (strstr (cie_aug_str, "z")) {
1003 cie_aug_len = decode_uleb128 (p, &p);
1005 has_fde_augmentation = TRUE;
1008 for (i = 0; cie_aug_str [i] != '\0'; ++i) {
1009 switch (cie_aug_str [i]) {
1015 read_encoded_val (p_encoding, p, &p);
1018 g_assert ((*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel)) || (*p == (DW_EH_PE_sdata8|DW_EH_PE_pcrel)));
1022 g_assert (*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel));
1026 g_assert_not_reached ();
1036 /* Continue decoding FDE */
1038 /* DW_EH_PE_sdata4|DW_EH_PE_pcrel encoding */
1039 pc_begin = *(gint32*)p;
1040 code = p + pc_begin;
1042 pc_range = *(guint32*)p;
1044 if (has_fde_augmentation) {
1045 aug_len = decode_uleb128 (p, &p);
1054 *code_len = pc_range;
1061 /* Decode FDE augmention */
1066 /* sdata|pcrel encoding */
1068 lsda_offset = read32 (fde_aug);
1069 else if (aug_len == 8)
1070 lsda_offset = *(gint64*)fde_aug;
1072 g_assert_not_reached ();
1073 if (lsda_offset != 0) {
1074 lsda = fde_aug + lsda_offset;
1076 decode_lsda (lsda, code, ex_info, ex_info_len, type_info, this_reg, this_offset);
1080 /* Make sure the FDE uses the same constants as we do */
1081 g_assert (code_align == 1);
1082 g_assert (data_align == DWARF_DATA_ALIGN);
1083 g_assert (return_reg == DWARF_PC_REG);
1085 buf_len = (cie + cie_len + 4 - cie_cfi) + (fde + fde_len + 4 - fde_cfi);
1086 buf = (guint8 *)g_malloc0 (buf_len);
1090 while (p < cie + cie_len + 4) {
1091 if (*p == DW_CFA_nop)
1094 decode_cie_op (p, &p);
1096 memcpy (buf + i, cie_cfi, p - cie_cfi);
1100 while (p < fde + fde_len + 4) {
1101 if (*p == DW_CFA_nop)
1104 decode_cie_op (p, &p);
1106 memcpy (buf + i, fde_cfi, p - fde_cfi);
1108 g_assert (i <= buf_len);
1112 return (guint8 *)g_realloc (buf, i);
1116 * mono_unwind_decode_mono_fde:
1118 * Decode an FDE entry in the LLVM emitted mono EH frame.
1119 * info->ex_info is set to a malloc-ed array of MonoJitExceptionInfo structures,
1120 * only try_start, try_end and handler_start is set.
1121 * info->type_info is set to a malloc-ed array containing the ttype table from the
1125 mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8 *code, MonoLLVMFDEInfo *res)
1127 guint8 *p, *fde_aug, *cie_cfi, *fde_cfi, *buf;
1128 int has_aug, aug_len, cie_cfi_len, fde_cfi_len;
1129 gint32 code_align, data_align, return_reg, pers_encoding;
1131 memset (res, 0, sizeof (*res));
1133 res->this_offset = -1;
1135 /* fde points to data emitted by LLVM in DwarfMonoException::EmitMonoEHFrame () */
1140 aug_len = read32 (p);
1152 /* The LSDA is embedded directly into the FDE */
1155 decode_lsda (lsda, code, &res->ex_info, &res->ex_info_len, &res->type_info, &res->this_reg, &res->this_offset);
1160 code_align = decode_uleb128 (p, &p);
1161 data_align = decode_sleb128 (p, &p);
1162 return_reg = decode_uleb128 (p, &p);
1165 if (pers_encoding != DW_EH_PE_omit)
1166 read_encoded_val (pers_encoding, p, &p);
1170 /* Make sure the FDE uses the same constants as we do */
1171 g_assert (code_align == 1);
1172 g_assert (data_align == DWARF_DATA_ALIGN);
1173 g_assert (return_reg == DWARF_PC_REG);
1175 /* Compute size of CIE unwind info it is DW_CFA_nop terminated */
1178 if (*p == DW_CFA_nop)
1181 decode_cie_op (p, &p);
1183 cie_cfi_len = p - cie_cfi;
1184 fde_cfi_len = (fde + fde_len - fde_cfi);
1186 buf = (guint8 *)g_malloc0 (cie_cfi_len + fde_cfi_len);
1187 memcpy (buf, cie_cfi, cie_cfi_len);
1188 memcpy (buf + cie_cfi_len, fde_cfi, fde_cfi_len);
1190 res->unw_info_len = cie_cfi_len + fde_cfi_len;
1191 res->unw_info = buf;
1195 * mono_unwind_get_cie_program:
1197 * Get the unwind bytecode for the DWARF CIE.
1200 mono_unwind_get_cie_program (void)
1202 #if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_POWERPC) || defined(TARGET_ARM)
1203 return mono_arch_get_cie_program ();