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 **new_table;
688 * Avoid freeing the old table so mono_get_cached_unwind_info ()
689 * doesn't need locks/hazard pointers.
692 new_table = g_new0 (MonoUnwindInfo*, cached_info_size * 2);
694 memcpy (new_table, cached_info, cached_info_size * sizeof (MonoUnwindInfo*));
696 mono_memory_barrier ();
698 cached_info = new_table;
700 cached_info_list = g_slist_prepend (cached_info_list, cached_info);
702 cached_info_size *= 2;
705 cached_info [cached_info_next ++] = info;
707 unwind_info_size += sizeof (MonoUnwindInfo) + unwind_info_len;
714 * This function is signal safe.
717 mono_get_cached_unwind_info (guint32 index, guint32 *unwind_info_len)
719 MonoUnwindInfo **table;
720 MonoUnwindInfo *info;
724 * This doesn't need any locks/hazard pointers,
725 * since new tables are copies of the old ones.
729 info = table [index];
731 *unwind_info_len = info->len;
738 * mono_unwind_get_dwarf_data_align:
740 * Return the data alignment used by the encoded unwind information.
743 mono_unwind_get_dwarf_data_align (void)
745 return DWARF_DATA_ALIGN;
749 * mono_unwind_get_dwarf_pc_reg:
751 * Return the dwarf register number of the register holding the ip of the
755 mono_unwind_get_dwarf_pc_reg (void)
761 decode_cie_op (guint8 *p, guint8 **endp)
766 case DW_CFA_advance_loc:
771 decode_uleb128 (p, &p);
778 decode_uleb128 (p, &p);
779 decode_uleb128 (p, &p);
781 case DW_CFA_def_cfa_offset:
782 decode_uleb128 (p, &p);
784 case DW_CFA_def_cfa_register:
785 decode_uleb128 (p, &p);
787 case DW_CFA_advance_loc4:
790 case DW_CFA_offset_extended_sf:
791 decode_uleb128 (p, &p);
792 decode_uleb128 (p, &p);
795 g_assert_not_reached ();
800 g_assert_not_reached ();
807 read_encoded_val (guint32 encoding, guint8 *p, guint8 **endp)
811 switch (encoding & 0xf) {
812 case DW_EH_PE_sdata8:
816 case DW_EH_PE_sdata4:
821 g_assert_not_reached ();
831 * Decode the Mono specific Language Specific Data Area generated by LLVM.
834 decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo **ex_info, guint32 *ex_info_len, gpointer **type_info, int *this_reg, int *this_offset)
837 int i, ncall_sites, this_encoding;
838 guint32 mono_magic, version;
842 /* This is the modified LSDA generated by the LLVM mono branch */
843 mono_magic = decode_uleb128 (p, &p);
844 g_assert (mono_magic == 0x4d4fef4f);
845 version = decode_uleb128 (p, &p);
846 g_assert (version == 1);
849 if (this_encoding == DW_EH_PE_udata4) {
850 gint32 op, reg, offset;
852 /* 'this' location */
854 g_assert (op == DW_OP_bregx);
856 reg = decode_uleb128 (p, &p);
857 offset = decode_sleb128 (p, &p);
859 *this_reg = mono_dwarf_reg_to_hw_reg (reg);
860 *this_offset = offset;
862 g_assert (this_encoding == DW_EH_PE_omit);
867 ncall_sites = decode_uleb128 (p, &p);
868 p = (guint8*)ALIGN_TO ((mgreg_t)p, 4);
871 *ex_info = g_malloc0 (ncall_sites * sizeof (MonoJitExceptionInfo));
872 *ex_info_len = ncall_sites;
875 *type_info = g_malloc0 (ncall_sites * sizeof (gpointer));
877 for (i = 0; i < ncall_sites; ++i) {
878 int block_start_offset, block_size, landing_pad;
881 block_start_offset = read32 (p);
882 p += sizeof (gint32);
883 block_size = read32 (p);
884 p += sizeof (gint32);
885 landing_pad = read32 (p);
886 p += sizeof (gint32);
888 p += sizeof (gint32);
890 g_assert (landing_pad);
891 g_assert (((size_t)tinfo % 4) == 0);
892 //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
896 (*type_info) [i] = tinfo;
897 (*ex_info)[i].try_start = code + block_start_offset;
898 (*ex_info)[i].try_end = code + block_start_offset + block_size;
899 (*ex_info)[i].handler_start = code + landing_pad;
905 * mono_unwind_decode_fde:
907 * Decode a DWARF FDE entry, returning the unwind opcodes.
908 * If not NULL, EX_INFO is set to a malloc-ed array of MonoJitExceptionInfo structures,
909 * only try_start, try_end and handler_start is set.
910 * If not NULL, TYPE_INFO is set to a malloc-ed array containing the ttype table from the
914 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)
916 guint8 *p, *cie, *fde_current, *fde_aug = NULL, *code, *fde_cfi, *cie_cfi;
917 gint32 fde_len, cie_offset, pc_begin, pc_range, aug_len;
918 gint32 cie_len, cie_id, cie_version, code_align, data_align, return_reg;
919 gint32 i, cie_aug_len, buf_len;
922 gboolean has_fde_augmentation = FALSE;
925 * http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
928 /* This is generated by JITDwarfEmitter::EmitEHFrame () */
937 // FIXME: Endianess ?
938 fde_len = *(guint32*)p;
939 g_assert (fde_len != 0xffffffff && fde_len != 0);
941 cie_offset = *(guint32*)p;
942 cie = p - cie_offset;
948 cie_len = *(guint32*)p;
950 cie_id = *(guint32*)p;
951 g_assert (cie_id == 0);
954 g_assert (cie_version == 1);
956 cie_aug_str = (char*)p;
957 p += strlen (cie_aug_str) + 1;
958 code_align = decode_uleb128 (p, &p);
959 data_align = decode_sleb128 (p, &p);
960 return_reg = decode_uleb128 (p, &p);
961 if (strstr (cie_aug_str, "z")) {
965 cie_aug_len = decode_uleb128 (p, &p);
967 has_fde_augmentation = TRUE;
970 for (i = 0; cie_aug_str [i] != '\0'; ++i) {
971 switch (cie_aug_str [i]) {
977 read_encoded_val (p_encoding, p, &p);
980 g_assert ((*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel)) || (*p == (DW_EH_PE_sdata8|DW_EH_PE_pcrel)));
984 g_assert (*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel));
988 g_assert_not_reached ();
998 /* Continue decoding FDE */
1000 /* DW_EH_PE_sdata4|DW_EH_PE_pcrel encoding */
1001 pc_begin = *(gint32*)p;
1002 code = p + pc_begin;
1004 pc_range = *(guint32*)p;
1006 if (has_fde_augmentation) {
1007 aug_len = decode_uleb128 (p, &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 DwarfMonoException::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 ();