Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / unwind.c
1 /**
2  * \file
3  * Stack Unwinding Interface
4  *
5  * Authors:
6  *   Zoltan Varga (vargaz@gmail.com)
7  *
8  * (C) 2008 Novell, Inc.
9  */
10
11 #include "mini.h"
12 #include "mini-unwind.h"
13
14 #include <mono/utils/mono-counters.h>
15 #include <mono/utils/freebsd-dwarf.h>
16 #include <mono/utils/hazard-pointer.h>
17 #include <mono/metadata/threads-types.h>
18 #include <mono/metadata/mono-endian.h>
19
20 typedef enum {
21         LOC_SAME,
22         LOC_OFFSET
23 } LocType;
24
25 typedef struct {
26         LocType loc_type;
27         int offset;
28 } Loc;
29
30 typedef struct {
31         guint32 len;
32         guint8 info [MONO_ZERO_LEN_ARRAY];
33 } MonoUnwindInfo;
34
35 #define ALIGN_TO(val,align) ((((size_t)val) + ((align) - 1)) & ~((align) - 1))
36
37 static mono_mutex_t unwind_mutex;
38
39 static MonoUnwindInfo **cached_info;
40 static int cached_info_next, cached_info_size;
41 static GSList *cached_info_list;
42 /* Statistics */
43 static int unwind_info_size;
44
45 #define unwind_lock() mono_os_mutex_lock (&unwind_mutex)
46 #define unwind_unlock() mono_os_mutex_unlock (&unwind_mutex)
47
48 #ifdef TARGET_AMD64
49 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 };
50 #define NUM_DWARF_REGS AMD64_NREG
51 #define DWARF_DATA_ALIGN (-8)
52 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (AMD64_RIP))
53 #elif defined(TARGET_ARM)
54 // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040a/IHI0040A_aadwarf.pdf
55 /* Assign d8..d15 to hregs 16..24 (dwarf regs 264..271) */
56 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 NUM_DWARF_REGS 272
58 #define DWARF_DATA_ALIGN (-4)
59 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (ARMREG_LR))
60 #define IS_DOUBLE_REG(dwarf_reg) (((dwarf_reg) >= 264) && ((dwarf_reg) <= 271))
61 #elif defined(TARGET_ARM64)
62 #define NUM_DWARF_REGS 96
63 #define DWARF_DATA_ALIGN (-8)
64 /* LR */
65 #define DWARF_PC_REG 30
66 static int map_hw_reg_to_dwarf_reg [] = {
67         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
68         16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
69         /* v8..v15 */
70         72, 73, 74, 75, 76, 77, 78, 79,
71 };
72 #elif defined (TARGET_X86)
73 /*
74  * ebp and esp are swapped:
75  * http://lists.cs.uiuc.edu/pipermail/lldb-dev/2014-January/003101.html
76  */
77 static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 5, 4, 6, 7, 8 };
78 /* + 1 is for IP */
79 #define NUM_DWARF_REGS (X86_NREG + 1)
80 #define DWARF_DATA_ALIGN (-4)
81 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (X86_NREG))
82 #elif defined (TARGET_POWERPC)
83 // http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
84 static int map_hw_reg_to_dwarf_reg [ppc_lr + 1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,
85                                                                                   9, 10, 11, 12, 13, 14, 15, 16,
86                                                                                   17, 18, 19, 20, 21, 22, 23, 24,
87                                                                                   25, 26, 27, 28, 29, 30, 31 };
88 #define DWARF_DATA_ALIGN (-(gint32)sizeof (mgreg_t))
89 #if _CALL_ELF == 2
90 #define DWARF_PC_REG 65
91 #else
92 #define DWARF_PC_REG 108
93 #endif
94 #define NUM_DWARF_REGS (DWARF_PC_REG + 1)
95 #elif defined (TARGET_S390X)
96 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 NUM_DWARF_REGS 16
98 #define DWARF_DATA_ALIGN (-8)
99 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (14))
100 #elif defined (TARGET_MIPS)
101 /* FIXME: */
102 static int map_hw_reg_to_dwarf_reg [32] = {
103         0, 1, 2, 3, 4, 5, 6, 7,
104         8, 9, 10, 11, 12, 13, 14, 15,
105         16, 17, 18, 19, 20, 21, 22, 23,
106         24, 25, 26, 27, 28, 29, 30, 31
107 };
108 #define NUM_DWARF_REGS 32
109 #define DWARF_DATA_ALIGN (-(gint32)sizeof (mgreg_t))
110 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (mips_ra))
111 #else
112 static int map_hw_reg_to_dwarf_reg [16];
113 #define NUM_DWARF_REGS 16
114 #define DWARF_DATA_ALIGN 0
115 #define DWARF_PC_REG -1
116 #endif
117
118 #define NUM_HW_REGS (sizeof (map_hw_reg_to_dwarf_reg) / sizeof (int))
119
120 #ifndef IS_DOUBLE_REG
121 #define IS_DOUBLE_REG(dwarf_reg) (dwarf_reg ? 0 : 0)
122 #endif
123
124 static gboolean dwarf_reg_to_hw_reg_inited;
125 static gboolean hw_reg_to_dwarf_reg_inited;
126
127 static int map_dwarf_reg_to_hw_reg [NUM_DWARF_REGS];
128
129 static void
130 init_hw_reg_map (void)
131 {
132 #ifdef TARGET_POWERPC
133         map_hw_reg_to_dwarf_reg [ppc_lr] = DWARF_PC_REG;
134 #endif
135         mono_memory_barrier ();
136         hw_reg_to_dwarf_reg_inited = TRUE;
137 }
138
139 /*
140  * mono_hw_reg_to_dwarf_reg:
141  *
142  *   Map the hardware register number REG to the register number used by DWARF.
143  */
144 int
145 mono_hw_reg_to_dwarf_reg (int reg)
146 {
147         if (!hw_reg_to_dwarf_reg_inited)
148                 init_hw_reg_map ();
149
150         if (NUM_HW_REGS == 0) {
151                 g_assert_not_reached ();
152                 return -1;
153         } else {
154                 return map_hw_reg_to_dwarf_reg [reg];
155         }
156 }
157
158 static void
159 init_dwarf_reg_map (void)
160 {
161         int i;
162
163         g_assert (NUM_HW_REGS > 0);
164         for (i = 0; i < NUM_HW_REGS; ++i) {
165                 map_dwarf_reg_to_hw_reg [mono_hw_reg_to_dwarf_reg (i)] = i;
166         }
167
168         mono_memory_barrier ();
169         dwarf_reg_to_hw_reg_inited = TRUE;
170 }
171
172 int
173 mono_dwarf_reg_to_hw_reg (int reg)
174 {
175         if (!dwarf_reg_to_hw_reg_inited)
176                 init_dwarf_reg_map ();
177
178         return map_dwarf_reg_to_hw_reg [reg];
179 }
180
181 static G_GNUC_UNUSED void
182 encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
183 {
184         guint8 *p = buf;
185
186         do {
187                 guint8 b = value & 0x7f;
188                 value >>= 7;
189                 if (value != 0) /* more bytes to come */
190                         b |= 0x80;
191                 *p ++ = b;
192         } while (value);
193
194         *endbuf = p;
195 }
196
197 static G_GNUC_UNUSED void
198 encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
199 {
200         gboolean more = 1;
201         gboolean negative = (value < 0);
202         guint32 size = 32;
203         guint8 byte;
204         guint8 *p = buf;
205
206         while (more) {
207                 byte = value & 0x7f;
208                 value >>= 7;
209                 /* the following is unnecessary if the
210                  * implementation of >>= uses an arithmetic rather
211                  * than logical shift for a signed left operand
212                  */
213                 if (negative)
214                         /* sign extend */
215                         value |= - (1 <<(size - 7));
216                 /* sign bit of byte is second high order bit (0x40) */
217                 if ((value == 0 && !(byte & 0x40)) ||
218                         (value == -1 && (byte & 0x40)))
219                         more = 0;
220                 else
221                         byte |= 0x80;
222                 *p ++= byte;
223         }
224
225         *endbuf = p;
226 }
227
228 static inline guint32
229 decode_uleb128 (guint8 *buf, guint8 **endbuf)
230 {
231         guint8 *p = buf;
232         guint32 res = 0;
233         int shift = 0;
234
235         while (TRUE) {
236                 guint8 b = *p;
237                 p ++;
238
239                 res = res | (((int)(b & 0x7f)) << shift);
240                 if (!(b & 0x80))
241                         break;
242                 shift += 7;
243         }
244
245         *endbuf = p;
246
247         return res;
248 }
249
250 static inline gint32
251 decode_sleb128 (guint8 *buf, guint8 **endbuf)
252 {
253         guint8 *p = buf;
254         gint32 res = 0;
255         int shift = 0;
256
257         while (TRUE) {
258                 guint8 b = *p;
259                 p ++;
260
261                 res = res | (((int)(b & 0x7f)) << shift);
262                 shift += 7;
263                 if (!(b & 0x80)) {
264                         if (shift < 32 && (b & 0x40))
265                                 res |= - (1 << shift);
266                         break;
267                 }
268         }
269
270         *endbuf = p;
271
272         return res;
273 }
274
275 void
276 mono_print_unwind_info (guint8 *unwind_info, int unwind_info_len)
277 {
278         guint8 *p;
279         int pos, reg, offset, cfa_reg, cfa_offset;
280
281         p = unwind_info;
282         pos = 0;
283         while (p < unwind_info + unwind_info_len) {
284                 int op = *p & 0xc0;
285
286                 switch (op) {
287                 case DW_CFA_advance_loc:
288                         pos += *p & 0x3f;
289                         p ++;
290                         break;
291                 case DW_CFA_offset:
292                         reg = *p & 0x3f;
293                         p ++;
294                         offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
295                         if (reg == DWARF_PC_REG)
296                                 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, "pc", -offset);
297                         else
298                                 printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
299                         break;
300                 case 0: {
301                         int ext_op = *p;
302                         p ++;
303                         switch (ext_op) {
304                         case DW_CFA_def_cfa:
305                                 cfa_reg = decode_uleb128 (p, &p);
306                                 cfa_offset = decode_uleb128 (p, &p);
307                                 printf ("CFA: [%x] def_cfa: %s+0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)), cfa_offset);
308                                 break;
309                         case DW_CFA_def_cfa_offset:
310                                 cfa_offset = decode_uleb128 (p, &p);
311                                 printf ("CFA: [%x] def_cfa_offset: 0x%x\n", pos, cfa_offset);
312                                 break;
313                         case DW_CFA_def_cfa_register:
314                                 cfa_reg = decode_uleb128 (p, &p);
315                                 printf ("CFA: [%x] def_cfa_reg: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)));
316                                 break;
317                         case DW_CFA_offset_extended_sf:
318                                 reg = decode_uleb128 (p, &p);
319                                 offset = decode_sleb128 (p, &p) * DWARF_DATA_ALIGN;
320                                 printf ("CFA: [%x] offset_extended_sf: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
321                                 break;
322                         case DW_CFA_same_value:
323                                 reg = decode_uleb128 (p, &p);
324                                 printf ("CFA: [%x] same_value: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)));
325                                 break;
326                         case DW_CFA_advance_loc4:
327                                 pos += read32 (p);
328                                 p += 4;
329                                 break;
330                         case DW_CFA_remember_state:
331                                 printf ("CFA: [%x] remember_state\n", pos);
332                                 break;
333                         case DW_CFA_restore_state:
334                                 printf ("CFA: [%x] restore_state\n", pos);
335                                 break;
336                         case DW_CFA_mono_advance_loc:
337                                 printf ("CFA: [%x] mono_advance_loc\n", pos);
338                                 break;
339                         default:
340                                 g_assert_not_reached ();
341                         }
342                         break;
343                 }
344                 default:
345                         g_assert_not_reached ();
346                 }
347         }
348 }
349
350 /*
351  * mono_unwind_ops_encode_full:
352  *
353  *   Encode the unwind ops in UNWIND_OPS into the compact DWARF encoding.
354  * Return a pointer to malloc'ed memory.
355  * If ENABLE_EXTENSIONS is FALSE, avoid encoding the mono extension
356  * opcode (DW_CFA_mono_advance_loc).
357  */
358 guint8*
359 mono_unwind_ops_encode_full (GSList *unwind_ops, guint32 *out_len, gboolean enable_extensions)
360 {
361         GSList *l;
362         MonoUnwindOp *op;
363         int loc;
364         guint8 buf [4096];
365         guint8 *p, *res;
366
367         p = buf;
368
369         loc = 0;
370         l = unwind_ops;
371         for (; l; l = l->next) {
372                 int reg;
373
374                 op = (MonoUnwindOp *)l->data;
375
376                 /* Convert the register from the hw encoding to the dwarf encoding */
377                 reg = mono_hw_reg_to_dwarf_reg (op->reg);
378
379                 if (op->op == DW_CFA_mono_advance_loc) {
380                         /* This advances loc to its location */
381                         loc = op->when;
382                 }
383
384                 /* Emit an advance_loc if neccesary */
385                 while (op->when > loc) {
386                         if (op->when - loc >= 65536) {
387                                 *p ++ = DW_CFA_advance_loc4;
388                                 guint32 v = (guint32)(op->when - loc);
389                                 memcpy (p, &v, 4);
390                                 g_assert (read32 (p) == (guint32)(op->when - loc));
391                                 p += 4;
392                                 loc = op->when;
393                         } else if (op->when - loc >= 256) {
394                                 *p ++ = DW_CFA_advance_loc2;
395                                 guint16 v = (guint16)(op->when - loc);
396                                 memcpy (p, &v, 2);
397                                 g_assert (read16 (p) == (guint32)(op->when - loc));
398                                 p += 2;
399                                 loc = op->when;
400                         } else if (op->when - loc >= 32) {
401                                 *p ++ = DW_CFA_advance_loc1;
402                                 *(guint8*)p = (guint8)(op->when - loc);
403                                 p += 1;
404                                 loc = op->when;
405                         } else if (op->when - loc < 32) {
406                                 *p ++ = DW_CFA_advance_loc | (op->when - loc);
407                                 loc = op->when;
408                         } else {
409                                 *p ++ = DW_CFA_advance_loc | (30);
410                                 loc += 30;
411                         }
412                 }                       
413
414                 switch (op->op) {
415                 case DW_CFA_def_cfa:
416                         *p ++ = op->op;
417                         encode_uleb128 (reg, p, &p);
418                         encode_uleb128 (op->val, p, &p);
419                         break;
420                 case DW_CFA_def_cfa_offset:
421                         *p ++ = op->op;
422                         encode_uleb128 (op->val, p, &p);
423                         break;
424                 case DW_CFA_def_cfa_register:
425                         *p ++ = op->op;
426                         encode_uleb128 (reg, p, &p);
427                         break;
428                 case DW_CFA_same_value:
429                         *p ++ = op->op;
430                         encode_uleb128 (reg, p, &p);
431                         break;
432                 case DW_CFA_offset:
433                         if (reg > 63) {
434                                 *p ++ = DW_CFA_offset_extended_sf;
435                                 encode_uleb128 (reg, p, &p);
436                                 encode_sleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
437                         } else {
438                                 *p ++ = DW_CFA_offset | reg;
439                                 encode_uleb128 (op->val / DWARF_DATA_ALIGN, p, &p);
440                         }
441                         break;
442                 case DW_CFA_remember_state:
443                 case DW_CFA_restore_state:
444                         *p ++ = op->op;
445                         break;
446                 case DW_CFA_mono_advance_loc:
447                         if (!enable_extensions)
448                                 break;
449                         /* Only one location is supported */
450                         g_assert (op->val == 0);
451                         *p ++ = op->op;
452                         break;
453 #if defined(TARGET_WIN32) && defined(TARGET_AMD64)
454                 case DW_CFA_mono_sp_alloc_info_win64:
455                 case DW_CFA_mono_fp_alloc_info_win64:
456                         // Drop Windows specific unwind op's. These op's are currently
457                         // only used when registering unwind info with Windows OS unwinder.
458                         break;
459 #endif
460                 default:
461                         g_assert_not_reached ();
462                         break;
463                 }
464         }
465         
466         g_assert (p - buf < 4096);
467         *out_len = p - buf;
468         res = (guint8 *)g_malloc (p - buf);
469         memcpy (res, buf, p - buf);
470         return res;
471 }
472
473 guint8*
474 mono_unwind_ops_encode (GSList *unwind_ops, guint32 *out_len)
475 {
476         return mono_unwind_ops_encode_full (unwind_ops, out_len, TRUE);
477 }
478
479 #if 0
480 #define UNW_DEBUG(stmt) do { stmt; } while (0)
481 #else
482 #define UNW_DEBUG(stmt) do { } while (0)
483 #endif
484
485 static G_GNUC_UNUSED void
486 print_dwarf_state (int cfa_reg, int cfa_offset, int ip, int nregs, Loc *locations, guint8 *reg_saved)
487 {
488         int i;
489
490         printf ("\t%x: cfa=r%d+%d ", ip, cfa_reg, cfa_offset);
491
492         for (i = 0; i < nregs; ++i)
493                 if (reg_saved [i] && locations [i].loc_type == LOC_OFFSET)
494                         printf ("r%d@%d(cfa) ", i, locations [i].offset);
495         printf ("\n");
496 }
497
498 typedef struct {
499         Loc locations [NUM_HW_REGS];
500         guint8 reg_saved [NUM_HW_REGS];
501         int cfa_reg, cfa_offset;
502 } UnwindState;
503
504 /*
505  * Given the state of the current frame as stored in REGS, execute the unwind 
506  * operations in unwind_info until the location counter reaches POS. The result is 
507  * stored back into REGS. OUT_CFA will receive the value of the CFA.
508  * If SAVE_LOCATIONS is non-NULL, it should point to an array of size SAVE_LOCATIONS_LEN.
509  * On return, the nth entry will point to the address of the stack slot where register
510  * N was saved, or NULL, if it was not saved by this frame.
511  * MARK_LOCATIONS should contain the locations marked by mono_emit_unwind_op_mark_loc (), if any.
512  * This function is signal safe.
513  */
514 void
515 mono_unwind_frame (guint8 *unwind_info, guint32 unwind_info_len, 
516                                    guint8 *start_ip, guint8 *end_ip, guint8 *ip, guint8 **mark_locations,
517                                    mono_unwind_reg_t *regs, int nregs,
518                                    mgreg_t **save_locations, int save_locations_len,
519                                    guint8 **out_cfa)
520 {
521         Loc locations [NUM_HW_REGS];
522         guint8 reg_saved [NUM_HW_REGS];
523         int pos, reg, hwreg, cfa_reg = -1, cfa_offset = 0, offset;
524         guint8 *p;
525         guint8 *cfa_val;
526         UnwindState state_stack [1];
527         int state_stack_pos;
528
529         memset (reg_saved, 0, sizeof (reg_saved));
530         state_stack [0].cfa_reg = -1;
531         state_stack [0].cfa_offset = 0;
532
533         p = unwind_info;
534         pos = 0;
535         cfa_reg = -1;
536         cfa_offset = -1;
537         state_stack_pos = 0;
538         while (pos <= ip - start_ip && p < unwind_info + unwind_info_len) {
539                 int op = *p & 0xc0;
540
541                 switch (op) {
542                 case DW_CFA_advance_loc:
543                         UNW_DEBUG (print_dwarf_state (cfa_reg, cfa_offset, pos, nregs, locations));
544                         pos += *p & 0x3f;
545                         p ++;
546                         break;
547                 case DW_CFA_offset:
548                         hwreg = mono_dwarf_reg_to_hw_reg (*p & 0x3f);
549                         p ++;
550                         reg_saved [hwreg] = TRUE;
551                         locations [hwreg].loc_type = LOC_OFFSET;
552                         locations [hwreg].offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
553                         break;
554                 case 0: {
555                         int ext_op = *p;
556                         p ++;
557                         switch (ext_op) {
558                         case DW_CFA_def_cfa:
559                                 cfa_reg = decode_uleb128 (p, &p);
560                                 cfa_offset = decode_uleb128 (p, &p);
561                                 break;
562                         case DW_CFA_def_cfa_offset:
563                                 cfa_offset = decode_uleb128 (p, &p);
564                                 break;
565                         case DW_CFA_def_cfa_register:
566                                 cfa_reg = decode_uleb128 (p, &p);
567                                 break;
568                         case DW_CFA_offset_extended_sf:
569                                 reg = decode_uleb128 (p, &p);
570                                 hwreg = mono_dwarf_reg_to_hw_reg (reg);
571                                 offset = decode_sleb128 (p, &p);
572                                 g_assert (reg < NUM_DWARF_REGS);
573                                 reg_saved [hwreg] = TRUE;
574                                 locations [hwreg].loc_type = LOC_OFFSET;
575                                 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
576                                 break;
577                         case DW_CFA_offset_extended:
578                                 reg = decode_uleb128 (p, &p);
579                                 hwreg = mono_dwarf_reg_to_hw_reg (reg);
580                                 offset = decode_uleb128 (p, &p);
581                                 g_assert (reg < NUM_DWARF_REGS);
582                                 reg_saved [hwreg] = TRUE;
583                                 locations [hwreg].loc_type = LOC_OFFSET;
584                                 locations [hwreg].offset = offset * DWARF_DATA_ALIGN;
585                                 break;
586                         case DW_CFA_same_value:
587                                 hwreg = mono_dwarf_reg_to_hw_reg (decode_uleb128 (p, &p));
588                                 locations [hwreg].loc_type = LOC_SAME;
589                                 break;
590                         case DW_CFA_advance_loc1:
591                                 pos += *p;
592                                 p += 1;
593                                 break;
594                         case DW_CFA_advance_loc2:
595                                 pos += read16 (p);
596                                 p += 2;
597                                 break;
598                         case DW_CFA_advance_loc4:
599                                 pos += read32 (p);
600                                 p += 4;
601                                 break;
602                         case DW_CFA_remember_state:
603                                 g_assert (state_stack_pos == 0);
604                                 memcpy (&state_stack [0].locations, &locations, sizeof (locations));
605                                 memcpy (&state_stack [0].reg_saved, &reg_saved, sizeof (reg_saved));
606                                 state_stack [0].cfa_reg = cfa_reg;
607                                 state_stack [0].cfa_offset = cfa_offset;
608                                 state_stack_pos ++;
609                                 break;
610                         case DW_CFA_restore_state:
611                                 g_assert (state_stack_pos == 1);
612                                 state_stack_pos --;
613                                 memcpy (&locations, &state_stack [0].locations, sizeof (locations));
614                                 memcpy (&reg_saved, &state_stack [0].reg_saved, sizeof (reg_saved));
615                                 cfa_reg = state_stack [0].cfa_reg;
616                                 cfa_offset = state_stack [0].cfa_offset;
617                                 break;
618                         case DW_CFA_mono_advance_loc:
619                                 g_assert (mark_locations [0]);
620                                 pos = mark_locations [0] - start_ip;
621                                 break;
622                         default:
623                                 g_assert_not_reached ();
624                         }
625                         break;
626                 }
627                 default:
628                         g_assert_not_reached ();
629                 }
630         }
631
632         if (save_locations)
633                 memset (save_locations, 0, save_locations_len * sizeof (mgreg_t*));
634
635         g_assert (cfa_reg != -1);
636         cfa_val = (guint8*)regs [mono_dwarf_reg_to_hw_reg (cfa_reg)] + cfa_offset;
637         for (hwreg = 0; hwreg < NUM_HW_REGS; ++hwreg) {
638                 if (reg_saved [hwreg] && locations [hwreg].loc_type == LOC_OFFSET) {
639                         int dwarfreg = mono_hw_reg_to_dwarf_reg (hwreg);
640                         g_assert (hwreg < nregs);
641                         if (IS_DOUBLE_REG (dwarfreg))
642                                 regs [hwreg] = *(guint64*)(cfa_val + locations [hwreg].offset);
643                         else
644                                 regs [hwreg] = *(mgreg_t*)(cfa_val + locations [hwreg].offset);
645                         if (save_locations && hwreg < save_locations_len)
646                                 save_locations [hwreg] = (mgreg_t*)(cfa_val + locations [hwreg].offset);
647                 }
648         }
649
650         *out_cfa = cfa_val;
651 }
652
653 void
654 mono_unwind_init (void)
655 {
656         mono_os_mutex_init_recursive (&unwind_mutex);
657
658         mono_counters_register ("Unwind info size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &unwind_info_size);
659 }
660
661 void
662 mono_unwind_cleanup (void)
663 {
664         int i;
665
666         mono_os_mutex_destroy (&unwind_mutex);
667
668         if (!cached_info)
669                 return;
670
671         for (i = 0; i < cached_info_next; ++i) {
672                 MonoUnwindInfo *cached = cached_info [i];
673
674                 g_free (cached);
675         }
676         g_free (cached_info);
677
678         for (GSList *cursor = cached_info_list; cursor != NULL; cursor = cursor->next)
679                 g_free (cursor->data);
680
681         g_slist_free (cached_info_list);
682 }
683
684 /*
685  * mono_cache_unwind_info
686  *
687  *   Save UNWIND_INFO in the unwind info cache and return an id which can be passed
688  * to mono_get_cached_unwind_info to get a cached copy of the info.
689  * A copy is made of the unwind info.
690  * This function is useful for two reasons:
691  * - many methods have the same unwind info
692  * - MonoJitInfo->unwind_info is an int so it can't store the pointer to the unwind info
693  */
694 guint32
695 mono_cache_unwind_info (guint8 *unwind_info, guint32 unwind_info_len)
696 {
697         int i;
698         MonoUnwindInfo *info;
699
700         unwind_lock ();
701
702         if (cached_info == NULL) {
703                 cached_info_size = 16;
704                 cached_info = g_new0 (MonoUnwindInfo*, cached_info_size);
705         }
706
707         for (i = 0; i < cached_info_next; ++i) {
708                 MonoUnwindInfo *cached = cached_info [i];
709
710                 if (cached->len == unwind_info_len && memcmp (cached->info, unwind_info, unwind_info_len) == 0) {
711                         unwind_unlock ();
712                         return i;
713                 }
714         }
715
716         info = (MonoUnwindInfo *)g_malloc (sizeof (MonoUnwindInfo) + unwind_info_len);
717         info->len = unwind_info_len;
718         memcpy (&info->info, unwind_info, unwind_info_len);
719
720         i = cached_info_next;
721         
722         if (cached_info_next >= cached_info_size) {
723                 MonoUnwindInfo **new_table;
724
725                 /*
726                  * Avoid freeing the old table so mono_get_cached_unwind_info ()
727                  * doesn't need locks/hazard pointers.
728                  */
729
730                 new_table = g_new0 (MonoUnwindInfo*, cached_info_size * 2);
731
732                 memcpy (new_table, cached_info, cached_info_size * sizeof (MonoUnwindInfo*));
733
734                 mono_memory_barrier ();
735
736                 cached_info_list = g_slist_prepend (cached_info_list, cached_info);
737
738                 cached_info = new_table;
739
740                 cached_info_size *= 2;
741         }
742
743         cached_info [cached_info_next ++] = info;
744
745         unwind_info_size += sizeof (MonoUnwindInfo) + unwind_info_len;
746
747         unwind_unlock ();
748         return i;
749 }
750
751 /*
752  * This function is signal safe.
753  */
754 guint8*
755 mono_get_cached_unwind_info (guint32 index, guint32 *unwind_info_len)
756 {
757         MonoUnwindInfo **table;
758         MonoUnwindInfo *info;
759         guint8 *data;
760
761         /*
762          * This doesn't need any locks/hazard pointers,
763          * since new tables are copies of the old ones.
764          */
765         table = cached_info;
766
767         info = table [index];
768
769         *unwind_info_len = info->len;
770         data = info->info;
771
772         return data;
773 }
774
775 /*
776  * mono_unwind_get_dwarf_data_align:
777  *
778  *   Return the data alignment used by the encoded unwind information.
779  */
780 int
781 mono_unwind_get_dwarf_data_align (void)
782 {
783         return DWARF_DATA_ALIGN;
784 }
785
786 /*
787  * mono_unwind_get_dwarf_pc_reg:
788  *
789  *   Return the dwarf register number of the register holding the ip of the
790  * previous frame.
791  */
792 int
793 mono_unwind_get_dwarf_pc_reg (void)
794 {
795         return DWARF_PC_REG;
796 }
797
798 static void
799 decode_cie_op (guint8 *p, guint8 **endp)
800 {
801         int op = *p & 0xc0;
802
803         switch (op) {
804         case DW_CFA_advance_loc:
805                 p ++;
806                 break;
807         case DW_CFA_offset:
808                 p ++;
809                 decode_uleb128 (p, &p);
810                 break;
811         case 0: {
812                 int ext_op = *p;
813                 p ++;
814                 switch (ext_op) {
815                 case DW_CFA_def_cfa:
816                         decode_uleb128 (p, &p);
817                         decode_uleb128 (p, &p);
818                         break;
819                 case DW_CFA_def_cfa_offset:
820                         decode_uleb128 (p, &p);
821                         break;
822                 case DW_CFA_def_cfa_register:
823                         decode_uleb128 (p, &p);
824                         break;
825                 case DW_CFA_advance_loc4:
826                         p += 4;
827                         break;
828                 case DW_CFA_offset_extended_sf:
829                         decode_uleb128 (p, &p);
830                         decode_uleb128 (p, &p);
831                         break;
832                 default:
833                         g_assert_not_reached ();
834                 }
835                 break;
836         }
837         default:
838                 g_assert_not_reached ();
839         }
840
841         *endp = p;
842 }
843
844 static gint64
845 read_encoded_val (guint32 encoding, guint8 *p, guint8 **endp)
846 {
847         gint64 res;
848
849         switch (encoding & 0xf) {
850         case DW_EH_PE_sdata8:
851                 res = *(gint64*)p;
852                 p += 8;
853                 break;
854         case DW_EH_PE_sdata4:
855                 res = *(gint32*)p;
856                 p += 4;
857                 break;
858         default:
859                 g_assert_not_reached ();
860         }
861
862         *endp = p;
863         return res;
864 }
865
866 /*
867  * decode_lsda:
868  *
869  *   Decode the Mono specific Language Specific Data Area generated by LLVM.
870  * This function is async safe.
871  */
872 static void
873 decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo *ex_info, gpointer *type_info, guint32 *ex_info_len, int *this_reg, int *this_offset)
874 {
875         guint8 *p;
876         int i, ncall_sites, this_encoding;
877         guint32 mono_magic, version;
878
879         p = lsda;
880
881         /* This is the modified LSDA generated by the LLVM mono branch */
882         mono_magic = decode_uleb128 (p, &p);
883         g_assert (mono_magic == 0x4d4fef4f);
884         version = decode_uleb128 (p, &p);
885         g_assert (version == 1);
886         this_encoding = *p;
887         p ++;
888         if (this_encoding == DW_EH_PE_udata4) {
889                 gint32 op, reg, offset;
890
891                 /* 'this' location */
892                 op = *p;
893                 g_assert (op == DW_OP_bregx);
894                 p ++;
895                 reg = decode_uleb128 (p, &p);
896                 offset = decode_sleb128 (p, &p);
897
898                 *this_reg = mono_dwarf_reg_to_hw_reg (reg);
899                 *this_offset = offset;
900         } else {
901                 g_assert (this_encoding == DW_EH_PE_omit);
902
903                 *this_reg = -1;
904                 *this_offset = -1;
905         }
906         ncall_sites = decode_uleb128 (p, &p);
907         p = (guint8*)ALIGN_TO ((mgreg_t)p, 4);
908
909         if (ex_info_len)
910                 *ex_info_len = ncall_sites;
911
912         for (i = 0; i < ncall_sites; ++i) {
913                 int block_start_offset, block_size, landing_pad;
914                 guint8 *tinfo;
915
916                 block_start_offset = read32 (p);
917                 p += sizeof (gint32);
918                 block_size = read32 (p);
919                 p += sizeof (gint32);
920                 landing_pad = read32 (p);
921                 p += sizeof (gint32);
922                 tinfo = p;
923                 p += sizeof (gint32);
924
925                 g_assert (landing_pad);
926                 g_assert (((size_t)tinfo % 4) == 0);
927                 //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
928
929                 if (ex_info) {
930                         if (type_info)
931                                 type_info [i] = tinfo;
932                         ex_info[i].try_start = code + block_start_offset;
933                         ex_info[i].try_end = code + block_start_offset + block_size;
934                         ex_info[i].handler_start = code + landing_pad;
935                 }
936         }
937 }
938
939 /*
940  * mono_unwind_decode_fde:
941  *
942  *   Decode a DWARF FDE entry, returning the unwind opcodes.
943  * If not NULL, EX_INFO is set to a malloc-ed array of MonoJitExceptionInfo structures,
944  * only try_start, try_end and handler_start is set.
945  * If not NULL, TYPE_INFO is set to a malloc-ed array containing the ttype table from the
946  * LSDA.
947  */
948 guint8*
949 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)
950 {
951         guint8 *p, *cie, *fde_current, *fde_aug = NULL, *code, *fde_cfi, *cie_cfi;
952         gint32 fde_len, cie_offset, pc_begin, pc_range, aug_len;
953         gint32 cie_len, cie_id, cie_version, code_align, data_align, return_reg;
954         gint32 i, cie_aug_len, buf_len;
955         char *cie_aug_str;
956         guint8 *buf;
957         gboolean has_fde_augmentation = FALSE;
958
959         /* 
960          * http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
961          */
962
963         /* This is generated by JITDwarfEmitter::EmitEHFrame () */
964
965         *type_info = NULL;
966         *this_reg = -1;
967         *this_offset = -1;
968
969         /* Decode FDE */
970
971         p = fde;
972         // FIXME: Endianess ?
973         fde_len = *(guint32*)p;
974         g_assert (fde_len != 0xffffffff && fde_len != 0);
975         p += 4;
976         cie_offset = *(guint32*)p;
977         cie = p - cie_offset;
978         p += 4;
979         fde_current = p;
980
981         /* Decode CIE */
982         p = cie;
983         cie_len = *(guint32*)p;
984         p += 4;
985         cie_id = *(guint32*)p;
986         g_assert (cie_id == 0);
987         p += 4;
988         cie_version = *p;
989         g_assert (cie_version == 1);
990         p += 1;
991         cie_aug_str = (char*)p;
992         p += strlen (cie_aug_str) + 1;
993         code_align = decode_uleb128 (p, &p);
994         data_align = decode_sleb128 (p, &p);
995         return_reg = decode_uleb128 (p, &p);
996         if (strstr (cie_aug_str, "z")) {
997                 guint8 *cie_aug;
998                 guint32 p_encoding;
999
1000                 cie_aug_len = decode_uleb128 (p, &p);
1001
1002                 has_fde_augmentation = TRUE;
1003
1004                 cie_aug = p;
1005                 for (i = 0; cie_aug_str [i] != '\0'; ++i) {
1006                         switch (cie_aug_str [i]) {
1007                         case 'z':
1008                                 break;
1009                         case 'P':
1010                                 p_encoding = *p;
1011                                 p ++;
1012                                 read_encoded_val (p_encoding, p, &p);
1013                                 break;
1014                         case 'L':
1015                                 g_assert ((*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel)) || (*p == (DW_EH_PE_sdata8|DW_EH_PE_pcrel)));
1016                                 p ++;
1017                                 break;
1018                         case 'R':
1019                                 g_assert (*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel));
1020                                 p ++;
1021                                 break;
1022                         default:
1023                                 g_assert_not_reached ();
1024                                 break;
1025                         }
1026                 }
1027                         
1028                 p = cie_aug;
1029                 p += cie_aug_len;
1030         }
1031         cie_cfi = p;
1032
1033         /* Continue decoding FDE */
1034         p = fde_current;
1035         /* DW_EH_PE_sdata4|DW_EH_PE_pcrel encoding */
1036         pc_begin = *(gint32*)p;
1037         code = p + pc_begin;
1038         p += 4;
1039         pc_range = *(guint32*)p;
1040         p += 4;
1041         if (has_fde_augmentation) {
1042                 aug_len = decode_uleb128 (p, &p);
1043                 fde_aug = p;
1044                 p += aug_len;
1045         } else {
1046                 aug_len = 0;
1047         }
1048         fde_cfi = p;
1049
1050         if (code_len)
1051                 *code_len = pc_range;
1052
1053         if (ex_info) {
1054                 *ex_info = NULL;
1055                 *ex_info_len = 0;
1056         }
1057
1058         /* Decode FDE augmention */
1059         if (aug_len) {
1060                 gint32 lsda_offset;
1061                 guint8 *lsda;
1062
1063                 /* sdata|pcrel encoding */
1064                 if (aug_len == 4)
1065                         lsda_offset = read32 (fde_aug);
1066                 else if (aug_len == 8)
1067                         lsda_offset = *(gint64*)fde_aug;
1068                 else
1069                         g_assert_not_reached ();
1070                 if (lsda_offset != 0) {
1071                         lsda = fde_aug + lsda_offset;
1072
1073                         /* Get the lengths first */
1074                         guint32 len;
1075                         decode_lsda (lsda, code, NULL, NULL, &len, this_reg, this_offset);
1076
1077                         if (ex_info)
1078                                 *ex_info = (MonoJitExceptionInfo *)g_malloc0 (len * sizeof (MonoJitExceptionInfo));
1079                         if (type_info)
1080                                 *type_info = (gpointer *)g_malloc0 (len * sizeof (gpointer));
1081
1082                         decode_lsda (lsda, code, ex_info ? *ex_info : NULL, type_info ? *type_info : NULL, ex_info_len, this_reg, this_offset);
1083                 }
1084         }
1085
1086         /* Make sure the FDE uses the same constants as we do */
1087         g_assert (code_align == 1);
1088         g_assert (data_align == DWARF_DATA_ALIGN);
1089         g_assert (return_reg == DWARF_PC_REG);
1090
1091         buf_len = (cie + cie_len + 4 - cie_cfi) + (fde + fde_len + 4 - fde_cfi);
1092         buf = (guint8 *)g_malloc0 (buf_len);
1093
1094         i = 0;
1095         p = cie_cfi;
1096         while (p < cie + cie_len + 4) {
1097                 if (*p == DW_CFA_nop)
1098                         break;
1099                 else
1100                         decode_cie_op (p, &p);
1101         }
1102         memcpy (buf + i, cie_cfi, p - cie_cfi);
1103         i += p - cie_cfi;
1104
1105         p = fde_cfi;
1106         while (p < fde + fde_len + 4) {
1107                 if (*p == DW_CFA_nop)
1108                         break;
1109                 else
1110                         decode_cie_op (p, &p);
1111         }
1112         memcpy (buf + i, fde_cfi, p - fde_cfi);
1113         i += p - fde_cfi;
1114         g_assert (i <= buf_len);
1115
1116         *out_len = i;
1117
1118         return (guint8 *)g_realloc (buf, i);
1119 }
1120
1121 /*
1122  * mono_unwind_decode_mono_fde:
1123  *
1124  *   Decode an FDE entry in the LLVM emitted mono EH frame.
1125  * If EI/TYPE_INFO/UNW_INFO are NULL, compute only the value of the scalar fields in INFO.
1126  * Otherwise:
1127  * - Fill out EX_INFO with try_start, try_end and handler_start.
1128  * - Fill out TYPE_INFO with the ttype table from the LSDA.
1129  * - Fill out UNW_INFO with the unwind info.
1130  * This function is async safe.
1131  */
1132 void
1133 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)
1134 {
1135         guint8 *p, *fde_aug, *cie_cfi, *fde_cfi, *buf;
1136         int has_aug, aug_len, cie_cfi_len, fde_cfi_len;
1137         gint32 code_align, data_align, return_reg, pers_encoding;
1138
1139         memset (res, 0, sizeof (*res));
1140         res->this_reg = -1;
1141         res->this_offset = -1;
1142
1143         /* fde points to data emitted by LLVM in DwarfMonoException::EmitMonoEHFrame () */
1144         p = fde;
1145         has_aug = *p;
1146         p ++;
1147         if (has_aug) {
1148                 aug_len = read32 (p);
1149                 p += 4;
1150         } else {
1151                 aug_len = 0;
1152         }
1153         fde_aug = p;
1154         p += aug_len;
1155         fde_cfi = p;
1156
1157         if (has_aug) {
1158                 guint8 *lsda;
1159
1160                 /* The LSDA is embedded directly into the FDE */
1161                 lsda = fde_aug;
1162
1163                 /* Get the lengths first */
1164                 decode_lsda (lsda, code, NULL, NULL, &res->ex_info_len, &res->this_reg, &res->this_offset);
1165
1166                 decode_lsda (lsda, code, ex_info, type_info, NULL, &res->this_reg, &res->this_offset);
1167         }
1168
1169         /* Decode CIE */
1170         p = cie;
1171         code_align = decode_uleb128 (p, &p);
1172         data_align = decode_sleb128 (p, &p);
1173         return_reg = decode_uleb128 (p, &p);
1174         pers_encoding = *p;
1175         p ++;
1176         if (pers_encoding != DW_EH_PE_omit)
1177                 read_encoded_val (pers_encoding, p, &p);
1178
1179         cie_cfi = p;
1180
1181         /* Make sure the FDE uses the same constants as we do */
1182         g_assert (code_align == 1);
1183         g_assert (data_align == DWARF_DATA_ALIGN);
1184         g_assert (return_reg == DWARF_PC_REG);
1185
1186         /* Compute size of CIE unwind info it is DW_CFA_nop terminated */
1187         p = cie_cfi;
1188         while (TRUE) {
1189                 if (*p == DW_CFA_nop)
1190                         break;
1191                 else
1192                         decode_cie_op (p, &p);
1193         }
1194         cie_cfi_len = p - cie_cfi;
1195         fde_cfi_len = (fde + fde_len - fde_cfi);
1196
1197         buf = unw_info;
1198         if (buf) {
1199                 memcpy (buf, cie_cfi, cie_cfi_len);
1200                 memcpy (buf + cie_cfi_len, fde_cfi, fde_cfi_len);
1201         }
1202
1203         res->unw_info_len = cie_cfi_len + fde_cfi_len;
1204 }
1205
1206 /*
1207  * mono_unwind_get_cie_program:
1208  *
1209  *   Get the unwind bytecode for the DWARF CIE.
1210  */
1211 GSList*
1212 mono_unwind_get_cie_program (void)
1213 {
1214 #if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_POWERPC) || defined(TARGET_ARM)
1215         return mono_arch_get_cie_program ();
1216 #else
1217         return NULL;
1218 #endif
1219 }