[interp] Remove varargs from InterpFrame and recompute it instead (#16598)
[mono-project.git] / mono / mini / unwind.c
blob34f35daea830c507eea768e3b58245f51bdf3662
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;
179 } else {
180 return map_hw_reg_to_dwarf_reg [reg];
184 static void
185 init_dwarf_reg_map (void)
187 int i;
189 g_assert (NUM_HW_REGS > 0);
190 for (i = 0; i < NUM_HW_REGS; ++i) {
191 map_dwarf_reg_to_hw_reg [mono_hw_reg_to_dwarf_reg (i)] = i;
194 mono_memory_barrier ();
195 dwarf_reg_to_hw_reg_inited = TRUE;
199 mono_dwarf_reg_to_hw_reg (int reg)
201 if (!dwarf_reg_to_hw_reg_inited)
202 init_dwarf_reg_map ();
204 return map_dwarf_reg_to_hw_reg [reg];
207 static G_GNUC_UNUSED void
208 encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
210 guint8 *p = buf;
212 do {
213 guint8 b = value & 0x7f;
214 value >>= 7;
215 if (value != 0) /* more bytes to come */
216 b |= 0x80;
217 *p ++ = b;
218 } while (value);
220 *endbuf = p;
223 static G_GNUC_UNUSED void
224 encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
226 gboolean more = 1;
227 gboolean negative = (value < 0);
228 guint32 size = 32;
229 guint8 byte;
230 guint8 *p = buf;
232 while (more) {
233 byte = value & 0x7f;
234 value >>= 7;
235 /* the following is unnecessary if the
236 * implementation of >>= uses an arithmetic rather
237 * than logical shift for a signed left operand
239 if (negative)
240 /* sign extend */
241 value |= - (1 <<(size - 7));
242 /* sign bit of byte is second high order bit (0x40) */
243 if ((value == 0 && !(byte & 0x40)) ||
244 (value == -1 && (byte & 0x40)))
245 more = 0;
246 else
247 byte |= 0x80;
248 *p ++= byte;
251 *endbuf = p;
254 static guint32
255 decode_uleb128 (guint8 *buf, guint8 **endbuf)
257 guint8 *p = buf;
258 guint32 res = 0;
259 int shift = 0;
261 while (TRUE) {
262 guint8 b = *p;
263 p ++;
265 res = res | (((int)(b & 0x7f)) << shift);
266 if (!(b & 0x80))
267 break;
268 shift += 7;
271 *endbuf = p;
273 return res;
276 static gint32
277 decode_sleb128 (guint8 *buf, guint8 **endbuf)
279 guint8 *p = buf;
280 gint32 res = 0;
281 int shift = 0;
283 while (TRUE) {
284 guint8 b = *p;
285 p ++;
287 res = res | (((int)(b & 0x7f)) << shift);
288 shift += 7;
289 if (!(b & 0x80)) {
290 if (shift < 32 && (b & 0x40))
291 res |= - (1 << shift);
292 break;
296 *endbuf = p;
298 return res;
301 void
302 mono_print_unwind_info (guint8 *unwind_info, int unwind_info_len)
304 guint8 *p;
305 int pos, reg, offset, cfa_reg, cfa_offset;
307 p = unwind_info;
308 pos = 0;
309 while (p < unwind_info + unwind_info_len) {
310 int op = *p & 0xc0;
312 switch (op) {
313 case DW_CFA_advance_loc:
314 pos += *p & 0x3f;
315 p ++;
316 break;
317 case DW_CFA_offset:
318 reg = *p & 0x3f;
319 p ++;
320 offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
321 if (reg == DWARF_PC_REG)
322 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, "pc", -offset);
323 else
324 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
325 break;
326 case 0: {
327 int ext_op = *p;
328 p ++;
329 switch (ext_op) {
330 case DW_CFA_def_cfa:
331 cfa_reg = decode_uleb128 (p, &p);
332 cfa_offset = decode_uleb128 (p, &p);
333 printf ("CFA: [%x] def_cfa: %s+0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)), cfa_offset);
334 break;
335 case DW_CFA_def_cfa_offset:
336 cfa_offset = decode_uleb128 (p, &p);
337 printf ("CFA: [%x] def_cfa_offset: 0x%x\n", pos, cfa_offset);
338 break;
339 case DW_CFA_def_cfa_register:
340 cfa_reg = decode_uleb128 (p, &p);
341 printf ("CFA: [%x] def_cfa_reg: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)));
342 break;
343 case DW_CFA_offset_extended_sf:
344 reg = decode_uleb128 (p, &p);
345 offset = decode_sleb128 (p, &p) * DWARF_DATA_ALIGN;
346 printf ("CFA: [%x] offset_extended_sf: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
347 break;
348 case DW_CFA_same_value:
349 reg = decode_uleb128 (p, &p);
350 printf ("CFA: [%x] same_value: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)));
351 break;
352 case DW_CFA_remember_state:
353 printf ("CFA: [%x] remember_state\n", pos);
354 break;
355 case DW_CFA_restore_state:
356 printf ("CFA: [%x] restore_state\n", pos);
357 break;
358 case DW_CFA_mono_advance_loc:
359 printf ("CFA: [%x] mono_advance_loc\n", pos);
360 break;
361 case DW_CFA_advance_loc1:
362 printf ("CFA: [%x] advance_loc1\n", pos);
363 pos += *p;
364 p += 1;
365 break;
366 case DW_CFA_advance_loc2:
367 printf ("CFA: [%x] advance_loc2\n", pos);
368 pos += read16 (p);
369 p += 2;
370 break;
371 case DW_CFA_advance_loc4:
372 printf ("CFA: [%x] advance_loc4\n", pos);
373 pos += read32 (p);
374 p += 4;
375 break;
376 default:
377 g_assert_not_reached ();
379 break;
381 default:
382 g_assert_not_reached ();
388 * mono_unwind_ops_encode_full:
390 * Encode the unwind ops in UNWIND_OPS into the compact DWARF encoding.
391 * Return a pointer to malloc'ed memory.
392 * If ENABLE_EXTENSIONS is FALSE, avoid encoding the mono extension
393 * opcode (DW_CFA_mono_advance_loc).
395 guint8*
396 mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enable_extensions)
398 GSList *l;
399 MonoUnwindOp *op;
400 int loc;
401 guint8 buf [4096];
402 guint8 *p, *res;
404 p = buf;
406 loc = 0;
407 l = unwind_ops;
408 for (; l; l = l->next) {
409 int reg;
411 op = (MonoUnwindOp *)l->data;
413 /* Convert the register from the hw encoding to the dwarf encoding */
414 reg = mono_hw_reg_to_dwarf_reg (op->reg);
416 if (op->op == DW_CFA_mono_advance_loc) {
417 /* This advances loc to its location */
418 loc = op->when;
421 /* Emit an advance_loc if neccesary */
422 while (op->when > loc) {
423 if (op->when - loc >= 65536) {
424 *p ++ = DW_CFA_advance_loc4;
425 guint32 v = (guint32)(op->when - loc);
426 memcpy (p, &v, 4);
427 g_assert (read32 (p) == (guint32)(op->when - loc));
428 p += 4;
429 loc = op->when;
430 } else if (op->when - loc >= 256) {
431 *p ++ = DW_CFA_advance_loc2;
432 guint16 v = (guint16)(op->when - loc);
433 memcpy (p, &v, 2);
434 g_assert (read16 (p) == (guint32)(op->when - loc));
435 p += 2;
436 loc = op->when;
437 } else if (op->when - loc >= 32) {
438 *p ++ = DW_CFA_advance_loc1;
439 *(guint8*)p = (guint8)(op->when - loc);
440 p += 1;
441 loc = op->when;
442 } else if (op->when - loc < 32) {
443 *p ++ = DW_CFA_advance_loc | (op->when - loc);
444 loc = op->when;
445 } else {
446 *p ++ = DW_CFA_advance_loc | (30);
447 loc += 30;
451 switch (op->op) {
452 case DW_CFA_def_cfa:
453 *p ++ = op->op;
454 encode_uleb128 (reg, p, &p);
455 encode_uleb128 (op->val, p, &p);
456 break;
457 case DW_CFA_def_cfa_offset:
458 *p ++ = op->op;
459 encode_uleb128 (op->val, p, &p);
460 break;
461 case DW_CFA_def_cfa_register:
462 *p ++ = op->op;
463 encode_uleb128 (reg, p, &p);
464 break;
465 case DW_CFA_same_value:
466 *p ++ = op->op;
467 encode_uleb128 (reg, p, &p);
468 break;
469 case DW_CFA_offset:
470 if (reg > 63) {
471 *p ++ = DW_CFA_offset_extended_sf;
472 encode_uleb128 (reg, p, &p);
473 encode_sleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
474 } else {
475 *p ++ = DW_CFA_offset | reg;
476 encode_uleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
478 break;
479 case DW_CFA_remember_state:
480 case DW_CFA_restore_state:
481 *p ++ = op->op;
482 break;
483 case DW_CFA_mono_advance_loc:
484 if (!enable_extensions)
485 break;
486 /* Only one location is supported */
487 g_assert (op->val == 0);
488 *p ++ = op->op;
489 break;
490 #if defined(TARGET_WIN32) && defined(TARGET_AMD64)
491 case DW_CFA_mono_sp_alloc_info_win64:
492 case DW_CFA_mono_fp_alloc_info_win64:
493 // Drop Windows specific unwind op's. These op's are currently
494 // only used when registering unwind info with Windows OS unwinder.
495 break;
496 #endif
497 default:
498 g_assert_not_reached ();
499 break;
503 g_assert (p - buf < 4096);
504 *out_len = p - buf;
505 res = (guint8 *)g_malloc (p - buf);
506 memcpy (res, buf, p - buf);
507 return res;
510 guint8*
511 mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
513 return mono_unwind_ops_encode_full (unwind_ops, out_len, TRUE);
516 #if 0
517 #define UNW_DEBUG(stmt) do { stmt; } while (0)
518 #else
519 #define UNW_DEBUG(stmt) do { } while (0)
520 #endif
522 static G_GNUC_UNUSED void
523 print_dwarf_state (int cfa_reg, int cfa_offset, int ip, int nregs, Loc *locations, guint8 *reg_saved)
525 int i;
527 printf ("\t%x: cfa=r%d+%d ", ip, cfa_reg, cfa_offset);
529 for (i = 0; i < nregs; ++i)
530 if (reg_saved [i] && locations [i].loc_type == LOC_OFFSET)
531 printf ("r%d@%d(cfa) ", i, locations [i].offset);
532 printf ("\n");
535 typedef struct {
536 Loc locations [NUM_HW_REGS];
537 guint8 reg_saved [NUM_HW_REGS];
538 int cfa_reg, cfa_offset;
539 } UnwindState;
542 * Given the state of the current frame as stored in REGS, execute the unwind
543 * operations in unwind_info until the location counter reaches POS. The result is
544 * stored back into REGS. OUT_CFA will receive the value of the CFA.
545 * If SAVE_LOCATIONS is non-NULL, it should point to an array of size SAVE_LOCATIONS_LEN.
546 * On return, the nth entry will point to the address of the stack slot where register
547 * N was saved, or NULL, if it was not saved by this frame.
548 * MARK_LOCATIONS should contain the locations marked by mono_emit_unwind_op_mark_loc (), if any.
549 * This function is signal safe.
551 * It returns FALSE on failure
553 gboolean
554 mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len,
555 guint8 *start_ip, guint8 *end_ip, guint8 *ip, guint8 **mark_locations,
556 mono_unwind_reg_t *regs, int nregs,
557 host_mgreg_t **save_locations, int save_locations_len,
558 guint8 **out_cfa)
560 Loc locations [NUM_HW_REGS];
561 guint8 reg_saved [NUM_HW_REGS];
562 int pos, reg, hwreg, cfa_reg = -1, cfa_offset = 0, offset;
563 guint8 *p;
564 guint8 *cfa_val;
565 UnwindState state_stack [1];
566 int state_stack_pos;
568 memset (reg_saved, 0, sizeof (reg_saved));
569 state_stack [0].cfa_reg = -1;
570 state_stack [0].cfa_offset = 0;
572 p = unwind_info;
573 pos = 0;
574 cfa_reg = -1;
575 cfa_offset = -1;
576 state_stack_pos = 0;
577 while (pos <= ip - start_ip && p < unwind_info + unwind_info_len) {
578 int op = *p & 0xc0;
580 switch (op) {
581 case DW_CFA_advance_loc:
582 UNW_DEBUG (print_dwarf_state (cfa_reg, cfa_offset, pos, nregs, locations));
583 pos += *p & 0x3f;
584 p ++;
585 break;
586 case DW_CFA_offset:
587 reg = *p & 0x3f;
588 p ++;
589 if (reg >= NUM_DWARF_REGS) {
590 /* Register we don't care about, like a caller save reg in a cold cconv */
591 decode_uleb128 (p, &p);
592 break;
594 hwreg = mono_dwarf_reg_to_hw_reg (reg);
595 reg_saved [hwreg] = TRUE;
596 locations [hwreg].loc_type = LOC_OFFSET;
597 locations [hwreg].offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
598 break;
599 case 0: {
600 int ext_op = *p;
601 p ++;
602 switch (ext_op) {
603 case DW_CFA_def_cfa:
604 cfa_reg = decode_uleb128 (p, &p);
605 cfa_offset = decode_uleb128 (p, &p);
606 break;
607 case DW_CFA_def_cfa_offset:
608 cfa_offset = decode_uleb128 (p, &p);
609 break;
610 case DW_CFA_def_cfa_register:
611 cfa_reg = decode_uleb128 (p, &p);
612 break;
613 case DW_CFA_offset_extended_sf:
614 reg = decode_uleb128 (p, &p);
615 offset = decode_sleb128 (p, &p);
616 if (reg >= NUM_DWARF_REGS)
617 break;
618 hwreg = mono_dwarf_reg_to_hw_reg (reg);
619 reg_saved [hwreg] = TRUE;
620 locations [hwreg].loc_type = LOC_OFFSET;
621 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
622 break;
623 case DW_CFA_offset_extended:
624 reg = decode_uleb128 (p, &p);
625 offset = decode_uleb128 (p, &p);
626 if (reg >= NUM_DWARF_REGS)
627 break;
628 hwreg = mono_dwarf_reg_to_hw_reg (reg);
629 reg_saved [hwreg] = TRUE;
630 locations [hwreg].loc_type = LOC_OFFSET;
631 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
632 break;
633 case DW_CFA_same_value:
634 reg = decode_uleb128 (p, &p);
635 if (reg >= NUM_DWARF_REGS)
636 break;
637 hwreg = mono_dwarf_reg_to_hw_reg (reg);
638 locations [hwreg].loc_type = LOC_SAME;
639 break;
640 case DW_CFA_advance_loc1:
641 pos += *p;
642 p += 1;
643 break;
644 case DW_CFA_advance_loc2:
645 pos += read16 (p);
646 p += 2;
647 break;
648 case DW_CFA_advance_loc4:
649 pos += read32 (p);
650 p += 4;
651 break;
652 case DW_CFA_remember_state:
653 if (state_stack_pos != 0) {
654 mono_runtime_printf_err ("Unwind failure. Assertion at %s %d\n.", __FILE__, __LINE__);
655 return FALSE;
657 memcpy (&state_stack [0].locations, &locations, sizeof (locations));
658 memcpy (&state_stack [0].reg_saved, &reg_saved, sizeof (reg_saved));
659 state_stack [0].cfa_reg = cfa_reg;
660 state_stack [0].cfa_offset = cfa_offset;
661 state_stack_pos ++;
662 break;
663 case DW_CFA_restore_state:
664 if (state_stack_pos != 1) {
665 mono_runtime_printf_err ("Unwind failure. Assertion at %s %d\n.", __FILE__, __LINE__);
666 return FALSE;
668 state_stack_pos --;
669 memcpy (&locations, &state_stack [0].locations, sizeof (locations));
670 memcpy (&reg_saved, &state_stack [0].reg_saved, sizeof (reg_saved));
671 cfa_reg = state_stack [0].cfa_reg;
672 cfa_offset = state_stack [0].cfa_offset;
673 break;
674 case DW_CFA_mono_advance_loc:
675 if (!mark_locations [0]) {
676 mono_runtime_printf_err ("Unwind failure. Assertion at %s %d\n.", __FILE__, __LINE__);
677 return FALSE;
679 pos = mark_locations [0] - start_ip;
680 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;
685 break;
687 default:
688 mono_runtime_printf_err ("Unwind failure. Illegal value for switch statement, assertion at %s %d\n.", __FILE__, __LINE__);
689 return FALSE;
693 if (save_locations)
694 memset (save_locations, 0, save_locations_len * sizeof (host_mgreg_t*));
696 if (cfa_reg == -1) {
697 mono_runtime_printf_err ("Unset cfa_reg in method %s. Memory around ip (%p):", mono_get_method_from_ip (ip), ip);
698 mono_dump_mem (ip - 0x10, 0x40);
699 return FALSE;
701 cfa_val = (guint8*)regs [mono_dwarf_reg_to_hw_reg (cfa_reg)] + cfa_offset;
702 for (hwreg = 0; hwreg < NUM_HW_REGS; ++hwreg) {
703 if (reg_saved [hwreg] && locations [hwreg].loc_type == LOC_OFFSET) {
704 int dwarfreg = mono_hw_reg_to_dwarf_reg (hwreg);
705 if (hwreg >= nregs) {
706 mono_runtime_printf_err ("Unwind failure. Assertion at %s %d\n.", __FILE__, __LINE__);
707 return FALSE;
709 if (IS_DOUBLE_REG (dwarfreg))
710 regs [hwreg] = *(guint64*)(cfa_val + locations [hwreg].offset);
711 else
712 regs [hwreg] = *(host_mgreg_t*)(cfa_val + locations [hwreg].offset);
713 if (save_locations && hwreg < save_locations_len)
714 save_locations [hwreg] = (host_mgreg_t*)(cfa_val + locations [hwreg].offset);
718 *out_cfa = cfa_val;
720 // Success
721 return TRUE;
724 void
725 mono_unwind_init (void)
727 mono_os_mutex_init_recursive (&unwind_mutex);
729 mono_counters_register ("Unwind info size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &unwind_info_size);
732 void
733 mono_unwind_cleanup (void)
735 int i;
737 mono_os_mutex_destroy (&unwind_mutex);
739 if (!cached_info)
740 return;
742 for (i = 0; i < cached_info_next; ++i) {
743 MonoUnwindInfo *cached = cached_info [i];
745 g_free (cached);
747 g_free (cached_info);
749 for (GSList *cursor = cached_info_list; cursor != NULL; cursor = cursor->next)
750 g_free (cursor->data);
752 g_slist_free (cached_info_list);
756 * mono_cache_unwind_info
758 * Save UNWIND_INFO in the unwind info cache and return an id which can be passed
759 * to mono_get_cached_unwind_info to get a cached copy of the info.
760 * A copy is made of the unwind info.
761 * This function is useful for two reasons:
762 * - many methods have the same unwind info
763 * - MonoJitInfo->unwind_info is an int so it can't store the pointer to the unwind info
765 guint32
766 mono_cache_unwind_info (guint8 *unwind_info, guint32 unwind_info_len)
768 int i;
769 MonoUnwindInfo *info;
771 unwind_lock ();
773 if (cached_info == NULL) {
774 cached_info_size = 16;
775 cached_info = g_new0 (MonoUnwindInfo*, cached_info_size);
778 for (i = 0; i < cached_info_next; ++i) {
779 MonoUnwindInfo *cached = cached_info [i];
781 if (cached->len == unwind_info_len && memcmp (cached->info, unwind_info, unwind_info_len) == 0) {
782 unwind_unlock ();
783 return i;
787 info = (MonoUnwindInfo *)g_malloc (sizeof (MonoUnwindInfo) + unwind_info_len);
788 info->len = unwind_info_len;
789 memcpy (&info->info, unwind_info, unwind_info_len);
791 i = cached_info_next;
793 if (cached_info_next >= cached_info_size) {
794 MonoUnwindInfo **new_table;
797 * Avoid freeing the old table so mono_get_cached_unwind_info ()
798 * doesn't need locks/hazard pointers.
801 new_table = g_new0 (MonoUnwindInfo*, cached_info_size * 2);
803 memcpy (new_table, cached_info, cached_info_size * sizeof (MonoUnwindInfo*));
805 mono_memory_barrier ();
807 cached_info_list = g_slist_prepend (cached_info_list, cached_info);
809 cached_info = new_table;
811 cached_info_size *= 2;
814 cached_info [cached_info_next ++] = info;
816 unwind_info_size += sizeof (MonoUnwindInfo) + unwind_info_len;
818 unwind_unlock ();
819 return i;
823 * This function is signal safe.
825 guint8*
826 mono_get_cached_unwind_info (guint32 index, guint32 *unwind_info_len)
828 MonoUnwindInfo **table;
829 MonoUnwindInfo *info;
830 guint8 *data;
833 * This doesn't need any locks/hazard pointers,
834 * since new tables are copies of the old ones.
836 table = cached_info;
838 info = table [index];
840 *unwind_info_len = info->len;
841 data = info->info;
843 return data;
847 * mono_unwind_get_dwarf_data_align:
849 * Return the data alignment used by the encoded unwind information.
852 mono_unwind_get_dwarf_data_align (void)
854 return DWARF_DATA_ALIGN;
858 * mono_unwind_get_dwarf_pc_reg:
860 * Return the dwarf register number of the register holding the ip of the
861 * previous frame.
864 mono_unwind_get_dwarf_pc_reg (void)
866 return DWARF_PC_REG;
869 static void
870 decode_cie_op (guint8 *p, guint8 **endp)
872 int op = *p & 0xc0;
874 switch (op) {
875 case DW_CFA_advance_loc:
876 p ++;
877 break;
878 case DW_CFA_offset:
879 p ++;
880 decode_uleb128 (p, &p);
881 break;
882 case 0: {
883 int ext_op = *p;
884 p ++;
885 switch (ext_op) {
886 case DW_CFA_def_cfa:
887 decode_uleb128 (p, &p);
888 decode_uleb128 (p, &p);
889 break;
890 case DW_CFA_def_cfa_offset:
891 decode_uleb128 (p, &p);
892 break;
893 case DW_CFA_def_cfa_register:
894 decode_uleb128 (p, &p);
895 break;
896 case DW_CFA_advance_loc4:
897 p += 4;
898 break;
899 case DW_CFA_offset_extended_sf:
900 decode_uleb128 (p, &p);
901 decode_uleb128 (p, &p);
902 break;
903 default:
904 g_assert_not_reached ();
906 break;
908 default:
909 g_assert_not_reached ();
912 *endp = p;
915 static gint64
916 read_encoded_val (guint32 encoding, guint8 *p, guint8 **endp)
918 gint64 res;
920 switch (encoding & 0xf) {
921 case DW_EH_PE_sdata8:
922 res = *(gint64*)p;
923 p += 8;
924 break;
925 case DW_EH_PE_sdata4:
926 res = *(gint32*)p;
927 p += 4;
928 break;
929 default:
930 g_assert_not_reached ();
933 *endp = p;
934 return res;
938 * decode_lsda:
940 * Decode the Mono specific Language Specific Data Area generated by LLVM.
941 * This function is async safe.
943 static void
944 decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo *ex_info, gpointer *type_info, guint32 *ex_info_len, int *this_reg, int *this_offset)
946 guint8 *p;
947 int i, ncall_sites, this_encoding;
948 guint32 mono_magic, version;
950 p = lsda;
952 /* This is the modified LSDA generated by the LLVM mono branch */
953 mono_magic = decode_uleb128 (p, &p);
954 g_assert (mono_magic == 0x4d4fef4f);
955 version = decode_uleb128 (p, &p);
956 g_assert (version == 1);
957 this_encoding = *p;
958 p ++;
959 if (this_encoding == DW_EH_PE_udata4) {
960 gint32 op, reg, offset;
962 /* 'this' location */
963 op = *p;
964 g_assert (op == DW_OP_bregx);
965 p ++;
966 reg = decode_uleb128 (p, &p);
967 offset = decode_sleb128 (p, &p);
969 *this_reg = mono_dwarf_reg_to_hw_reg (reg);
970 *this_offset = offset;
971 } else {
972 g_assert (this_encoding == DW_EH_PE_omit);
974 *this_reg = -1;
975 *this_offset = -1;
977 ncall_sites = decode_uleb128 (p, &p);
978 p = (guint8*)ALIGN_TO ((gsize)p, 4);
980 if (ex_info_len)
981 *ex_info_len = ncall_sites;
983 for (i = 0; i < ncall_sites; ++i) {
984 int block_start_offset, block_size, landing_pad;
985 guint8 *tinfo;
987 block_start_offset = read32 (p);
988 p += sizeof (gint32);
989 block_size = read32 (p);
990 p += sizeof (gint32);
991 landing_pad = read32 (p);
992 p += sizeof (gint32);
993 tinfo = p;
994 p += sizeof (gint32);
996 g_assert (landing_pad);
997 g_assert (((size_t)tinfo % 4) == 0);
998 //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
1000 if (ex_info) {
1001 if (type_info)
1002 type_info [i] = tinfo;
1003 ex_info[i].try_start = code + block_start_offset;
1004 ex_info[i].try_end = code + block_start_offset + block_size;
1005 ex_info[i].handler_start = code + landing_pad;
1011 * mono_unwind_decode_fde:
1013 * Decode a DWARF FDE entry, returning the unwind opcodes.
1014 * If not NULL, EX_INFO is set to a malloc-ed array of MonoJitExceptionInfo structures,
1015 * only try_start, try_end and handler_start is set.
1016 * If not NULL, TYPE_INFO is set to a malloc-ed array containing the ttype table from the
1017 * LSDA.
1019 guint8*
1020 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)
1022 guint8 *p, *cie, *fde_current, *fde_aug = NULL, *code, *fde_cfi, *cie_cfi;
1023 gint32 fde_len, cie_offset, pc_begin, pc_range, aug_len;
1024 gint32 cie_len, cie_id, cie_version, code_align, data_align, return_reg;
1025 gint32 i, cie_aug_len, buf_len;
1026 char *cie_aug_str;
1027 guint8 *buf;
1028 gboolean has_fde_augmentation = FALSE;
1031 * http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
1034 /* This is generated by JITDwarfEmitter::EmitEHFrame () */
1036 *type_info = NULL;
1037 *this_reg = -1;
1038 *this_offset = -1;
1040 /* Decode FDE */
1042 p = fde;
1043 // FIXME: Endianess ?
1044 fde_len = *(guint32*)p;
1045 g_assert (fde_len != 0xffffffff && fde_len != 0);
1046 p += 4;
1047 cie_offset = *(guint32*)p;
1048 cie = p - cie_offset;
1049 p += 4;
1050 fde_current = p;
1052 /* Decode CIE */
1053 p = cie;
1054 cie_len = *(guint32*)p;
1055 p += 4;
1056 cie_id = *(guint32*)p;
1057 g_assert (cie_id == 0);
1058 p += 4;
1059 cie_version = *p;
1060 g_assert (cie_version == 1);
1061 p += 1;
1062 cie_aug_str = (char*)p;
1063 p += strlen (cie_aug_str) + 1;
1064 code_align = decode_uleb128 (p, &p);
1065 data_align = decode_sleb128 (p, &p);
1066 return_reg = decode_uleb128 (p, &p);
1067 if (strstr (cie_aug_str, "z")) {
1068 guint8 *cie_aug;
1069 guint32 p_encoding;
1071 cie_aug_len = decode_uleb128 (p, &p);
1073 has_fde_augmentation = TRUE;
1075 cie_aug = p;
1076 for (i = 0; cie_aug_str [i] != '\0'; ++i) {
1077 switch (cie_aug_str [i]) {
1078 case 'z':
1079 break;
1080 case 'P':
1081 p_encoding = *p;
1082 p ++;
1083 read_encoded_val (p_encoding, p, &p);
1084 break;
1085 case 'L':
1086 g_assert ((*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel)) || (*p == (DW_EH_PE_sdata8|DW_EH_PE_pcrel)));
1087 p ++;
1088 break;
1089 case 'R':
1090 g_assert (*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel));
1091 p ++;
1092 break;
1093 default:
1094 g_assert_not_reached ();
1095 break;
1099 p = cie_aug;
1100 p += cie_aug_len;
1102 cie_cfi = p;
1104 /* Continue decoding FDE */
1105 p = fde_current;
1106 /* DW_EH_PE_sdata4|DW_EH_PE_pcrel encoding */
1107 pc_begin = *(gint32*)p;
1108 code = p + pc_begin;
1109 p += 4;
1110 pc_range = *(guint32*)p;
1111 p += 4;
1112 if (has_fde_augmentation) {
1113 aug_len = decode_uleb128 (p, &p);
1114 fde_aug = p;
1115 p += aug_len;
1116 } else {
1117 aug_len = 0;
1119 fde_cfi = p;
1121 if (code_len)
1122 *code_len = pc_range;
1124 if (ex_info) {
1125 *ex_info = NULL;
1126 *ex_info_len = 0;
1129 /* Decode FDE augmention */
1130 if (aug_len) {
1131 gint32 lsda_offset;
1132 guint8 *lsda;
1134 /* sdata|pcrel encoding */
1135 if (aug_len == 4)
1136 lsda_offset = read32 (fde_aug);
1137 else if (aug_len == 8)
1138 lsda_offset = *(gint64*)fde_aug;
1139 else
1140 g_assert_not_reached ();
1141 if (lsda_offset != 0) {
1142 lsda = fde_aug + lsda_offset;
1144 /* Get the lengths first */
1145 guint32 len;
1146 decode_lsda (lsda, code, NULL, NULL, &len, this_reg, this_offset);
1148 if (ex_info)
1149 *ex_info = (MonoJitExceptionInfo *)g_malloc0 (len * sizeof (MonoJitExceptionInfo));
1150 if (type_info)
1151 *type_info = (gpointer *)g_malloc0 (len * sizeof (gpointer));
1153 decode_lsda (lsda, code, ex_info ? *ex_info : NULL, type_info ? *type_info : NULL, ex_info_len, this_reg, this_offset);
1157 /* Make sure the FDE uses the same constants as we do */
1158 g_assert (code_align == 1);
1159 g_assert (data_align == DWARF_DATA_ALIGN);
1160 g_assert (return_reg == DWARF_PC_REG);
1162 buf_len = (cie + cie_len + 4 - cie_cfi) + (fde + fde_len + 4 - fde_cfi);
1163 buf = (guint8 *)g_malloc0 (buf_len);
1165 i = 0;
1166 p = cie_cfi;
1167 while (p < cie + cie_len + 4) {
1168 if (*p == DW_CFA_nop)
1169 break;
1170 else
1171 decode_cie_op (p, &p);
1173 memcpy (buf + i, cie_cfi, p - cie_cfi);
1174 i += p - cie_cfi;
1176 p = fde_cfi;
1177 while (p < fde + fde_len + 4) {
1178 if (*p == DW_CFA_nop)
1179 break;
1180 else
1181 decode_cie_op (p, &p);
1183 memcpy (buf + i, fde_cfi, p - fde_cfi);
1184 i += p - fde_cfi;
1185 g_assert (i <= buf_len);
1187 *out_len = i;
1189 return (guint8 *)g_realloc (buf, i);
1193 * mono_unwind_decode_mono_fde:
1195 * Decode an FDE entry in the LLVM emitted mono EH frame.
1196 * If EI/TYPE_INFO/UNW_INFO are NULL, compute only the value of the scalar fields in INFO.
1197 * Otherwise:
1198 * - Fill out EX_INFO with try_start, try_end and handler_start.
1199 * - Fill out TYPE_INFO with the ttype table from the LSDA.
1200 * - Fill out UNW_INFO with the unwind info.
1201 * This function is async safe.
1203 void
1204 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)
1206 guint8 *p, *fde_aug, *cie_cfi, *fde_cfi, *buf;
1207 int has_aug, aug_len, cie_cfi_len, fde_cfi_len;
1208 gint32 code_align, data_align, return_reg, pers_encoding;
1210 memset (res, 0, sizeof (*res));
1211 res->this_reg = -1;
1212 res->this_offset = -1;
1214 /* fde points to data emitted by LLVM in DwarfMonoException::EmitMonoEHFrame () */
1215 p = fde;
1216 has_aug = *p;
1217 p ++;
1218 if (has_aug) {
1219 aug_len = read32 (p);
1220 p += 4;
1221 } else {
1222 aug_len = 0;
1224 fde_aug = p;
1225 p += aug_len;
1226 fde_cfi = p;
1228 if (has_aug) {
1229 guint8 *lsda;
1231 /* The LSDA is embedded directly into the FDE */
1232 lsda = fde_aug;
1234 /* Get the lengths first */
1235 decode_lsda (lsda, code, NULL, NULL, &res->ex_info_len, &res->this_reg, &res->this_offset);
1237 decode_lsda (lsda, code, ex_info, type_info, NULL, &res->this_reg, &res->this_offset);
1240 /* Decode CIE */
1241 p = cie;
1242 code_align = decode_uleb128 (p, &p);
1243 data_align = decode_sleb128 (p, &p);
1244 return_reg = decode_uleb128 (p, &p);
1245 pers_encoding = *p;
1246 p ++;
1247 if (pers_encoding != DW_EH_PE_omit)
1248 read_encoded_val (pers_encoding, p, &p);
1250 cie_cfi = p;
1252 /* Make sure the FDE uses the same constants as we do */
1253 g_assert (code_align == 1);
1254 g_assert (data_align == DWARF_DATA_ALIGN);
1255 g_assert (return_reg == DWARF_PC_REG);
1257 /* Compute size of CIE unwind info it is DW_CFA_nop terminated */
1258 p = cie_cfi;
1259 while (TRUE) {
1260 if (*p == DW_CFA_nop)
1261 break;
1262 else
1263 decode_cie_op (p, &p);
1265 cie_cfi_len = p - cie_cfi;
1266 fde_cfi_len = (fde + fde_len - fde_cfi);
1268 buf = unw_info;
1269 if (buf) {
1270 memcpy (buf, cie_cfi, cie_cfi_len);
1271 memcpy (buf + cie_cfi_len, fde_cfi, fde_cfi_len);
1274 res->unw_info_len = cie_cfi_len + fde_cfi_len;
1278 * mono_unwind_get_cie_program:
1280 * Get the unwind bytecode for the DWARF CIE.
1282 GSList*
1283 mono_unwind_get_cie_program (void)
1285 #if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_POWERPC) || defined(TARGET_ARM)
1286 return mono_arch_get_cie_program ();
1287 #else
1288 return NULL;
1289 #endif