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_mutex_lock (&unwind_mutex)
45 #define unwind_unlock() mono_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_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 */
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 };
57 #define DWARF_DATA_ALIGN (-4)
58 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (ARMREG_LR))
59 #elif defined(TARGET_ARM64)
61 #define DWARF_DATA_ALIGN (-8)
63 #define DWARF_PC_REG 30
64 static int map_hw_reg_to_dwarf_reg [] = {
65 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
66 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
68 72, 73, 74, 75, 76, 77, 78, 79,
70 #elif defined (TARGET_X86)
73 * LLVM seems to generate unwind info where esp is encoded as 5, and ebp as 4, ie see this line:
74 * def ESP : RegisterWithSubRegs<"esp", [SP]>, DwarfRegNum<[-2, 5, 4]>;
75 * in lib/Target/X86/X86RegisterInfo.td in the llvm sources.
77 static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 5, 4, 6, 7, 8 };
79 static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
82 #define NUM_REGS X86_NREG + 1
83 #define DWARF_DATA_ALIGN (-4)
84 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (X86_NREG))
85 #elif defined (TARGET_POWERPC)
86 // http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
87 static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,
88 9, 10, 11, 12, 13, 14, 15, 16,
89 17, 18, 19, 20, 21, 22, 23, 24,
90 25, 26, 27, 28, 29, 30, 31 };
92 #define DWARF_DATA_ALIGN (-(gint32)sizeof (mgreg_t))
93 #define DWARF_PC_REG 108
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 };
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
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];
113 #define DWARF_DATA_ALIGN 0
114 #define DWARF_PC_REG -1
117 static gboolean dwarf_reg_to_hw_reg_inited;
119 static int map_dwarf_reg_to_hw_reg [NUM_REGS];
122 * mono_hw_reg_to_dwarf_reg:
124 * Map the hardware register number REG to the register number used by DWARF.
127 mono_hw_reg_to_dwarf_reg (int reg)
129 #ifdef TARGET_POWERPC
133 g_assert (reg < NUM_REGS);
137 g_assert_not_reached ();
140 return map_hw_reg_to_dwarf_reg [reg];
149 g_assert (NUM_REGS > 0);
150 for (i = 0; i < sizeof (map_hw_reg_to_dwarf_reg) / sizeof (int); ++i) {
151 map_dwarf_reg_to_hw_reg [mono_hw_reg_to_dwarf_reg (i)] = i;
154 #ifdef TARGET_POWERPC
155 map_dwarf_reg_to_hw_reg [DWARF_PC_REG] = ppc_lr;
158 mono_memory_barrier ();
159 dwarf_reg_to_hw_reg_inited = TRUE;
163 mono_dwarf_reg_to_hw_reg (int reg)
165 if (!dwarf_reg_to_hw_reg_inited)
168 return map_dwarf_reg_to_hw_reg [reg];
171 static G_GNUC_UNUSED void
172 encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
177 guint8 b = value & 0x7f;
179 if (value != 0) /* more bytes to come */
187 static G_GNUC_UNUSED void
188 encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
191 gboolean negative = (value < 0);
199 /* the following is unnecessary if the
200 * implementation of >>= uses an arithmetic rather
201 * than logical shift for a signed left operand
205 value |= - (1 <<(size - 7));
206 /* sign bit of byte is second high order bit (0x40) */
207 if ((value == 0 && !(byte & 0x40)) ||
208 (value == -1 && (byte & 0x40)))
218 static inline guint32
219 decode_uleb128 (guint8 *buf, guint8 **endbuf)
229 res = res | (((int)(b & 0x7f)) << shift);
241 decode_sleb128 (guint8 *buf, guint8 **endbuf)
251 res = res | (((int)(b & 0x7f)) << shift);
254 if (shift < 32 && (b & 0x40))
255 res |= - (1 << shift);
266 mono_print_unwind_info (guint8 *unwind_info, int unwind_info_len)
269 int pos, reg, offset, cfa_reg, cfa_offset;
273 while (p < unwind_info + unwind_info_len) {
277 case DW_CFA_advance_loc:
284 offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
285 if (reg == DWARF_PC_REG)
286 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, "pc", -offset);
288 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
295 cfa_reg = decode_uleb128 (p, &p);
296 cfa_offset = decode_uleb128 (p, &p);
297 printf ("CFA: [%x] def_cfa: %s+0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)), cfa_offset);
299 case DW_CFA_def_cfa_offset:
300 cfa_offset = decode_uleb128 (p, &p);
301 printf ("CFA: [%x] def_cfa_offset: 0x%x\n", pos, cfa_offset);
303 case DW_CFA_def_cfa_register:
304 cfa_reg = decode_uleb128 (p, &p);
305 printf ("CFA: [%x] def_cfa_reg: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)));
307 case DW_CFA_offset_extended_sf:
308 reg = decode_uleb128 (p, &p);
309 offset = decode_sleb128 (p, &p) * DWARF_DATA_ALIGN;
310 printf ("CFA: [%x] offset_extended_sf: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
312 case DW_CFA_same_value:
313 reg = decode_uleb128 (p, &p);
314 printf ("CFA: [%x] same_value: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)));
316 case DW_CFA_advance_loc4:
320 case DW_CFA_remember_state:
321 printf ("CFA: [%x] remember_state\n", pos);
323 case DW_CFA_restore_state:
324 printf ("CFA: [%x] restore_state\n", pos);
326 case DW_CFA_mono_advance_loc:
327 printf ("CFA: [%x] mono_advance_loc\n", pos);
330 g_assert_not_reached ();
335 g_assert_not_reached ();
341 * mono_unwind_ops_encode:
343 * Encode the unwind ops in UNWIND_OPS into the compact DWARF encoding.
344 * Return a pointer to malloc'ed memory.
347 mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
359 for (; l; l = l->next) {
364 /* Convert the register from the hw encoding to the dwarf encoding */
365 reg = mono_hw_reg_to_dwarf_reg (op->reg);
367 if (op->op == DW_CFA_mono_advance_loc) {
368 /* This advances loc to its location */
372 /* Emit an advance_loc if neccesary */
373 while (op->when > loc) {
374 if (op->when - loc > 65536) {
375 *p ++ = DW_CFA_advance_loc4;
376 *(guint32*)p = (guint32)(op->when - loc);
377 g_assert (read32 (p) == (guint32)(op->when - loc));
380 } else if (op->when - loc > 256) {
381 *p ++ = DW_CFA_advance_loc2;
382 *(guint16*)p = (guint16)(op->when - loc);
383 g_assert (read16 (p) == (guint32)(op->when - loc));
386 } else if (op->when - loc >= 32) {
387 *p ++ = DW_CFA_advance_loc1;
388 *(guint8*)p = (guint8)(op->when - loc);
391 } else if (op->when - loc < 32) {
392 *p ++ = DW_CFA_advance_loc | (op->when - loc);
395 *p ++ = DW_CFA_advance_loc | (30);
403 encode_uleb128 (reg, p, &p);
404 encode_uleb128 (op->val, p, &p);
406 case DW_CFA_def_cfa_offset:
408 encode_uleb128 (op->val, p, &p);
410 case DW_CFA_def_cfa_register:
412 encode_uleb128 (reg, p, &p);
414 case DW_CFA_same_value:
416 encode_uleb128 (reg, p, &p);
420 *p ++ = DW_CFA_offset_extended_sf;
421 encode_uleb128 (reg, p, &p);
422 encode_sleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
424 *p ++ = DW_CFA_offset | reg;
425 encode_uleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
428 case DW_CFA_remember_state:
429 case DW_CFA_restore_state:
432 case DW_CFA_mono_advance_loc:
433 /* Only one location is supported */
434 g_assert (op->val == 0);
438 g_assert_not_reached ();
443 g_assert (p - buf < 4096);
445 res = g_malloc (p - buf);
446 memcpy (res, buf, p - buf);
451 #define UNW_DEBUG(stmt) do { stmt; } while (0)
453 #define UNW_DEBUG(stmt) do { } while (0)
456 static G_GNUC_UNUSED void
457 print_dwarf_state (int cfa_reg, int cfa_offset, int ip, int nregs, Loc *locations, guint8 *reg_saved)
461 printf ("\t%x: cfa=r%d+%d ", ip, cfa_reg, cfa_offset);
463 for (i = 0; i < nregs; ++i)
464 if (reg_saved [i] && locations [i].loc_type == LOC_OFFSET)
465 printf ("r%d@%d(cfa) ", i, locations [i].offset);
470 Loc locations [NUM_REGS];
471 guint8 reg_saved [NUM_REGS];
472 int cfa_reg, cfa_offset;
476 * Given the state of the current frame as stored in REGS, execute the unwind
477 * operations in unwind_info until the location counter reaches POS. The result is
478 * stored back into REGS. OUT_CFA will receive the value of the CFA.
479 * If SAVE_LOCATIONS is non-NULL, it should point to an array of size SAVE_LOCATIONS_LEN.
480 * On return, the nth entry will point to the address of the stack slot where register
481 * N was saved, or NULL, if it was not saved by this frame.
482 * MARK_LOCATIONS should contain the locations marked by mono_emit_unwind_op_mark_loc (), if any.
483 * This function is signal safe.
486 mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len,
487 guint8 *start_ip, guint8 *end_ip, guint8 *ip, guint8 **mark_locations,
488 mgreg_t *regs, int nregs,
489 mgreg_t **save_locations, int save_locations_len,
492 Loc locations [NUM_REGS];
493 guint8 reg_saved [NUM_REGS];
494 int i, pos, reg, cfa_reg = -1, cfa_offset = 0, offset;
497 UnwindState state_stack [1];
500 memset (reg_saved, 0, sizeof (reg_saved));
501 state_stack [0].cfa_reg = -1;
502 state_stack [0].cfa_offset = 0;
509 while (pos <= ip - start_ip && p < unwind_info + unwind_info_len) {
513 case DW_CFA_advance_loc:
514 UNW_DEBUG (print_dwarf_state (cfa_reg, cfa_offset, pos, nregs, locations));
521 reg_saved [reg] = TRUE;
522 locations [reg].loc_type = LOC_OFFSET;
523 locations [reg].offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
530 cfa_reg = decode_uleb128 (p, &p);
531 cfa_offset = decode_uleb128 (p, &p);
533 case DW_CFA_def_cfa_offset:
534 cfa_offset = decode_uleb128 (p, &p);
536 case DW_CFA_def_cfa_register:
537 cfa_reg = decode_uleb128 (p, &p);
539 case DW_CFA_offset_extended_sf:
540 reg = decode_uleb128 (p, &p);
541 offset = decode_sleb128 (p, &p);
542 g_assert (reg < NUM_REGS);
543 reg_saved [reg] = TRUE;
544 locations [reg].loc_type = LOC_OFFSET;
545 locations [reg].offset = offset * DWARF_DATA_ALIGN;
547 case DW_CFA_offset_extended:
548 reg = decode_uleb128 (p, &p);
549 offset = decode_uleb128 (p, &p);
550 g_assert (reg < NUM_REGS);
551 reg_saved [reg] = TRUE;
552 locations [reg].loc_type = LOC_OFFSET;
553 locations [reg].offset = offset * DWARF_DATA_ALIGN;
555 case DW_CFA_same_value:
556 reg = decode_uleb128 (p, &p);
557 locations [reg].loc_type = LOC_SAME;
559 case DW_CFA_advance_loc1:
563 case DW_CFA_advance_loc2:
567 case DW_CFA_advance_loc4:
571 case DW_CFA_remember_state:
572 g_assert (state_stack_pos == 0);
573 memcpy (&state_stack [0].locations, &locations, sizeof (locations));
574 memcpy (&state_stack [0].reg_saved, ®_saved, sizeof (reg_saved));
575 state_stack [0].cfa_reg = cfa_reg;
576 state_stack [0].cfa_offset = cfa_offset;
579 case DW_CFA_restore_state:
580 g_assert (state_stack_pos == 1);
582 memcpy (&locations, &state_stack [0].locations, sizeof (locations));
583 memcpy (®_saved, &state_stack [0].reg_saved, sizeof (reg_saved));
584 cfa_reg = state_stack [0].cfa_reg;
585 cfa_offset = state_stack [0].cfa_offset;
587 case DW_CFA_mono_advance_loc:
588 g_assert (mark_locations [0]);
589 pos = mark_locations [0] - start_ip;
592 g_assert_not_reached ();
597 g_assert_not_reached ();
602 memset (save_locations, 0, save_locations_len * sizeof (mgreg_t*));
604 g_assert (cfa_reg != -1);
605 cfa_val = (guint8*)regs [mono_dwarf_reg_to_hw_reg (cfa_reg)] + cfa_offset;
606 for (i = 0; i < NUM_REGS; ++i) {
607 if (reg_saved [i] && locations [i].loc_type == LOC_OFFSET) {
608 int hreg = mono_dwarf_reg_to_hw_reg (i);
609 g_assert (hreg < nregs);
610 regs [hreg] = *(mgreg_t*)(cfa_val + locations [i].offset);
611 if (save_locations && hreg < save_locations_len)
612 save_locations [hreg] = (mgreg_t*)(cfa_val + locations [i].offset);
620 mono_unwind_init (void)
622 mono_mutex_init_recursive (&unwind_mutex);
624 mono_counters_register ("Unwind info size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &unwind_info_size);
628 mono_unwind_cleanup (void)
632 mono_mutex_destroy (&unwind_mutex);
637 for (i = 0; i < cached_info_next; ++i) {
638 MonoUnwindInfo *cached = cached_info [i];
643 g_free (cached_info);
647 * mono_cache_unwind_info
649 * Save UNWIND_INFO in the unwind info cache and return an id which can be passed
650 * to mono_get_cached_unwind_info to get a cached copy of the info.
651 * A copy is made of the unwind info.
652 * This function is useful for two reasons:
653 * - many methods have the same unwind info
654 * - MonoJitInfo->unwind_info is an int so it can't store the pointer to the unwind info
657 mono_cache_unwind_info (guint8 *unwind_info, guint32 unwind_info_len)
660 MonoUnwindInfo *info;
664 if (cached_info == NULL) {
665 cached_info_size = 16;
666 cached_info = g_new0 (MonoUnwindInfo*, cached_info_size);
669 for (i = 0; i < cached_info_next; ++i) {
670 MonoUnwindInfo *cached = cached_info [i];
672 if (cached->len == unwind_info_len && memcmp (cached->info, unwind_info, unwind_info_len) == 0) {
678 info = g_malloc (sizeof (MonoUnwindInfo) + unwind_info_len);
679 info->len = unwind_info_len;
680 memcpy (&info->info, unwind_info, unwind_info_len);
682 i = cached_info_next;
684 if (cached_info_next >= cached_info_size) {
685 MonoUnwindInfo **old_table, **new_table;
688 * Avoid freeing the old table so mono_get_cached_unwind_info ()
689 * doesn't need locks/hazard pointers.
692 old_table = cached_info;
693 new_table = g_new0 (MonoUnwindInfo*, cached_info_size * 2);
695 memcpy (new_table, cached_info, cached_info_size * sizeof (MonoUnwindInfo*));
697 mono_memory_barrier ();
699 cached_info = new_table;
701 cached_info_list = g_slist_prepend (cached_info_list, cached_info);
703 cached_info_size *= 2;
706 cached_info [cached_info_next ++] = info;
708 unwind_info_size += sizeof (MonoUnwindInfo) + unwind_info_len;
715 * This function is signal safe.
718 mono_get_cached_unwind_info (guint32 index, guint32 *unwind_info_len)
720 MonoUnwindInfo **table;
721 MonoUnwindInfo *info;
725 * This doesn't need any locks/hazard pointers,
726 * since new tables are copies of the old ones.
730 info = table [index];
732 *unwind_info_len = info->len;
739 * mono_unwind_get_dwarf_data_align:
741 * Return the data alignment used by the encoded unwind information.
744 mono_unwind_get_dwarf_data_align (void)
746 return DWARF_DATA_ALIGN;
750 * mono_unwind_get_dwarf_pc_reg:
752 * Return the dwarf register number of the register holding the ip of the
756 mono_unwind_get_dwarf_pc_reg (void)
762 decode_cie_op (guint8 *p, guint8 **endp)
767 case DW_CFA_advance_loc:
772 decode_uleb128 (p, &p);
779 decode_uleb128 (p, &p);
780 decode_uleb128 (p, &p);
782 case DW_CFA_def_cfa_offset:
783 decode_uleb128 (p, &p);
785 case DW_CFA_def_cfa_register:
786 decode_uleb128 (p, &p);
788 case DW_CFA_advance_loc4:
791 case DW_CFA_offset_extended_sf:
792 decode_uleb128 (p, &p);
793 decode_uleb128 (p, &p);
796 g_assert_not_reached ();
801 g_assert_not_reached ();
808 read_encoded_val (guint32 encoding, guint8 *p, guint8 **endp)
812 switch (encoding & 0xf) {
813 case DW_EH_PE_sdata8:
817 case DW_EH_PE_sdata4:
822 g_assert_not_reached ();
832 * Decode the Mono specific Language Specific Data Area generated by LLVM.
835 decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo **ex_info, guint32 *ex_info_len, gpointer **type_info, int *this_reg, int *this_offset)
838 int i, ncall_sites, this_encoding;
839 guint32 mono_magic, version;
843 /* This is the modified LSDA generated by the LLVM mono branch */
844 mono_magic = decode_uleb128 (p, &p);
845 g_assert (mono_magic == 0x4d4fef4f);
846 version = decode_uleb128 (p, &p);
847 g_assert (version == 1);
850 if (this_encoding == DW_EH_PE_udata4) {
851 gint32 op, reg, offset;
853 /* 'this' location */
855 g_assert (op == DW_OP_bregx);
857 reg = decode_uleb128 (p, &p);
858 offset = decode_sleb128 (p, &p);
860 *this_reg = mono_dwarf_reg_to_hw_reg (reg);
861 *this_offset = offset;
863 g_assert (this_encoding == DW_EH_PE_omit);
868 ncall_sites = decode_uleb128 (p, &p);
869 p = (guint8*)ALIGN_TO ((mgreg_t)p, 4);
872 *ex_info = g_malloc0 (ncall_sites * sizeof (MonoJitExceptionInfo));
873 *ex_info_len = ncall_sites;
876 *type_info = g_malloc0 (ncall_sites * sizeof (gpointer));
878 for (i = 0; i < ncall_sites; ++i) {
879 int block_start_offset, block_size, landing_pad;
882 block_start_offset = read32 (p);
883 p += sizeof (gint32);
884 block_size = read32 (p);
885 p += sizeof (gint32);
886 landing_pad = read32 (p);
887 p += sizeof (gint32);
889 p += sizeof (gint32);
891 g_assert (landing_pad);
892 g_assert (((size_t)tinfo % 4) == 0);
893 //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
897 (*type_info) [i] = tinfo;
898 (*ex_info)[i].try_start = code + block_start_offset;
899 (*ex_info)[i].try_end = code + block_start_offset + block_size;
900 (*ex_info)[i].handler_start = code + landing_pad;
906 * mono_unwind_decode_fde:
908 * Decode a DWARF FDE entry, returning the unwind opcodes.
909 * If not NULL, EX_INFO is set to a malloc-ed array of MonoJitExceptionInfo structures,
910 * only try_start, try_end and handler_start is set.
911 * If not NULL, TYPE_INFO is set to a malloc-ed array containing the ttype table from the
915 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)
917 guint8 *p, *cie, *fde_current, *fde_aug = NULL, *code, *fde_cfi, *cie_cfi;
918 gint32 fde_len, cie_offset, pc_begin, pc_range, aug_len, fde_data_len;
919 gint32 cie_len, cie_id, cie_version, code_align, data_align, return_reg;
920 gint32 i, cie_aug_len, buf_len;
923 gboolean has_fde_augmentation = FALSE;
926 * http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
936 // FIXME: Endianess ?
937 fde_len = *(guint32*)p;
938 g_assert (fde_len != 0xffffffff && fde_len != 0);
940 cie_offset = *(guint32*)p;
941 cie = p - cie_offset;
947 cie_len = *(guint32*)p;
949 cie_id = *(guint32*)p;
950 g_assert (cie_id == 0);
953 g_assert (cie_version == 1);
955 cie_aug_str = (char*)p;
956 p += strlen (cie_aug_str) + 1;
957 code_align = decode_uleb128 (p, &p);
958 data_align = decode_sleb128 (p, &p);
959 return_reg = decode_uleb128 (p, &p);
960 if (strstr (cie_aug_str, "z")) {
964 cie_aug_len = decode_uleb128 (p, &p);
966 has_fde_augmentation = TRUE;
969 for (i = 0; cie_aug_str [i] != '\0'; ++i) {
970 switch (cie_aug_str [i]) {
976 read_encoded_val (p_encoding, p, &p);
979 g_assert ((*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel)) || (*p == (DW_EH_PE_sdata8|DW_EH_PE_pcrel)));
983 g_assert (*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel));
987 g_assert_not_reached ();
997 /* Continue decoding FDE */
999 /* DW_EH_PE_sdata4|DW_EH_PE_pcrel encoding */
1000 pc_begin = *(gint32*)p;
1001 code = p + pc_begin;
1003 pc_range = *(guint32*)p;
1005 if (has_fde_augmentation) {
1006 aug_len = decode_uleb128 (p, &p);
1013 fde_data_len = fde + 4 + fde_len - p;
1016 *code_len = pc_range;
1023 /* Decode FDE augmention */
1028 /* sdata|pcrel encoding */
1030 lsda_offset = read32 (fde_aug);
1031 else if (aug_len == 8)
1032 lsda_offset = *(gint64*)fde_aug;
1034 g_assert_not_reached ();
1035 if (lsda_offset != 0) {
1036 lsda = fde_aug + lsda_offset;
1038 decode_lsda (lsda, code, ex_info, ex_info_len, type_info, this_reg, this_offset);
1042 /* Make sure the FDE uses the same constants as we do */
1043 g_assert (code_align == 1);
1044 g_assert (data_align == DWARF_DATA_ALIGN);
1045 g_assert (return_reg == DWARF_PC_REG);
1047 buf_len = (cie + cie_len + 4 - cie_cfi) + (fde + fde_len + 4 - fde_cfi);
1048 buf = g_malloc0 (buf_len);
1052 while (p < cie + cie_len + 4) {
1053 if (*p == DW_CFA_nop)
1056 decode_cie_op (p, &p);
1058 memcpy (buf + i, cie_cfi, p - cie_cfi);
1062 while (p < fde + fde_len + 4) {
1063 if (*p == DW_CFA_nop)
1066 decode_cie_op (p, &p);
1068 memcpy (buf + i, fde_cfi, p - fde_cfi);
1070 g_assert (i <= buf_len);
1074 return g_realloc (buf, i);
1078 * mono_unwind_decode_mono_fde:
1080 * Decode an FDE entry in the LLVM emitted mono EH frame.
1081 * info->ex_info is set to a malloc-ed array of MonoJitExceptionInfo structures,
1082 * only try_start, try_end and handler_start is set.
1083 * info->type_info is set to a malloc-ed array containing the ttype table from the
1087 mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8 *code, MonoLLVMFDEInfo *res)
1089 guint8 *p, *fde_aug, *cie_cfi, *fde_cfi, *buf;
1090 int has_aug, aug_len, cie_cfi_len, fde_cfi_len;
1091 gint32 code_align, data_align, return_reg, pers_encoding;
1093 memset (res, 0, sizeof (*res));
1095 res->this_offset = -1;
1097 /* fde points to data emitted by LLVM in DwarfException::EmitMonoEHFrame () */
1102 aug_len = read32 (p);
1114 /* The LSDA is embedded directly into the FDE */
1117 decode_lsda (lsda, code, &res->ex_info, &res->ex_info_len, &res->type_info, &res->this_reg, &res->this_offset);
1122 code_align = decode_uleb128 (p, &p);
1123 data_align = decode_sleb128 (p, &p);
1124 return_reg = decode_uleb128 (p, &p);
1127 if (pers_encoding != DW_EH_PE_omit)
1128 read_encoded_val (pers_encoding, p, &p);
1132 /* Make sure the FDE uses the same constants as we do */
1133 g_assert (code_align == 1);
1134 g_assert (data_align == DWARF_DATA_ALIGN);
1135 g_assert (return_reg == DWARF_PC_REG);
1137 /* Compute size of CIE unwind info it is DW_CFA_nop terminated */
1140 if (*p == DW_CFA_nop)
1143 decode_cie_op (p, &p);
1145 cie_cfi_len = p - cie_cfi;
1146 fde_cfi_len = (fde + fde_len - fde_cfi);
1148 buf = g_malloc0 (cie_cfi_len + fde_cfi_len);
1149 memcpy (buf, cie_cfi, cie_cfi_len);
1150 memcpy (buf + cie_cfi_len, fde_cfi, fde_cfi_len);
1152 res->unw_info_len = cie_cfi_len + fde_cfi_len;
1153 res->unw_info = buf;
1157 * mono_unwind_get_cie_program:
1159 * Get the unwind bytecode for the DWARF CIE.
1162 mono_unwind_get_cie_program (void)
1164 #if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_POWERPC)
1165 return mono_arch_get_cie_program ();