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);
452 #if defined(TARGET_WIN32) && defined(TARGET_AMD64)
453 case DW_CFA_mono_sp_alloc_info_win64:
454 case DW_CFA_mono_fp_alloc_info_win64:
455 // Drop Windows specific unwind op's. These op's are currently
456 // only used when registering unwind info with Windows OS unwinder.
460 g_assert_not_reached ();
465 g_assert (p - buf < 4096);
467 res = (guint8 *)g_malloc (p - buf);
468 memcpy (res, buf, p - buf);
473 mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
475 return mono_unwind_ops_encode_full (unwind_ops, out_len, TRUE);
479 #define UNW_DEBUG(stmt) do { stmt; } while (0)
481 #define UNW_DEBUG(stmt) do { } while (0)
484 static G_GNUC_UNUSED void
485 print_dwarf_state (int cfa_reg, int cfa_offset, int ip, int nregs, Loc *locations, guint8 *reg_saved)
489 printf ("\t%x: cfa=r%d+%d ", ip, cfa_reg, cfa_offset);
491 for (i = 0; i < nregs; ++i)
492 if (reg_saved [i] && locations [i].loc_type == LOC_OFFSET)
493 printf ("r%d@%d(cfa) ", i, locations [i].offset);
498 Loc locations [NUM_HW_REGS];
499 guint8 reg_saved [NUM_HW_REGS];
500 int cfa_reg, cfa_offset;
504 * Given the state of the current frame as stored in REGS, execute the unwind
505 * operations in unwind_info until the location counter reaches POS. The result is
506 * stored back into REGS. OUT_CFA will receive the value of the CFA.
507 * If SAVE_LOCATIONS is non-NULL, it should point to an array of size SAVE_LOCATIONS_LEN.
508 * On return, the nth entry will point to the address of the stack slot where register
509 * N was saved, or NULL, if it was not saved by this frame.
510 * MARK_LOCATIONS should contain the locations marked by mono_emit_unwind_op_mark_loc (), if any.
511 * This function is signal safe.
514 mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len,
515 guint8 *start_ip, guint8 *end_ip, guint8 *ip, guint8 **mark_locations,
516 mono_unwind_reg_t *regs, int nregs,
517 mgreg_t **save_locations, int save_locations_len,
520 Loc locations [NUM_HW_REGS];
521 guint8 reg_saved [NUM_HW_REGS];
522 int pos, reg, hwreg, cfa_reg = -1, cfa_offset = 0, offset;
525 UnwindState state_stack [1];
528 memset (reg_saved, 0, sizeof (reg_saved));
529 state_stack [0].cfa_reg = -1;
530 state_stack [0].cfa_offset = 0;
537 while (pos <= ip - start_ip && p < unwind_info + unwind_info_len) {
541 case DW_CFA_advance_loc:
542 UNW_DEBUG (print_dwarf_state (cfa_reg, cfa_offset, pos, nregs, locations));
547 hwreg = mono_dwarf_reg_to_hw_reg (*p & 0x3f);
549 reg_saved [hwreg] = TRUE;
550 locations [hwreg].loc_type = LOC_OFFSET;
551 locations [hwreg].offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
558 cfa_reg = decode_uleb128 (p, &p);
559 cfa_offset = decode_uleb128 (p, &p);
561 case DW_CFA_def_cfa_offset:
562 cfa_offset = decode_uleb128 (p, &p);
564 case DW_CFA_def_cfa_register:
565 cfa_reg = decode_uleb128 (p, &p);
567 case DW_CFA_offset_extended_sf:
568 reg = decode_uleb128 (p, &p);
569 hwreg = mono_dwarf_reg_to_hw_reg (reg);
570 offset = decode_sleb128 (p, &p);
571 g_assert (reg < NUM_DWARF_REGS);
572 reg_saved [hwreg] = TRUE;
573 locations [hwreg].loc_type = LOC_OFFSET;
574 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
576 case DW_CFA_offset_extended:
577 reg = decode_uleb128 (p, &p);
578 hwreg = mono_dwarf_reg_to_hw_reg (reg);
579 offset = decode_uleb128 (p, &p);
580 g_assert (reg < NUM_DWARF_REGS);
581 reg_saved [hwreg] = TRUE;
582 locations [hwreg].loc_type = LOC_OFFSET;
583 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
585 case DW_CFA_same_value:
586 hwreg = mono_dwarf_reg_to_hw_reg (decode_uleb128 (p, &p));
587 locations [hwreg].loc_type = LOC_SAME;
589 case DW_CFA_advance_loc1:
593 case DW_CFA_advance_loc2:
597 case DW_CFA_advance_loc4:
601 case DW_CFA_remember_state:
602 g_assert (state_stack_pos == 0);
603 memcpy (&state_stack [0].locations, &locations, sizeof (locations));
604 memcpy (&state_stack [0].reg_saved, ®_saved, sizeof (reg_saved));
605 state_stack [0].cfa_reg = cfa_reg;
606 state_stack [0].cfa_offset = cfa_offset;
609 case DW_CFA_restore_state:
610 g_assert (state_stack_pos == 1);
612 memcpy (&locations, &state_stack [0].locations, sizeof (locations));
613 memcpy (®_saved, &state_stack [0].reg_saved, sizeof (reg_saved));
614 cfa_reg = state_stack [0].cfa_reg;
615 cfa_offset = state_stack [0].cfa_offset;
617 case DW_CFA_mono_advance_loc:
618 g_assert (mark_locations [0]);
619 pos = mark_locations [0] - start_ip;
622 g_assert_not_reached ();
627 g_assert_not_reached ();
632 memset (save_locations, 0, save_locations_len * sizeof (mgreg_t*));
634 g_assert (cfa_reg != -1);
635 cfa_val = (guint8*)regs [mono_dwarf_reg_to_hw_reg (cfa_reg)] + cfa_offset;
636 for (hwreg = 0; hwreg < NUM_HW_REGS; ++hwreg) {
637 if (reg_saved [hwreg] && locations [hwreg].loc_type == LOC_OFFSET) {
638 int dwarfreg = mono_hw_reg_to_dwarf_reg (hwreg);
639 g_assert (hwreg < nregs);
640 if (IS_DOUBLE_REG (dwarfreg))
641 regs [hwreg] = *(guint64*)(cfa_val + locations [hwreg].offset);
643 regs [hwreg] = *(mgreg_t*)(cfa_val + locations [hwreg].offset);
644 if (save_locations && hwreg < save_locations_len)
645 save_locations [hwreg] = (mgreg_t*)(cfa_val + locations [hwreg].offset);
653 mono_unwind_init (void)
655 mono_os_mutex_init_recursive (&unwind_mutex);
657 mono_counters_register ("Unwind info size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &unwind_info_size);
661 mono_unwind_cleanup (void)
665 mono_os_mutex_destroy (&unwind_mutex);
670 for (i = 0; i < cached_info_next; ++i) {
671 MonoUnwindInfo *cached = cached_info [i];
675 g_free (cached_info);
677 for (GSList *cursor = cached_info_list; cursor != NULL; cursor = cursor->next)
678 g_free (cursor->data);
680 g_slist_free (cached_info_list);
684 * mono_cache_unwind_info
686 * Save UNWIND_INFO in the unwind info cache and return an id which can be passed
687 * to mono_get_cached_unwind_info to get a cached copy of the info.
688 * A copy is made of the unwind info.
689 * This function is useful for two reasons:
690 * - many methods have the same unwind info
691 * - MonoJitInfo->unwind_info is an int so it can't store the pointer to the unwind info
694 mono_cache_unwind_info (guint8 *unwind_info, guint32 unwind_info_len)
697 MonoUnwindInfo *info;
701 if (cached_info == NULL) {
702 cached_info_size = 16;
703 cached_info = g_new0 (MonoUnwindInfo*, cached_info_size);
706 for (i = 0; i < cached_info_next; ++i) {
707 MonoUnwindInfo *cached = cached_info [i];
709 if (cached->len == unwind_info_len && memcmp (cached->info, unwind_info, unwind_info_len) == 0) {
715 info = (MonoUnwindInfo *)g_malloc (sizeof (MonoUnwindInfo) + unwind_info_len);
716 info->len = unwind_info_len;
717 memcpy (&info->info, unwind_info, unwind_info_len);
719 i = cached_info_next;
721 if (cached_info_next >= cached_info_size) {
722 MonoUnwindInfo **new_table;
725 * Avoid freeing the old table so mono_get_cached_unwind_info ()
726 * doesn't need locks/hazard pointers.
729 new_table = g_new0 (MonoUnwindInfo*, cached_info_size * 2);
731 memcpy (new_table, cached_info, cached_info_size * sizeof (MonoUnwindInfo*));
733 mono_memory_barrier ();
735 cached_info_list = g_slist_prepend (cached_info_list, cached_info);
737 cached_info = new_table;
739 cached_info_size *= 2;
742 cached_info [cached_info_next ++] = info;
744 unwind_info_size += sizeof (MonoUnwindInfo) + unwind_info_len;
751 * This function is signal safe.
754 mono_get_cached_unwind_info (guint32 index, guint32 *unwind_info_len)
756 MonoUnwindInfo **table;
757 MonoUnwindInfo *info;
761 * This doesn't need any locks/hazard pointers,
762 * since new tables are copies of the old ones.
766 info = table [index];
768 *unwind_info_len = info->len;
775 * mono_unwind_get_dwarf_data_align:
777 * Return the data alignment used by the encoded unwind information.
780 mono_unwind_get_dwarf_data_align (void)
782 return DWARF_DATA_ALIGN;
786 * mono_unwind_get_dwarf_pc_reg:
788 * Return the dwarf register number of the register holding the ip of the
792 mono_unwind_get_dwarf_pc_reg (void)
798 decode_cie_op (guint8 *p, guint8 **endp)
803 case DW_CFA_advance_loc:
808 decode_uleb128 (p, &p);
815 decode_uleb128 (p, &p);
816 decode_uleb128 (p, &p);
818 case DW_CFA_def_cfa_offset:
819 decode_uleb128 (p, &p);
821 case DW_CFA_def_cfa_register:
822 decode_uleb128 (p, &p);
824 case DW_CFA_advance_loc4:
827 case DW_CFA_offset_extended_sf:
828 decode_uleb128 (p, &p);
829 decode_uleb128 (p, &p);
832 g_assert_not_reached ();
837 g_assert_not_reached ();
844 read_encoded_val (guint32 encoding, guint8 *p, guint8 **endp)
848 switch (encoding & 0xf) {
849 case DW_EH_PE_sdata8:
853 case DW_EH_PE_sdata4:
858 g_assert_not_reached ();
868 * Decode the Mono specific Language Specific Data Area generated by LLVM.
871 decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo **ex_info, guint32 *ex_info_len, gpointer **type_info, int *this_reg, int *this_offset)
874 int i, ncall_sites, this_encoding;
875 guint32 mono_magic, version;
879 /* This is the modified LSDA generated by the LLVM mono branch */
880 mono_magic = decode_uleb128 (p, &p);
881 g_assert (mono_magic == 0x4d4fef4f);
882 version = decode_uleb128 (p, &p);
883 g_assert (version == 1);
886 if (this_encoding == DW_EH_PE_udata4) {
887 gint32 op, reg, offset;
889 /* 'this' location */
891 g_assert (op == DW_OP_bregx);
893 reg = decode_uleb128 (p, &p);
894 offset = decode_sleb128 (p, &p);
896 *this_reg = mono_dwarf_reg_to_hw_reg (reg);
897 *this_offset = offset;
899 g_assert (this_encoding == DW_EH_PE_omit);
904 ncall_sites = decode_uleb128 (p, &p);
905 p = (guint8*)ALIGN_TO ((mgreg_t)p, 4);
908 *ex_info = (MonoJitExceptionInfo *)g_malloc0 (ncall_sites * sizeof (MonoJitExceptionInfo));
909 *ex_info_len = ncall_sites;
912 *type_info = (gpointer *)g_malloc0 (ncall_sites * sizeof (gpointer));
914 for (i = 0; i < ncall_sites; ++i) {
915 int block_start_offset, block_size, landing_pad;
918 block_start_offset = read32 (p);
919 p += sizeof (gint32);
920 block_size = read32 (p);
921 p += sizeof (gint32);
922 landing_pad = read32 (p);
923 p += sizeof (gint32);
925 p += sizeof (gint32);
927 g_assert (landing_pad);
928 g_assert (((size_t)tinfo % 4) == 0);
929 //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
933 (*type_info) [i] = tinfo;
934 (*ex_info)[i].try_start = code + block_start_offset;
935 (*ex_info)[i].try_end = code + block_start_offset + block_size;
936 (*ex_info)[i].handler_start = code + landing_pad;
942 * mono_unwind_decode_fde:
944 * Decode a DWARF FDE entry, returning the unwind opcodes.
945 * If not NULL, EX_INFO is set to a malloc-ed array of MonoJitExceptionInfo structures,
946 * only try_start, try_end and handler_start is set.
947 * If not NULL, TYPE_INFO is set to a malloc-ed array containing the ttype table from the
951 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)
953 guint8 *p, *cie, *fde_current, *fde_aug = NULL, *code, *fde_cfi, *cie_cfi;
954 gint32 fde_len, cie_offset, pc_begin, pc_range, aug_len;
955 gint32 cie_len, cie_id, cie_version, code_align, data_align, return_reg;
956 gint32 i, cie_aug_len, buf_len;
959 gboolean has_fde_augmentation = FALSE;
962 * http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
965 /* This is generated by JITDwarfEmitter::EmitEHFrame () */
974 // FIXME: Endianess ?
975 fde_len = *(guint32*)p;
976 g_assert (fde_len != 0xffffffff && fde_len != 0);
978 cie_offset = *(guint32*)p;
979 cie = p - cie_offset;
985 cie_len = *(guint32*)p;
987 cie_id = *(guint32*)p;
988 g_assert (cie_id == 0);
991 g_assert (cie_version == 1);
993 cie_aug_str = (char*)p;
994 p += strlen (cie_aug_str) + 1;
995 code_align = decode_uleb128 (p, &p);
996 data_align = decode_sleb128 (p, &p);
997 return_reg = decode_uleb128 (p, &p);
998 if (strstr (cie_aug_str, "z")) {
1002 cie_aug_len = decode_uleb128 (p, &p);
1004 has_fde_augmentation = TRUE;
1007 for (i = 0; cie_aug_str [i] != '\0'; ++i) {
1008 switch (cie_aug_str [i]) {
1014 read_encoded_val (p_encoding, p, &p);
1017 g_assert ((*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel)) || (*p == (DW_EH_PE_sdata8|DW_EH_PE_pcrel)));
1021 g_assert (*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel));
1025 g_assert_not_reached ();
1035 /* Continue decoding FDE */
1037 /* DW_EH_PE_sdata4|DW_EH_PE_pcrel encoding */
1038 pc_begin = *(gint32*)p;
1039 code = p + pc_begin;
1041 pc_range = *(guint32*)p;
1043 if (has_fde_augmentation) {
1044 aug_len = decode_uleb128 (p, &p);
1053 *code_len = pc_range;
1060 /* Decode FDE augmention */
1065 /* sdata|pcrel encoding */
1067 lsda_offset = read32 (fde_aug);
1068 else if (aug_len == 8)
1069 lsda_offset = *(gint64*)fde_aug;
1071 g_assert_not_reached ();
1072 if (lsda_offset != 0) {
1073 lsda = fde_aug + lsda_offset;
1075 decode_lsda (lsda, code, ex_info, ex_info_len, type_info, this_reg, this_offset);
1079 /* Make sure the FDE uses the same constants as we do */
1080 g_assert (code_align == 1);
1081 g_assert (data_align == DWARF_DATA_ALIGN);
1082 g_assert (return_reg == DWARF_PC_REG);
1084 buf_len = (cie + cie_len + 4 - cie_cfi) + (fde + fde_len + 4 - fde_cfi);
1085 buf = (guint8 *)g_malloc0 (buf_len);
1089 while (p < cie + cie_len + 4) {
1090 if (*p == DW_CFA_nop)
1093 decode_cie_op (p, &p);
1095 memcpy (buf + i, cie_cfi, p - cie_cfi);
1099 while (p < fde + fde_len + 4) {
1100 if (*p == DW_CFA_nop)
1103 decode_cie_op (p, &p);
1105 memcpy (buf + i, fde_cfi, p - fde_cfi);
1107 g_assert (i <= buf_len);
1111 return (guint8 *)g_realloc (buf, i);
1115 * mono_unwind_decode_mono_fde:
1117 * Decode an FDE entry in the LLVM emitted mono EH frame.
1118 * info->ex_info is set to a malloc-ed array of MonoJitExceptionInfo structures,
1119 * only try_start, try_end and handler_start is set.
1120 * info->type_info is set to a malloc-ed array containing the ttype table from the
1124 mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8 *code, MonoLLVMFDEInfo *res)
1126 guint8 *p, *fde_aug, *cie_cfi, *fde_cfi, *buf;
1127 int has_aug, aug_len, cie_cfi_len, fde_cfi_len;
1128 gint32 code_align, data_align, return_reg, pers_encoding;
1130 memset (res, 0, sizeof (*res));
1132 res->this_offset = -1;
1134 /* fde points to data emitted by LLVM in DwarfMonoException::EmitMonoEHFrame () */
1139 aug_len = read32 (p);
1151 /* The LSDA is embedded directly into the FDE */
1154 decode_lsda (lsda, code, &res->ex_info, &res->ex_info_len, &res->type_info, &res->this_reg, &res->this_offset);
1159 code_align = decode_uleb128 (p, &p);
1160 data_align = decode_sleb128 (p, &p);
1161 return_reg = decode_uleb128 (p, &p);
1164 if (pers_encoding != DW_EH_PE_omit)
1165 read_encoded_val (pers_encoding, p, &p);
1169 /* Make sure the FDE uses the same constants as we do */
1170 g_assert (code_align == 1);
1171 g_assert (data_align == DWARF_DATA_ALIGN);
1172 g_assert (return_reg == DWARF_PC_REG);
1174 /* Compute size of CIE unwind info it is DW_CFA_nop terminated */
1177 if (*p == DW_CFA_nop)
1180 decode_cie_op (p, &p);
1182 cie_cfi_len = p - cie_cfi;
1183 fde_cfi_len = (fde + fde_len - fde_cfi);
1185 buf = (guint8 *)g_malloc0 (cie_cfi_len + fde_cfi_len);
1186 memcpy (buf, cie_cfi, cie_cfi_len);
1187 memcpy (buf + cie_cfi_len, fde_cfi, fde_cfi_len);
1189 res->unw_info_len = cie_cfi_len + fde_cfi_len;
1190 res->unw_info = buf;
1194 * mono_unwind_get_cie_program:
1196 * Get the unwind bytecode for the DWARF CIE.
1199 mono_unwind_get_cie_program (void)
1201 #if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_POWERPC) || defined(TARGET_ARM)
1202 return mono_arch_get_cie_program ();