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