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