Merge pull request #4540 from kumpera/android-changes-part1
[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  */
871 static void
872 decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo **ex_info, guint32 *ex_info_len, gpointer **type_info, int *this_reg, int *this_offset)
873 {
874         guint8 *p;
875         int i, ncall_sites, this_encoding;
876         guint32 mono_magic, version;
877
878         p = lsda;
879
880         /* This is the modified LSDA generated by the LLVM mono branch */
881         mono_magic = decode_uleb128 (p, &p);
882         g_assert (mono_magic == 0x4d4fef4f);
883         version = decode_uleb128 (p, &p);
884         g_assert (version == 1);
885         this_encoding = *p;
886         p ++;
887         if (this_encoding == DW_EH_PE_udata4) {
888                 gint32 op, reg, offset;
889
890                 /* 'this' location */
891                 op = *p;
892                 g_assert (op == DW_OP_bregx);
893                 p ++;
894                 reg = decode_uleb128 (p, &p);
895                 offset = decode_sleb128 (p, &p);
896
897                 *this_reg = mono_dwarf_reg_to_hw_reg (reg);
898                 *this_offset = offset;
899         } else {
900                 g_assert (this_encoding == DW_EH_PE_omit);
901
902                 *this_reg = -1;
903                 *this_offset = -1;
904         }
905         ncall_sites = decode_uleb128 (p, &p);
906         p = (guint8*)ALIGN_TO ((mgreg_t)p, 4);
907
908         if (ex_info) {
909                 *ex_info = (MonoJitExceptionInfo *)g_malloc0 (ncall_sites * sizeof (MonoJitExceptionInfo));
910                 *ex_info_len = ncall_sites;
911         }
912         if (type_info)
913                 *type_info = (gpointer *)g_malloc0 (ncall_sites * sizeof (gpointer));
914
915         for (i = 0; i < ncall_sites; ++i) {
916                 int block_start_offset, block_size, landing_pad;
917                 guint8 *tinfo;
918
919                 block_start_offset = read32 (p);
920                 p += sizeof (gint32);
921                 block_size = read32 (p);
922                 p += sizeof (gint32);
923                 landing_pad = read32 (p);
924                 p += sizeof (gint32);
925                 tinfo = p;
926                 p += sizeof (gint32);
927
928                 g_assert (landing_pad);
929                 g_assert (((size_t)tinfo % 4) == 0);
930                 //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
931
932                 if (ex_info) {
933                         if (*type_info)
934                                 (*type_info) [i] = tinfo;
935                         (*ex_info)[i].try_start = code + block_start_offset;
936                         (*ex_info)[i].try_end = code + block_start_offset + block_size;
937                         (*ex_info)[i].handler_start = code + landing_pad;
938                 }
939         }
940 }
941
942 /*
943  * mono_unwind_decode_fde:
944  *
945  *   Decode a DWARF FDE entry, returning the unwind opcodes.
946  * If not NULL, EX_INFO is set to a malloc-ed array of MonoJitExceptionInfo structures,
947  * only try_start, try_end and handler_start is set.
948  * If not NULL, TYPE_INFO is set to a malloc-ed array containing the ttype table from the
949  * LSDA.
950  */
951 guint8*
952 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)
953 {
954         guint8 *p, *cie, *fde_current, *fde_aug = NULL, *code, *fde_cfi, *cie_cfi;
955         gint32 fde_len, cie_offset, pc_begin, pc_range, aug_len;
956         gint32 cie_len, cie_id, cie_version, code_align, data_align, return_reg;
957         gint32 i, cie_aug_len, buf_len;
958         char *cie_aug_str;
959         guint8 *buf;
960         gboolean has_fde_augmentation = FALSE;
961
962         /* 
963          * http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
964          */
965
966         /* This is generated by JITDwarfEmitter::EmitEHFrame () */
967
968         *type_info = NULL;
969         *this_reg = -1;
970         *this_offset = -1;
971
972         /* Decode FDE */
973
974         p = fde;
975         // FIXME: Endianess ?
976         fde_len = *(guint32*)p;
977         g_assert (fde_len != 0xffffffff && fde_len != 0);
978         p += 4;
979         cie_offset = *(guint32*)p;
980         cie = p - cie_offset;
981         p += 4;
982         fde_current = p;
983
984         /* Decode CIE */
985         p = cie;
986         cie_len = *(guint32*)p;
987         p += 4;
988         cie_id = *(guint32*)p;
989         g_assert (cie_id == 0);
990         p += 4;
991         cie_version = *p;
992         g_assert (cie_version == 1);
993         p += 1;
994         cie_aug_str = (char*)p;
995         p += strlen (cie_aug_str) + 1;
996         code_align = decode_uleb128 (p, &p);
997         data_align = decode_sleb128 (p, &p);
998         return_reg = decode_uleb128 (p, &p);
999         if (strstr (cie_aug_str, "z")) {
1000                 guint8 *cie_aug;
1001                 guint32 p_encoding;
1002
1003                 cie_aug_len = decode_uleb128 (p, &p);
1004
1005                 has_fde_augmentation = TRUE;
1006
1007                 cie_aug = p;
1008                 for (i = 0; cie_aug_str [i] != '\0'; ++i) {
1009                         switch (cie_aug_str [i]) {
1010                         case 'z':
1011                                 break;
1012                         case 'P':
1013                                 p_encoding = *p;
1014                                 p ++;
1015                                 read_encoded_val (p_encoding, p, &p);
1016                                 break;
1017                         case 'L':
1018                                 g_assert ((*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel)) || (*p == (DW_EH_PE_sdata8|DW_EH_PE_pcrel)));
1019                                 p ++;
1020                                 break;
1021                         case 'R':
1022                                 g_assert (*p == (DW_EH_PE_sdata4|DW_EH_PE_pcrel));
1023                                 p ++;
1024                                 break;
1025                         default:
1026                                 g_assert_not_reached ();
1027                                 break;
1028                         }
1029                 }
1030                         
1031                 p = cie_aug;
1032                 p += cie_aug_len;
1033         }
1034         cie_cfi = p;
1035
1036         /* Continue decoding FDE */
1037         p = fde_current;
1038         /* DW_EH_PE_sdata4|DW_EH_PE_pcrel encoding */
1039         pc_begin = *(gint32*)p;
1040         code = p + pc_begin;
1041         p += 4;
1042         pc_range = *(guint32*)p;
1043         p += 4;
1044         if (has_fde_augmentation) {
1045                 aug_len = decode_uleb128 (p, &p);
1046                 fde_aug = p;
1047                 p += aug_len;
1048         } else {
1049                 aug_len = 0;
1050         }
1051         fde_cfi = p;
1052
1053         if (code_len)
1054                 *code_len = pc_range;
1055
1056         if (ex_info) {
1057                 *ex_info = NULL;
1058                 *ex_info_len = 0;
1059         }
1060
1061         /* Decode FDE augmention */
1062         if (aug_len) {
1063                 gint32 lsda_offset;
1064                 guint8 *lsda;
1065
1066                 /* sdata|pcrel encoding */
1067                 if (aug_len == 4)
1068                         lsda_offset = read32 (fde_aug);
1069                 else if (aug_len == 8)
1070                         lsda_offset = *(gint64*)fde_aug;
1071                 else
1072                         g_assert_not_reached ();
1073                 if (lsda_offset != 0) {
1074                         lsda = fde_aug + lsda_offset;
1075
1076                         decode_lsda (lsda, code, ex_info, ex_info_len, type_info, this_reg, this_offset);
1077                 }
1078         }
1079
1080         /* Make sure the FDE uses the same constants as we do */
1081         g_assert (code_align == 1);
1082         g_assert (data_align == DWARF_DATA_ALIGN);
1083         g_assert (return_reg == DWARF_PC_REG);
1084
1085         buf_len = (cie + cie_len + 4 - cie_cfi) + (fde + fde_len + 4 - fde_cfi);
1086         buf = (guint8 *)g_malloc0 (buf_len);
1087
1088         i = 0;
1089         p = cie_cfi;
1090         while (p < cie + cie_len + 4) {
1091                 if (*p == DW_CFA_nop)
1092                         break;
1093                 else
1094                         decode_cie_op (p, &p);
1095         }
1096         memcpy (buf + i, cie_cfi, p - cie_cfi);
1097         i += p - cie_cfi;
1098
1099         p = fde_cfi;
1100         while (p < fde + fde_len + 4) {
1101                 if (*p == DW_CFA_nop)
1102                         break;
1103                 else
1104                         decode_cie_op (p, &p);
1105         }
1106         memcpy (buf + i, fde_cfi, p - fde_cfi);
1107         i += p - fde_cfi;
1108         g_assert (i <= buf_len);
1109
1110         *out_len = i;
1111
1112         return (guint8 *)g_realloc (buf, i);
1113 }
1114
1115 /*
1116  * mono_unwind_decode_mono_fde:
1117  *
1118  *   Decode an FDE entry in the LLVM emitted mono EH frame.
1119  * info->ex_info is set to a malloc-ed array of MonoJitExceptionInfo structures,
1120  * only try_start, try_end and handler_start is set.
1121  * info->type_info is set to a malloc-ed array containing the ttype table from the
1122  * LSDA.
1123  */
1124 void
1125 mono_unwind_decode_llvm_mono_fde (guint8 *fde, int fde_len, guint8 *cie, guint8 *code, MonoLLVMFDEInfo *res)
1126 {
1127         guint8 *p, *fde_aug, *cie_cfi, *fde_cfi, *buf;
1128         int has_aug, aug_len, cie_cfi_len, fde_cfi_len;
1129         gint32 code_align, data_align, return_reg, pers_encoding;
1130
1131         memset (res, 0, sizeof (*res));
1132         res->this_reg = -1;
1133         res->this_offset = -1;
1134
1135         /* fde points to data emitted by LLVM in DwarfMonoException::EmitMonoEHFrame () */
1136         p = fde;
1137         has_aug = *p;
1138         p ++;
1139         if (has_aug) {
1140                 aug_len = read32 (p);
1141                 p += 4;
1142         } else {
1143                 aug_len = 0;
1144         }
1145         fde_aug = p;
1146         p += aug_len;
1147         fde_cfi = p;
1148
1149         if (has_aug) {
1150                 guint8 *lsda;
1151
1152                 /* The LSDA is embedded directly into the FDE */
1153                 lsda = fde_aug;
1154
1155                 decode_lsda (lsda, code, &res->ex_info, &res->ex_info_len, &res->type_info, &res->this_reg, &res->this_offset);
1156         }
1157
1158         /* Decode CIE */
1159         p = cie;
1160         code_align = decode_uleb128 (p, &p);
1161         data_align = decode_sleb128 (p, &p);
1162         return_reg = decode_uleb128 (p, &p);
1163         pers_encoding = *p;
1164         p ++;
1165         if (pers_encoding != DW_EH_PE_omit)
1166                 read_encoded_val (pers_encoding, p, &p);
1167
1168         cie_cfi = p;
1169
1170         /* Make sure the FDE uses the same constants as we do */
1171         g_assert (code_align == 1);
1172         g_assert (data_align == DWARF_DATA_ALIGN);
1173         g_assert (return_reg == DWARF_PC_REG);
1174
1175         /* Compute size of CIE unwind info it is DW_CFA_nop terminated */
1176         p = cie_cfi;
1177         while (TRUE) {
1178                 if (*p == DW_CFA_nop)
1179                         break;
1180                 else
1181                         decode_cie_op (p, &p);
1182         }
1183         cie_cfi_len = p - cie_cfi;
1184         fde_cfi_len = (fde + fde_len - fde_cfi);
1185
1186         buf = (guint8 *)g_malloc0 (cie_cfi_len + fde_cfi_len);
1187         memcpy (buf, cie_cfi, cie_cfi_len);
1188         memcpy (buf + cie_cfi_len, fde_cfi, fde_cfi_len);
1189
1190         res->unw_info_len = cie_cfi_len + fde_cfi_len;
1191         res->unw_info = buf;
1192 }
1193
1194 /*
1195  * mono_unwind_get_cie_program:
1196  *
1197  *   Get the unwind bytecode for the DWARF CIE.
1198  */
1199 GSList*
1200 mono_unwind_get_cie_program (void)
1201 {
1202 #if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_POWERPC) || defined(TARGET_ARM)
1203         return mono_arch_get_cie_program ();
1204 #else
1205         return NULL;
1206 #endif
1207 }