Apply changes from https://github.com/dotnet/runtime/commit/eb1756e97d23df13bc6fe798e...
[mono-project.git] / mono / mini / unwind.c
blob721f7f3a2d2ca2c5dce5b8808b5907583af9c3ad
1 /**
2 * \file
3 * Stack Unwinding Interface
5 * Authors:
6 * Zoltan Varga (vargaz@gmail.com)
8 * (C) 2008 Novell, Inc.
9 */
11 #include "mini.h"
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/utils/mono-logger-internals.h>
18 #include <mono/metadata/threads-types.h>
19 #include <mono/metadata/mono-endian.h>
21 typedef enum {
22 LOC_SAME,
23 LOC_OFFSET
24 } LocType;
26 typedef struct {
27 LocType loc_type;
28 int offset;
29 } Loc;
31 typedef struct {
32 guint32 len;
33 guint8 info [MONO_ZERO_LEN_ARRAY];
34 } MonoUnwindInfo;
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;
41 /* Statistics */
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)
47 #ifdef TARGET_AMD64
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)
63 /* LR */
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,
68 /* v8..v15 */
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 };
77 /* + 1 is for IP */
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 (target_mgreg_t))
88 #if _CALL_ELF == 2
89 #define DWARF_PC_REG 65
90 #else
91 #define DWARF_PC_REG 108
92 #endif
93 #define NUM_DWARF_REGS (DWARF_PC_REG + 1)
94 #elif defined (TARGET_S390X)
96 * 0-15 = GR0-15
97 * 16-31 = FP0-15
99 static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7,
100 8, 9, 10, 11, 12, 13, 14, 15,
101 16, 17, 18, 19, 20, 21, 22, 23,
102 24, 25, 26, 27, 28, 29, 30, 31};
103 #define NUM_DWARF_REGS 32
104 #define DWARF_DATA_ALIGN (-8)
105 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (14))
106 #elif defined (TARGET_MIPS)
107 /* FIXME: */
108 static int map_hw_reg_to_dwarf_reg [32] = {
109 0, 1, 2, 3, 4, 5, 6, 7,
110 8, 9, 10, 11, 12, 13, 14, 15,
111 16, 17, 18, 19, 20, 21, 22, 23,
112 24, 25, 26, 27, 28, 29, 30, 31
114 #define NUM_DWARF_REGS 32
115 #define DWARF_DATA_ALIGN (-(gint32)sizeof (target_mgreg_t))
116 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (mips_ra))
117 #elif defined(TARGET_RISCV)
120 * These values have not currently been formalized in the RISC-V psABI. See
121 * instead gcc/config/riscv/riscv.h in the GCC source tree.
124 #define NUM_DWARF_REGS (RISCV_N_GREGS + RISCV_N_FREGS)
125 #define DWARF_DATA_ALIGN (-4)
126 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (RISCV_RA))
128 static int map_hw_reg_to_dwarf_reg [NUM_DWARF_REGS] = {
129 // x0..x31
130 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
131 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
132 // f0..f31
133 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
134 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
137 #else
138 static int map_hw_reg_to_dwarf_reg [16];
139 #define NUM_DWARF_REGS 16
140 #define DWARF_DATA_ALIGN 1
141 #define DWARF_PC_REG -1
142 #endif
144 #define NUM_HW_REGS (sizeof (map_hw_reg_to_dwarf_reg) / sizeof (int))
146 #ifndef IS_DOUBLE_REG
147 #define IS_DOUBLE_REG(dwarf_reg) (dwarf_reg ? 0 : 0)
148 #endif
150 static gboolean dwarf_reg_to_hw_reg_inited;
151 static gboolean hw_reg_to_dwarf_reg_inited;
153 static int map_dwarf_reg_to_hw_reg [NUM_DWARF_REGS];
155 static void
156 init_hw_reg_map (void)
158 #ifdef TARGET_POWERPC
159 map_hw_reg_to_dwarf_reg [ppc_lr] = DWARF_PC_REG;
160 #endif
161 mono_memory_barrier ();
162 hw_reg_to_dwarf_reg_inited = TRUE;
166 * mono_hw_reg_to_dwarf_reg:
168 * Map the hardware register number REG to the register number used by DWARF.
171 mono_hw_reg_to_dwarf_reg (int reg)
173 if (!hw_reg_to_dwarf_reg_inited)
174 init_hw_reg_map ();
176 if (NUM_HW_REGS == 0) {
177 g_assert_not_reached ();
178 return -1;
181 return map_hw_reg_to_dwarf_reg [reg];
184 static void
185 init_dwarf_reg_map (void)
187 g_assert (NUM_HW_REGS > 0);
188 for (int i = 0; i < NUM_HW_REGS; ++i) {
189 map_dwarf_reg_to_hw_reg [mono_hw_reg_to_dwarf_reg (i)] = i;
192 mono_memory_barrier ();
193 dwarf_reg_to_hw_reg_inited = TRUE;
197 mono_dwarf_reg_to_hw_reg (int reg)
199 if (!dwarf_reg_to_hw_reg_inited)
200 init_dwarf_reg_map ();
202 return map_dwarf_reg_to_hw_reg [reg];
205 static G_GNUC_UNUSED void
206 encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
208 guint8 *p = buf;
210 do {
211 guint8 b = value & 0x7f;
212 value >>= 7;
213 if (value != 0) /* more bytes to come */
214 b |= 0x80;
215 *p ++ = b;
216 } while (value);
218 *endbuf = p;
221 static G_GNUC_UNUSED void
222 encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
224 gboolean more = 1;
225 gboolean negative = (value < 0);
226 guint32 size = 32;
227 guint8 byte;
228 guint8 *p = buf;
230 while (more) {
231 byte = value & 0x7f;
232 value >>= 7;
233 /* the following is unnecessary if the
234 * implementation of >>= uses an arithmetic rather
235 * than logical shift for a signed left operand
237 if (negative)
238 /* sign extend */
239 value |= - (1 <<(size - 7));
240 /* sign bit of byte is second high order bit (0x40) */
241 if ((value == 0 && !(byte & 0x40)) ||
242 (value == -1 && (byte & 0x40)))
243 more = 0;
244 else
245 byte |= 0x80;
246 *p ++= byte;
249 *endbuf = p;
252 static guint32
253 decode_uleb128 (guint8 *buf, guint8 **endbuf)
255 guint8 *p = buf;
256 guint32 res = 0;
257 int shift = 0;
259 while (TRUE) {
260 guint8 b = *p;
261 p ++;
263 res = res | (((int)(b & 0x7f)) << shift);
264 if (!(b & 0x80))
265 break;
266 shift += 7;
269 *endbuf = p;
271 return res;
274 static gint32
275 decode_sleb128 (guint8 *buf, guint8 **endbuf)
277 guint8 *p = buf;
278 gint32 res = 0;
279 int shift = 0;
281 guint8 b;
283 do {
284 b = *p;
285 p ++;
287 res = res | (((int)(b & 0x7f)) << shift);
288 shift += 7;
289 } while (b & 0x80);
291 if (shift < 32 && (b & 0x40))
292 res |= - (1 << shift);
294 *endbuf = p;
296 return res;
299 void
300 mono_print_unwind_info (guint8 *unwind_info, int unwind_info_len)
302 guint8 *p;
303 int pos, reg, offset, cfa_reg, cfa_offset;
305 p = unwind_info;
306 pos = 0;
307 while (p < unwind_info + unwind_info_len) {
308 int op = *p & 0xc0;
310 switch (op) {
311 case DW_CFA_advance_loc:
312 pos += *p & 0x3f;
313 printf ("CFA: [%x] advance loc\n",pos);
314 p ++;
315 break;
316 case DW_CFA_offset:
317 reg = *p & 0x3f;
318 p ++;
319 offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
320 if (reg == DWARF_PC_REG)
321 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, "pc", -offset);
322 else
323 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
324 break;
325 case 0: {
326 int ext_op = *p;
327 p ++;
328 switch (ext_op) {
329 case DW_CFA_def_cfa:
330 cfa_reg = decode_uleb128 (p, &p);
331 cfa_offset = decode_uleb128 (p, &p);
332 printf ("CFA: [%x] def_cfa: %s+0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)), cfa_offset);
333 break;
334 case DW_CFA_def_cfa_offset:
335 cfa_offset = decode_uleb128 (p, &p);
336 printf ("CFA: [%x] def_cfa_offset: 0x%x\n", pos, cfa_offset);
337 break;
338 case DW_CFA_def_cfa_register:
339 cfa_reg = decode_uleb128 (p, &p);
340 printf ("CFA: [%x] def_cfa_reg: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)));
341 break;
342 case DW_CFA_offset_extended_sf:
343 reg = decode_uleb128 (p, &p);
344 offset = decode_sleb128 (p, &p) * DWARF_DATA_ALIGN;
345 printf ("CFA: [%x] offset_extended_sf: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
346 break;
347 case DW_CFA_same_value:
348 reg = decode_uleb128 (p, &p);
349 printf ("CFA: [%x] same_value: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)));
350 break;
351 case DW_CFA_remember_state:
352 printf ("CFA: [%x] remember_state\n", pos);
353 break;
354 case DW_CFA_restore_state:
355 printf ("CFA: [%x] restore_state\n", pos);
356 break;
357 case DW_CFA_mono_advance_loc:
358 printf ("CFA: [%x] mono_advance_loc\n", pos);
359 break;
360 case DW_CFA_advance_loc1:
361 printf ("CFA: [%x] advance_loc1\n", pos);
362 pos += *p;
363 p += 1;
364 break;
365 case DW_CFA_advance_loc2:
366 printf ("CFA: [%x] advance_loc2\n", pos);
367 pos += read16 (p);
368 p += 2;
369 break;
370 case DW_CFA_advance_loc4:
371 printf ("CFA: [%x] advance_loc4\n", pos);
372 pos += read32 (p);
373 p += 4;
374 break;
375 default:
376 g_assert_not_reached ();
378 break;
380 default:
381 g_assert_not_reached ();
387 * mono_unwind_ops_encode_full:
389 * Encode the unwind ops in UNWIND_OPS into the compact DWARF encoding.
390 * Return a pointer to malloc'ed memory.
391 * If ENABLE_EXTENSIONS is FALSE, avoid encoding the mono extension
392 * opcode (DW_CFA_mono_advance_loc).
394 guint8*
395 mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enable_extensions)
397 MonoUnwindOp *op;
398 int loc = 0;
399 guint8 buf [4096];
400 guint8 *p, *res;
402 p = buf;
404 for (GSList *l = unwind_ops; l; l = l->next) {
405 int reg;
407 op = (MonoUnwindOp *)l->data;
409 /* Convert the register from the hw encoding to the dwarf encoding */
410 reg = mono_hw_reg_to_dwarf_reg (op->reg);
412 if (op->op == DW_CFA_mono_advance_loc) {
413 /* This advances loc to its location */
414 loc = op->when;
417 /* Emit an advance_loc if neccesary */
418 while (op->when > loc) {
419 if (op->when - loc >= 65536) {
420 *p ++ = DW_CFA_advance_loc4;
421 guint32 v = (guint32)(op->when - loc);
422 memcpy (p, &v, 4);
423 g_assert (read32 (p) == GUINT32_TO_LE((guint32)(op->when - loc)));
424 p += 4;
425 loc = op->when;
426 } else if (op->when - loc >= 256) {
427 *p ++ = DW_CFA_advance_loc2;
428 guint16 v = (guint16)(op->when - loc);
429 memcpy (p, &v, 2);
430 g_assert (read16 (p) == GUINT16_TO_LE((guint32)(op->when - loc)));
431 p += 2;
432 loc = op->when;
433 } else if (op->when - loc >= 32) {
434 *p ++ = DW_CFA_advance_loc1;
435 *(guint8*)p = (guint8)(op->when - loc);
436 p += 1;
437 loc = op->when;
438 } else if (op->when - loc < 32) {
439 *p ++ = DW_CFA_advance_loc | (op->when - loc);
440 loc = op->when;
441 } else {
442 *p ++ = DW_CFA_advance_loc | (30);
443 loc += 30;
447 switch (op->op) {
448 case DW_CFA_def_cfa:
449 *p ++ = op->op;
450 encode_uleb128 (reg, p, &p);
451 encode_uleb128 (op->val, p, &p);
452 break;
453 case DW_CFA_def_cfa_offset:
454 *p ++ = op->op;
455 encode_uleb128 (op->val, p, &p);
456 break;
457 case DW_CFA_def_cfa_register:
458 *p ++ = op->op;
459 encode_uleb128 (reg, p, &p);
460 break;
461 case DW_CFA_same_value:
462 *p ++ = op->op;
463 encode_uleb128 (reg, p, &p);
464 break;
465 case DW_CFA_offset:
466 if (reg > 63) {
467 *p ++ = DW_CFA_offset_extended_sf;
468 encode_uleb128 (reg, p, &p);
469 encode_sleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
470 } else {
471 *p ++ = DW_CFA_offset | reg;
472 encode_uleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
474 break;
475 case DW_CFA_remember_state:
476 case DW_CFA_restore_state:
477 *p ++ = op->op;
478 break;
479 case DW_CFA_mono_advance_loc:
480 if (!enable_extensions)
481 break;
482 /* Only one location is supported */
483 g_assert (op->val == 0);
484 *p ++ = op->op;
485 break;
486 #if defined(TARGET_WIN32) && defined(TARGET_AMD64)
487 case DW_CFA_mono_sp_alloc_info_win64:
488 case DW_CFA_mono_fp_alloc_info_win64:
489 // Drop Windows specific unwind op's. These op's are currently
490 // only used when registering unwind info with Windows OS unwinder.
491 break;
492 #endif
493 default:
494 g_assert_not_reached ();
495 break;
499 g_assert (p - buf < 4096);
500 *out_len = p - buf;
501 res = (guint8 *)g_malloc (p - buf);
502 memcpy (res, buf, p - buf);
503 return res;
506 guint8*
507 mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
509 return mono_unwind_ops_encode_full (unwind_ops, out_len, TRUE);
512 #if 0
513 #define UNW_DEBUG(stmt) do { stmt; } while (0)
514 #else
515 #define UNW_DEBUG(stmt) do { } while (0)
516 #endif
518 static G_GNUC_UNUSED void
519 print_dwarf_state (int cfa_reg, int cfa_offset, int ip, int nregs, Loc *locations, guint8 *reg_saved)
521 printf ("\t%x: cfa=r%d+%d ", ip, cfa_reg, cfa_offset);
523 for (int i = 0; i < nregs; ++i)
524 if (reg_saved [i] && locations [i].loc_type == LOC_OFFSET)
525 printf ("r%d@%d(cfa) ", i, locations [i].offset);
526 printf ("\n");
529 typedef struct {
530 Loc locations [NUM_HW_REGS];
531 guint8 reg_saved [NUM_HW_REGS];
532 int cfa_reg, cfa_offset;
533 } UnwindState;
536 * Given the state of the current frame as stored in REGS, execute the unwind
537 * operations in unwind_info until the location counter reaches POS. The result is
538 * stored back into REGS. OUT_CFA will receive the value of the CFA.
539 * If SAVE_LOCATIONS is non-NULL, it should point to an array of size SAVE_LOCATIONS_LEN.
540 * On return, the nth entry will point to the address of the stack slot where register
541 * N was saved, or NULL, if it was not saved by this frame.
542 * MARK_LOCATIONS should contain the locations marked by mono_emit_unwind_op_mark_loc (), if any.
543 * This function is signal safe.
545 * It returns FALSE on failure
547 gboolean
548 mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len,
549 guint8 *start_ip, guint8 *end_ip, guint8 *ip, guint8 **mark_locations,
550 mono_unwind_reg_t *regs, int nregs,
551 host_mgreg_t **save_locations, int save_locations_len,
552 guint8 **out_cfa)
554 Loc locations [NUM_HW_REGS];
555 guint8 reg_saved [NUM_HW_REGS];
556 int pos, reg, hwreg, cfa_reg = -1, cfa_offset = 0, offset;
557 guint8 *p;
558 guint8 *cfa_val;
559 UnwindState state_stack [1];
560 int state_stack_pos;
562 memset (reg_saved, 0, sizeof (reg_saved));
563 state_stack [0].cfa_reg = -1;
564 state_stack [0].cfa_offset = 0;
566 p = unwind_info;
567 pos = 0;
568 cfa_reg = -1;
569 cfa_offset = -1;
570 state_stack_pos = 0;
571 while (pos <= ip - start_ip && p < unwind_info + unwind_info_len) {
572 int op = *p & 0xc0;
574 switch (op) {
575 case DW_CFA_advance_loc:
576 UNW_DEBUG (print_dwarf_state (cfa_reg, cfa_offset, pos, nregs, locations));
577 pos += *p & 0x3f;
578 p ++;
579 break;
580 case DW_CFA_offset:
581 reg = *p & 0x3f;
582 p ++;
583 if (reg >= NUM_DWARF_REGS) {
584 /* Register we don't care about, like a caller save reg in a cold cconv */
585 decode_uleb128 (p, &p);
586 break;
588 hwreg = mono_dwarf_reg_to_hw_reg (reg);
589 reg_saved [hwreg] = TRUE;
590 locations [hwreg].loc_type = LOC_OFFSET;
591 locations [hwreg].offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
592 break;
593 case 0: {
594 int ext_op = *p;
595 p ++;
596 switch (ext_op) {
597 case DW_CFA_def_cfa:
598 cfa_reg = decode_uleb128 (p, &p);
599 cfa_offset = decode_uleb128 (p, &p);
600 break;
601 case DW_CFA_def_cfa_offset:
602 cfa_offset = decode_uleb128 (p, &p);
603 break;
604 case DW_CFA_def_cfa_register:
605 cfa_reg = decode_uleb128 (p, &p);
606 break;
607 case DW_CFA_offset_extended_sf:
608 reg = decode_uleb128 (p, &p);
609 offset = decode_sleb128 (p, &p);
610 if (reg >= NUM_DWARF_REGS)
611 break;
612 hwreg = mono_dwarf_reg_to_hw_reg (reg);
613 reg_saved [hwreg] = TRUE;
614 locations [hwreg].loc_type = LOC_OFFSET;
615 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
616 break;
617 case DW_CFA_offset_extended:
618 reg = decode_uleb128 (p, &p);
619 offset = decode_uleb128 (p, &p);
620 if (reg >= NUM_DWARF_REGS)
621 break;
622 hwreg = mono_dwarf_reg_to_hw_reg (reg);
623 reg_saved [hwreg] = TRUE;
624 locations [hwreg].loc_type = LOC_OFFSET;
625 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
626 break;
627 case DW_CFA_same_value:
628 reg = decode_uleb128 (p, &p);
629 if (reg >= NUM_DWARF_REGS)
630 break;
631 hwreg = mono_dwarf_reg_to_hw_reg (reg);
632 locations [hwreg].loc_type = LOC_SAME;
633 break;
634 case DW_CFA_advance_loc1:
635 pos += *p;
636 p += 1;
637 break;
638 case DW_CFA_advance_loc2:
639 pos += read16 (p);
640 p += 2;
641 break;
642 case DW_CFA_advance_loc4:
643 pos += read32 (p);
644 p += 4;
645 break;
646 case DW_CFA_remember_state:
647 if (state_stack_pos != 0) {
648 mono_runtime_printf_err ("Unwind failure. Assertion at %s %d\n.", __FILE__, __LINE__);
649 return FALSE;
651 memcpy (&state_stack [0].locations, &locations, sizeof (locations));
652 memcpy (&state_stack [0].reg_saved, &reg_saved, sizeof (reg_saved));
653 state_stack [0].cfa_reg = cfa_reg;
654 state_stack [0].cfa_offset = cfa_offset;
655 state_stack_pos ++;
656 break;
657 case DW_CFA_restore_state:
658 if (state_stack_pos != 1) {
659 mono_runtime_printf_err ("Unwind failure. Assertion at %s %d\n.", __FILE__, __LINE__);
660 return FALSE;
662 state_stack_pos --;
663 memcpy (&locations, &state_stack [0].locations, sizeof (locations));
664 memcpy (&reg_saved, &state_stack [0].reg_saved, sizeof (reg_saved));
665 cfa_reg = state_stack [0].cfa_reg;
666 cfa_offset = state_stack [0].cfa_offset;
667 break;
668 case DW_CFA_mono_advance_loc:
669 if (!mark_locations [0]) {
670 mono_runtime_printf_err ("Unwind failure. Assertion at %s %d\n.", __FILE__, __LINE__);
671 return FALSE;
673 pos = mark_locations [0] - start_ip;
674 break;
675 default:
676 mono_runtime_printf_err ("Unwind failure. Illegal value for switch statement, assertion at %s %d\n.", __FILE__, __LINE__);
677 return FALSE;
679 break;
681 default:
682 mono_runtime_printf_err ("Unwind failure. Illegal value for switch statement, assertion at %s %d\n.", __FILE__, __LINE__);
683 return FALSE;
687 if (save_locations)
688 memset (save_locations, 0, save_locations_len * sizeof (host_mgreg_t*));
690 if (cfa_reg == -1) {
691 mono_runtime_printf_err ("Unset cfa_reg in method %s. Memory around ip (%p):", mono_get_method_from_ip (ip), ip);
692 mono_dump_mem (ip - 0x10, 0x40);
693 return FALSE;
695 cfa_val = (guint8*)regs [mono_dwarf_reg_to_hw_reg (cfa_reg)] + cfa_offset;
696 for (hwreg = 0; hwreg < NUM_HW_REGS; ++hwreg) {
697 if (reg_saved [hwreg] && locations [hwreg].loc_type == LOC_OFFSET) {
698 int dwarfreg = mono_hw_reg_to_dwarf_reg (hwreg);
699 if (hwreg >= nregs) {
700 mono_runtime_printf_err ("Unwind failure. Assertion at %s %d\n.", __FILE__, __LINE__);
701 return FALSE;
703 if (IS_DOUBLE_REG (dwarfreg))
704 regs [hwreg] = *(guint64*)(cfa_val + locations [hwreg].offset);
705 else
706 regs [hwreg] = *(host_mgreg_t*)(cfa_val + locations [hwreg].offset);
707 if (save_locations && hwreg < save_locations_len)
708 save_locations [hwreg] = (host_mgreg_t*)(cfa_val + locations [hwreg].offset);
712 *out_cfa = cfa_val;
714 // Success
715 return TRUE;
718 void
719 mono_unwind_init (void)
721 mono_os_mutex_init_recursive (&unwind_mutex);
723 mono_counters_register ("Unwind info size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &unwind_info_size);
726 void
727 mono_unwind_cleanup (void)
729 mono_os_mutex_destroy (&unwind_mutex);
731 if (!cached_info)
732 return;
734 for (int i = 0; i < cached_info_next; ++i) {
735 MonoUnwindInfo *cached = cached_info [i];
737 g_free (cached);
739 g_free (cached_info);
741 for (GSList *cursor = cached_info_list; cursor != NULL; cursor = cursor->next)
742 g_free (cursor->data);
744 g_slist_free (cached_info_list);
748 * mono_cache_unwind_info
750 * Save UNWIND_INFO in the unwind info cache and return an id which can be passed
751 * to mono_get_cached_unwind_info to get a cached copy of the info.
752 * A copy is made of the unwind info.
753 * This function is useful for two reasons:
754 * - many methods have the same unwind info
755 * - MonoJitInfo->unwind_info is an int so it can't store the pointer to the unwind info
757 guint32
758 mono_cache_unwind_info (guint8 *unwind_info, guint32 unwind_info_len)
760 int i;
761 MonoUnwindInfo *info;
763 unwind_lock ();
765 if (cached_info == NULL) {
766 cached_info_size = 16;
767 cached_info = g_new0 (MonoUnwindInfo*, cached_info_size);
770 for (i = 0; i < cached_info_next; ++i) {
771 MonoUnwindInfo *cached = cached_info [i];
773 if (cached->len == unwind_info_len && memcmp (cached->info, unwind_info, unwind_info_len) == 0) {
774 unwind_unlock ();
775 return i;
779 info = (MonoUnwindInfo *)g_malloc (sizeof (MonoUnwindInfo) + unwind_info_len);
780 info->len = unwind_info_len;
781 memcpy (&info->info, unwind_info, unwind_info_len);
783 i = cached_info_next;
785 if (cached_info_next >= cached_info_size) {
786 MonoUnwindInfo **new_table;
789 * Avoid freeing the old table so mono_get_cached_unwind_info ()
790 * doesn't need locks/hazard pointers.
793 new_table = g_new0 (MonoUnwindInfo*, cached_info_size * 2);
795 memcpy (new_table, cached_info, cached_info_size * sizeof (MonoUnwindInfo*));
797 mono_memory_barrier ();
799 cached_info_list = g_slist_prepend (cached_info_list, cached_info);
801 cached_info = new_table;
803 cached_info_size *= 2;
806 cached_info [cached_info_next ++] = info;
808 unwind_info_size += sizeof (MonoUnwindInfo) + unwind_info_len;
810 unwind_unlock ();
811 return i;
815 * This function is signal safe.
817 guint8*
818 mono_get_cached_unwind_info (guint32 index, guint32 *unwind_info_len)
820 MonoUnwindInfo **table;
821 MonoUnwindInfo *info;
822 guint8 *data;
825 * This doesn't need any locks/hazard pointers,
826 * since new tables are copies of the old ones.
828 table = cached_info;
830 info = table [index];
832 *unwind_info_len = info->len;
833 data = info->info;
835 return data;
839 * mono_unwind_get_dwarf_data_align:
841 * Return the data alignment used by the encoded unwind information.
844 mono_unwind_get_dwarf_data_align (void)
846 return DWARF_DATA_ALIGN;
850 * mono_unwind_get_dwarf_pc_reg:
852 * Return the dwarf register number of the register holding the ip of the
853 * previous frame.
856 mono_unwind_get_dwarf_pc_reg (void)
858 return DWARF_PC_REG;
861 static void
862 decode_cie_op (guint8 *p, guint8 **endp)
864 int op = *p & 0xc0;
866 switch (op) {
867 case DW_CFA_advance_loc:
868 p ++;
869 break;
870 case DW_CFA_offset:
871 p ++;
872 decode_uleb128 (p, &p);
873 break;
874 case 0: {
875 int ext_op = *p;
876 p ++;
877 switch (ext_op) {
878 case DW_CFA_def_cfa:
879 decode_uleb128 (p, &p);
880 decode_uleb128 (p, &p);
881 break;
882 case DW_CFA_def_cfa_offset:
883 decode_uleb128 (p, &p);
884 break;
885 case DW_CFA_def_cfa_register:
886 decode_uleb128 (p, &p);
887 break;
888 case DW_CFA_advance_loc4:
889 p += 4;
890 break;
891 case DW_CFA_offset_extended_sf:
892 decode_uleb128 (p, &p);
893 decode_uleb128 (p, &p);
894 break;
895 default:
896 g_assert_not_reached ();
898 break;
900 default:
901 g_assert_not_reached ();
904 *endp = p;
907 static gint64
908 read_encoded_val (guint32 encoding, guint8 *p, guint8 **endp)
910 gint64 res;
912 switch (encoding & 0xf) {
913 case DW_EH_PE_sdata8:
914 res = *(gint64*)p;
915 p += 8;
916 break;
917 case DW_EH_PE_sdata4:
918 res = *(gint32*)p;
919 p += 4;
920 break;
921 default:
922 g_assert_not_reached ();
925 *endp = p;
926 return res;
930 * decode_lsda:
932 * Decode the Mono specific Language Specific Data Area generated by LLVM.
933 * This function is async safe.
935 static void
936 decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo *ex_info, gpointer *type_info, guint32 *ex_info_len, int *this_reg, int *this_offset)
938 guint8 *p;
939 int ncall_sites, this_encoding;
940 guint32 mono_magic, version;
942 p = lsda;
944 /* This is the modified LSDA generated by the LLVM mono branch */
945 mono_magic = decode_uleb128 (p, &p);
946 g_assert (mono_magic == 0x4d4fef4f);
947 version = decode_uleb128 (p, &p);
948 g_assert (version == 1);
949 this_encoding = *p;
950 p ++;
951 if (this_encoding == DW_EH_PE_udata4) {
952 gint32 op, reg, offset;
954 /* 'this' location */
955 op = *p;
956 g_assert (op == DW_OP_bregx);
957 p ++;
958 reg = decode_uleb128 (p, &p);
959 offset = decode_sleb128 (p, &p);
961 *this_reg = mono_dwarf_reg_to_hw_reg (reg);
962 *this_offset = offset;
963 } else {
964 g_assert (this_encoding == DW_EH_PE_omit);
966 *this_reg = -1;
967 *this_offset = -1;
969 ncall_sites = decode_uleb128 (p, &p);
970 p = (guint8*)ALIGN_TO ((gsize)p, 4);
972 if (ex_info_len)
973 *ex_info_len = ncall_sites;
975 for (int i = 0; i < ncall_sites; ++i) {
976 int block_start_offset, block_size, landing_pad;
977 guint8 *tinfo;
979 block_start_offset = read32 (p);
980 p += sizeof (gint32);
981 block_size = read32 (p);
982 p += sizeof (gint32);
983 landing_pad = read32 (p);
984 p += sizeof (gint32);
985 tinfo = p;
986 p += sizeof (gint32);
988 g_assert (landing_pad);
989 g_assert (((size_t)tinfo % 4) == 0);
990 //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
992 if (ex_info) {
993 if (type_info)
994 type_info [i] = tinfo;
995 ex_info[i].try_start = code + block_start_offset;
996 ex_info[i].try_end = code + block_start_offset + block_size;
997 ex_info[i].handler_start = code + landing_pad;
1003 * mono_unwind_decode_fde:
1005 * Decode a DWARF FDE entry, returning the unwind opcodes.
1006 * If not NULL, EX_INFO is set to a malloc-ed array of MonoJitExceptionInfo structures,
1007 * only try_start, try_end and handler_start is set.
1008 * If not NULL, TYPE_INFO is set to a malloc-ed array containing the ttype table from the
1009 * LSDA.
1011 guint8*
1012 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)
1014 guint8 *p, *cie, *fde_current, *fde_aug = NULL, *code, *fde_cfi, *cie_cfi;
1015 gint32 fde_len, cie_offset, pc_begin, pc_range, aug_len;
1016 gint32 cie_len, cie_id, cie_version, code_align, data_align, return_reg;
1017 gint32 i, cie_aug_len, buf_len;
1018 char *cie_aug_str;
1019 guint8 *buf;
1020 gboolean has_fde_augmentation = FALSE;
1023 * http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
1026 /* This is generated by JITDwarfEmitter::EmitEHFrame () */
1028 *type_info = NULL;
1029 *this_reg = -1;
1030 *this_offset = -1;
1032 /* Decode FDE */
1034 p = fde;
1035 // FIXME: Endianess ?
1036 fde_len = *(guint32*)p;
1037 g_assert (fde_len != 0xffffffff && fde_len != 0);
1038 p += 4;
1039 cie_offset = *(guint32*)p;
1040 cie = p - cie_offset;
1041 p += 4;
1042 fde_current = p;
1044 /* Decode CIE */
1045 p = cie;
1046 cie_len = *(guint32*)p;
1047 p += 4;
1048 cie_id = *(guint32*)p;
1049 g_assert (cie_id == 0);
1050 p += 4;
1051 cie_version = *p;
1052 g_assert (cie_version == 1);
1053 p += 1;
1054 cie_aug_str = (char*)p;
1055 p += strlen (cie_aug_str) + 1;
1056 code_align = decode_uleb128 (p, &p);
1057 data_align = decode_sleb128 (p, &p);
1058 return_reg = decode_uleb128 (p, &p);
1059 if (strstr (cie_aug_str, "z")) {
1060 guint8 *cie_aug;
1061 guint32 p_encoding;
1063 cie_aug_len = decode_uleb128 (p, &p);
1065 has_fde_augmentation = TRUE;
1067 cie_aug = p;
1068 for (i = 0; cie_aug_str [i] != '\0'; ++i) {
1069 switch (cie_aug_str [i]) {
1070 case 'z':
1071 break;
1072 case 'P':
1073 p_encoding = *p;
1074 p ++;
1075 read_encoded_val (p_encoding, p, &p);
1076 break;
1077 case 'L':
1078 g_assert ((*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel)) || (*p == (DW_EH_PE_sdata8|DW_EH_PE_pcrel)));
1079 p ++;
1080 break;
1081 case 'R':
1082 g_assert (*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel));
1083 p ++;
1084 break;
1085 default:
1086 g_assert_not_reached ();
1087 break;
1091 p = cie_aug;
1092 p += cie_aug_len;
1094 cie_cfi = p;
1096 /* Continue decoding FDE */
1097 p = fde_current;
1098 /* DW_EH_PE_sdata4|DW_EH_PE_pcrel encoding */
1099 pc_begin = *(gint32*)p;
1100 code = p + pc_begin;
1101 p += 4;
1102 pc_range = *(guint32*)p;
1103 p += 4;
1104 if (has_fde_augmentation) {
1105 aug_len = decode_uleb128 (p, &p);
1106 fde_aug = p;
1107 p += aug_len;
1108 } else {
1109 aug_len = 0;
1111 fde_cfi = p;
1113 if (code_len)
1114 *code_len = pc_range;
1116 if (ex_info) {
1117 *ex_info = NULL;
1118 *ex_info_len = 0;
1121 /* Decode FDE augmention */
1122 if (aug_len) {
1123 gint32 lsda_offset;
1124 guint8 *lsda;
1126 /* sdata|pcrel encoding */
1127 if (aug_len == 4)
1128 lsda_offset = read32 (fde_aug);
1129 else if (aug_len == 8)
1130 lsda_offset = *(gint64*)fde_aug;
1131 else
1132 g_assert_not_reached ();
1133 if (lsda_offset != 0) {
1134 lsda = fde_aug + lsda_offset;
1136 /* Get the lengths first */
1137 guint32 len;
1138 decode_lsda (lsda, code, NULL, NULL, &len, this_reg, this_offset);
1140 if (ex_info)
1141 *ex_info = (MonoJitExceptionInfo *)g_malloc0 (len * sizeof (MonoJitExceptionInfo));
1142 if (type_info)
1143 *type_info = (gpointer *)g_malloc0 (len * sizeof (gpointer));
1145 decode_lsda (lsda, code, ex_info ? *ex_info : NULL, type_info ? *type_info : NULL, ex_info_len, this_reg, this_offset);
1149 /* Make sure the FDE uses the same constants as we do */
1150 g_assert (code_align == 1);
1151 g_assert (data_align == DWARF_DATA_ALIGN);
1152 g_assert (return_reg == DWARF_PC_REG);
1154 buf_len = (cie + cie_len + 4 - cie_cfi) + (fde + fde_len + 4 - fde_cfi);
1155 buf = (guint8 *)g_malloc0 (buf_len);
1157 i = 0;
1158 p = cie_cfi;
1159 while (p < cie + cie_len + 4) {
1160 if (*p == DW_CFA_nop)
1161 break;
1162 decode_cie_op (p, &p);
1164 memcpy (buf + i, cie_cfi, p - cie_cfi);
1165 i += p - cie_cfi;
1167 p = fde_cfi;
1168 while (p < fde + fde_len + 4) {
1169 if (*p == DW_CFA_nop)
1170 break;
1171 decode_cie_op (p, &p);
1173 memcpy (buf + i, fde_cfi, p - fde_cfi);
1174 i += p - fde_cfi;
1175 g_assert (i <= buf_len);
1177 *out_len = i;
1179 return (guint8 *)g_realloc (buf, i);
1183 * mono_unwind_decode_mono_fde:
1185 * Decode an FDE entry in the LLVM emitted mono EH frame.
1186 * If EI/TYPE_INFO/UNW_INFO are NULL, compute only the value of the scalar fields in INFO.
1187 * Otherwise:
1188 * - Fill out EX_INFO with try_start, try_end and handler_start.
1189 * - Fill out TYPE_INFO with the ttype table from the LSDA.
1190 * - Fill out UNW_INFO with the unwind info.
1191 * This function is async safe.
1193 void
1194 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)
1196 guint8 *p, *fde_aug, *cie_cfi, *fde_cfi, *buf;
1197 int has_aug, aug_len, cie_cfi_len, fde_cfi_len;
1198 gint32 code_align, data_align, return_reg, pers_encoding;
1200 memset (res, 0, sizeof (*res));
1201 res->this_reg = -1;
1202 res->this_offset = -1;
1204 /* fde points to data emitted by LLVM in DwarfMonoException::EmitMonoEHFrame () */
1205 p = fde;
1206 has_aug = *p;
1207 p ++;
1208 if (has_aug) {
1209 aug_len = read32 (p);
1210 p += 4;
1211 } else {
1212 aug_len = 0;
1214 fde_aug = p;
1215 p += aug_len;
1216 fde_cfi = p;
1218 if (has_aug) {
1219 guint8 *lsda;
1221 /* The LSDA is embedded directly into the FDE */
1222 lsda = fde_aug;
1224 /* Get the lengths first */
1225 decode_lsda (lsda, code, NULL, NULL, &res->ex_info_len, &res->this_reg, &res->this_offset);
1227 decode_lsda (lsda, code, ex_info, type_info, NULL, &res->this_reg, &res->this_offset);
1230 /* Decode CIE */
1231 p = cie;
1232 code_align = decode_uleb128 (p, &p);
1233 data_align = decode_sleb128 (p, &p);
1234 return_reg = decode_uleb128 (p, &p);
1235 pers_encoding = *p;
1236 p ++;
1237 if (pers_encoding != DW_EH_PE_omit)
1238 read_encoded_val (pers_encoding, p, &p);
1240 cie_cfi = p;
1242 /* Make sure the FDE uses the same constants as we do */
1243 g_assert (code_align == 1);
1244 g_assert (data_align == DWARF_DATA_ALIGN);
1245 g_assert (return_reg == DWARF_PC_REG);
1247 /* Compute size of CIE unwind info it is DW_CFA_nop terminated */
1248 p = cie_cfi;
1249 while (*p != DW_CFA_nop) {
1250 decode_cie_op (p, &p);
1252 cie_cfi_len = p - cie_cfi;
1253 fde_cfi_len = (fde + fde_len - fde_cfi);
1255 buf = unw_info;
1256 if (buf) {
1257 memcpy (buf, cie_cfi, cie_cfi_len);
1258 memcpy (buf + cie_cfi_len, fde_cfi, fde_cfi_len);
1261 res->unw_info_len = cie_cfi_len + fde_cfi_len;
1265 * mono_unwind_get_cie_program:
1267 * Get the unwind bytecode for the DWARF CIE.
1269 GSList*
1270 mono_unwind_get_cie_program (void)
1272 #if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_POWERPC) || defined(TARGET_ARM)
1273 return mono_arch_get_cie_program ();
1274 #else
1275 return NULL;
1276 #endif