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.
870 * This function is async safe.
873 decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo *ex_info, gpointer *type_info, guint32 *ex_info_len, int *this_reg, int *this_offset)
876 int i, ncall_sites, this_encoding;
877 guint32 mono_magic, version;
881 /* This is the modified LSDA generated by the LLVM mono branch */
882 mono_magic = decode_uleb128 (p, &p);
883 g_assert (mono_magic == 0x4d4fef4f);
884 version = decode_uleb128 (p, &p);
885 g_assert (version == 1);
888 if (this_encoding == DW_EH_PE_udata4) {
889 gint32 op, reg, offset;
891 /* 'this' location */
893 g_assert (op == DW_OP_bregx);
895 reg = decode_uleb128 (p, &p);
896 offset = decode_sleb128 (p, &p);
898 *this_reg = mono_dwarf_reg_to_hw_reg (reg);
899 *this_offset = offset;
901 g_assert (this_encoding == DW_EH_PE_omit);
906 ncall_sites = decode_uleb128 (p, &p);
907 p = (guint8*)ALIGN_TO ((mgreg_t)p, 4);
910 *ex_info_len = ncall_sites;
912 for (i = 0; i < ncall_sites; ++i) {
913 int block_start_offset, block_size, landing_pad;
916 block_start_offset = read32 (p);
917 p += sizeof (gint32);
918 block_size = read32 (p);
919 p += sizeof (gint32);
920 landing_pad = read32 (p);
921 p += sizeof (gint32);
923 p += sizeof (gint32);
925 g_assert (landing_pad);
926 g_assert (((size_t)tinfo % 4) == 0);
927 //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
931 type_info [i] = tinfo;
932 ex_info[i].try_start = code + block_start_offset;
933 ex_info[i].try_end = code + block_start_offset + block_size;
934 ex_info[i].handler_start = code + landing_pad;
940 * mono_unwind_decode_fde:
942 * Decode a DWARF FDE entry, returning the unwind opcodes.
943 * If not NULL, EX_INFO is set to a malloc-ed array of MonoJitExceptionInfo structures,
944 * only try_start, try_end and handler_start is set.
945 * If not NULL, TYPE_INFO is set to a malloc-ed array containing the ttype table from the
949 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)
951 guint8 *p, *cie, *fde_current, *fde_aug = NULL, *code, *fde_cfi, *cie_cfi;
952 gint32 fde_len, cie_offset, pc_begin, pc_range, aug_len;
953 gint32 cie_len, cie_id, cie_version, code_align, data_align, return_reg;
954 gint32 i, cie_aug_len, buf_len;
957 gboolean has_fde_augmentation = FALSE;
960 * http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
963 /* This is generated by JITDwarfEmitter::EmitEHFrame () */
972 // FIXME: Endianess ?
973 fde_len = *(guint32*)p;
974 g_assert (fde_len != 0xffffffff && fde_len != 0);
976 cie_offset = *(guint32*)p;
977 cie = p - cie_offset;
983 cie_len = *(guint32*)p;
985 cie_id = *(guint32*)p;
986 g_assert (cie_id == 0);
989 g_assert (cie_version == 1);
991 cie_aug_str = (char*)p;
992 p += strlen (cie_aug_str) + 1;
993 code_align = decode_uleb128 (p, &p);
994 data_align = decode_sleb128 (p, &p);
995 return_reg = decode_uleb128 (p, &p);
996 if (strstr (cie_aug_str, "z")) {
1000 cie_aug_len = decode_uleb128 (p, &p);
1002 has_fde_augmentation = TRUE;
1005 for (i = 0; cie_aug_str [i] != '\0'; ++i) {
1006 switch (cie_aug_str [i]) {
1012 read_encoded_val (p_encoding, p, &p);
1015 g_assert ((*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel)) || (*p == (DW_EH_PE_sdata8|DW_EH_PE_pcrel)));
1019 g_assert (*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel));
1023 g_assert_not_reached ();
1033 /* Continue decoding FDE */
1035 /* DW_EH_PE_sdata4|DW_EH_PE_pcrel encoding */
1036 pc_begin = *(gint32*)p;
1037 code = p + pc_begin;
1039 pc_range = *(guint32*)p;
1041 if (has_fde_augmentation) {
1042 aug_len = decode_uleb128 (p, &p);
1051 *code_len = pc_range;
1058 /* Decode FDE augmention */
1063 /* sdata|pcrel encoding */
1065 lsda_offset = read32 (fde_aug);
1066 else if (aug_len == 8)
1067 lsda_offset = *(gint64*)fde_aug;
1069 g_assert_not_reached ();
1070 if (lsda_offset != 0) {
1071 lsda = fde_aug + lsda_offset;
1073 /* Get the lengths first */
1075 decode_lsda (lsda, code, NULL, NULL, &len, this_reg, this_offset);
1078 *ex_info = (MonoJitExceptionInfo *)g_malloc0 (len * sizeof (MonoJitExceptionInfo));
1080 *type_info = (gpointer *)g_malloc0 (len * sizeof (gpointer));
1082 decode_lsda (lsda, code, ex_info ? *ex_info : NULL, type_info ? *type_info : NULL, ex_info_len, this_reg, this_offset);
1086 /* Make sure the FDE uses the same constants as we do */
1087 g_assert (code_align == 1);
1088 g_assert (data_align == DWARF_DATA_ALIGN);
1089 g_assert (return_reg == DWARF_PC_REG);
1091 buf_len = (cie + cie_len + 4 - cie_cfi) + (fde + fde_len + 4 - fde_cfi);
1092 buf = (guint8 *)g_malloc0 (buf_len);
1096 while (p < cie + cie_len + 4) {
1097 if (*p == DW_CFA_nop)
1100 decode_cie_op (p, &p);
1102 memcpy (buf + i, cie_cfi, p - cie_cfi);
1106 while (p < fde + fde_len + 4) {
1107 if (*p == DW_CFA_nop)
1110 decode_cie_op (p, &p);
1112 memcpy (buf + i, fde_cfi, p - fde_cfi);
1114 g_assert (i <= buf_len);
1118 return (guint8 *)g_realloc (buf, i);
1122 * mono_unwind_decode_mono_fde:
1124 * Decode an FDE entry in the LLVM emitted mono EH frame.
1125 * If EI/TYPE_INFO/UNW_INFO are NULL, compute only the value of the scalar fields in INFO.
1127 * - Fill out EX_INFO with try_start, try_end and handler_start.
1128 * - Fill out TYPE_INFO with the ttype table from the LSDA.
1129 * - Fill out UNW_INFO with the unwind info.
1130 * This function is async safe.
1133 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)
1135 guint8 *p, *fde_aug, *cie_cfi, *fde_cfi, *buf;
1136 int has_aug, aug_len, cie_cfi_len, fde_cfi_len;
1137 gint32 code_align, data_align, return_reg, pers_encoding;
1139 memset (res, 0, sizeof (*res));
1141 res->this_offset = -1;
1143 /* fde points to data emitted by LLVM in DwarfMonoException::EmitMonoEHFrame () */
1148 aug_len = read32 (p);
1160 /* The LSDA is embedded directly into the FDE */
1163 /* Get the lengths first */
1164 decode_lsda (lsda, code, NULL, NULL, &res->ex_info_len, &res->this_reg, &res->this_offset);
1166 decode_lsda (lsda, code, ex_info, type_info, NULL, &res->this_reg, &res->this_offset);
1171 code_align = decode_uleb128 (p, &p);
1172 data_align = decode_sleb128 (p, &p);
1173 return_reg = decode_uleb128 (p, &p);
1176 if (pers_encoding != DW_EH_PE_omit)
1177 read_encoded_val (pers_encoding, p, &p);
1181 /* Make sure the FDE uses the same constants as we do */
1182 g_assert (code_align == 1);
1183 g_assert (data_align == DWARF_DATA_ALIGN);
1184 g_assert (return_reg == DWARF_PC_REG);
1186 /* Compute size of CIE unwind info it is DW_CFA_nop terminated */
1189 if (*p == DW_CFA_nop)
1192 decode_cie_op (p, &p);
1194 cie_cfi_len = p - cie_cfi;
1195 fde_cfi_len = (fde + fde_len - fde_cfi);
1199 memcpy (buf, cie_cfi, cie_cfi_len);
1200 memcpy (buf + cie_cfi_len, fde_cfi, fde_cfi_len);
1203 res->unw_info_len = cie_cfi_len + fde_cfi_len;
1207 * mono_unwind_get_cie_program:
1209 * Get the unwind bytecode for the DWARF CIE.
1212 mono_unwind_get_cie_program (void)
1214 #if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_POWERPC) || defined(TARGET_ARM)
1215 return mono_arch_get_cie_program ();