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