2001-04-09 Andrew MacLeod <amacleod@redhat.com>
[official-gcc.git] / gcc / unwind-dw2.c
blobe2f20c9ee107306a6bd7db48fbb68a8476ad1ad4
1 /* DWARF2 exception handling and frame unwind runtime interface routines.
2 Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include "tconfig.h"
22 #include "tsystem.h"
23 #include "dwarf2.h"
24 #include "unwind.h"
25 #include "unwind-dw2-fde.h"
26 #include "gthr.h"
29 #if !USING_SJLJ_EXCEPTIONS
31 #ifndef STACK_GROWS_DOWNWARD
32 #define STACK_GROWS_DOWNWARD 0
33 #else
34 #undef STACK_GROWS_DOWNWARD
35 #define STACK_GROWS_DOWNWARD 1
36 #endif
38 /* A target can override (perhaps for backward compatibility) how
39 many dwarf2 columns are unwound. */
40 #ifndef DWARF_FRAME_REGISTERS
41 #define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
42 #endif
44 /* This is the register and unwind state for a particular frame. */
45 struct _Unwind_Context
47 void *reg[DWARF_FRAME_REGISTERS+1];
48 void *cfa;
49 void *ra;
50 void *lsda;
51 struct dwarf_eh_bases bases;
52 _Unwind_Word args_size;
55 /* Byte size of every register managed by these routines. */
56 static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS];
59 /* The result of interpreting the frame unwind info for a frame.
60 This is all symbolic at this point, as none of the values can
61 be resolved until the target pc is located. */
62 typedef struct
64 /* Each register save state can be described in terms of a CFA slot,
65 another register, or a location expression. */
66 struct frame_state_reg_info
68 struct {
69 union {
70 unsigned int reg;
71 _Unwind_Sword offset;
72 unsigned char *exp;
73 } loc;
74 enum {
75 REG_UNSAVED,
76 REG_SAVED_OFFSET,
77 REG_SAVED_REG,
78 REG_SAVED_EXP,
79 } how;
80 } reg[DWARF_FRAME_REGISTERS+1];
82 /* Used to implement DW_CFA_remember_state. */
83 struct frame_state_reg_info *prev;
84 } regs;
86 /* The CFA can be described in terms of a reg+offset or a
87 location expression. */
88 _Unwind_Sword cfa_offset;
89 _Unwind_Word cfa_reg;
90 unsigned char *cfa_exp;
91 enum {
92 CFA_UNSET,
93 CFA_REG_OFFSET,
94 CFA_EXP,
95 } cfa_how;
97 /* The PC described by the current frame state. */
98 void *pc;
100 /* The information we care about from the CIE/FDE. */
101 _Unwind_Personality_Fn personality;
102 signed int data_align;
103 unsigned int code_align;
104 unsigned char retaddr_column;
105 unsigned char addr_encoding;
106 unsigned char saw_z;
107 unsigned char saw_lsda;
108 } _Unwind_FrameState;
110 /* Decode the unsigned LEB128 constant at BUF into the variable pointed to
111 by R, and return the new value of BUF. */
113 static unsigned char *
114 read_uleb128 (unsigned char *buf, _Unwind_Word *r)
116 unsigned shift = 0;
117 _Unwind_Word result = 0;
119 while (1)
121 unsigned char byte = *buf++;
122 result |= (byte & 0x7f) << shift;
123 if ((byte & 0x80) == 0)
124 break;
125 shift += 7;
127 *r = result;
128 return buf;
131 /* Decode the signed LEB128 constant at BUF into the variable pointed to
132 by R, and return the new value of BUF. */
134 static unsigned char *
135 read_sleb128 (unsigned char *buf, _Unwind_Sword *r)
137 unsigned shift = 0;
138 _Unwind_Sword result = 0;
139 unsigned char byte;
141 while (1)
143 byte = *buf++;
144 result |= (byte & 0x7f) << shift;
145 shift += 7;
146 if ((byte & 0x80) == 0)
147 break;
149 if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
150 result |= - (1 << shift);
152 *r = result;
153 return buf;
156 /* Read unaligned data from the instruction buffer. */
158 union unaligned
160 void *p;
161 unsigned u2 __attribute__ ((mode (HI)));
162 unsigned u4 __attribute__ ((mode (SI)));
163 unsigned u8 __attribute__ ((mode (DI)));
164 signed s2 __attribute__ ((mode (HI)));
165 signed s4 __attribute__ ((mode (SI)));
166 signed s8 __attribute__ ((mode (DI)));
167 } __attribute__ ((packed));
169 static inline void *
170 read_pointer (void *p) { union unaligned *up = p; return up->p; }
172 static inline int
173 read_1u (void *p) { return *(unsigned char *)p; }
175 static inline int
176 read_1s (void *p) { return *(signed char *)p; }
178 static inline int
179 read_2u (void *p) { union unaligned *up = p; return up->u2; }
181 static inline int
182 read_2s (void *p) { union unaligned *up = p; return up->s2; }
184 static inline unsigned int
185 read_4u (void *p) { union unaligned *up = p; return up->u4; }
187 static inline int
188 read_4s (void *p) { union unaligned *up = p; return up->s4; }
190 static inline unsigned long
191 read_8u (void *p) { union unaligned *up = p; return up->u8; }
193 static inline unsigned long
194 read_8s (void *p) { union unaligned *up = p; return up->s8; }
196 static unsigned char *
197 read_encoded_pointer (unsigned char *p, unsigned char encoding,
198 struct dwarf_eh_bases *bases, void **pptr)
200 signed long val;
201 unsigned char *ret;
203 switch (encoding & 0x0f)
205 case DW_EH_PE_absptr:
206 val = (_Unwind_Ptr) read_pointer (p);
207 ret = p + sizeof (void *);
208 break;
210 case DW_EH_PE_uleb128:
211 ret = read_uleb128 (p, &val);
212 break;
213 case DW_EH_PE_sleb128:
214 ret = read_sleb128 (p, &val);
215 break;
217 case DW_EH_PE_udata2:
218 val = read_2u (p);
219 ret = p + 2;
220 break;
221 case DW_EH_PE_udata4:
222 val = read_4u (p);
223 ret = p + 4;
224 break;
225 case DW_EH_PE_udata8:
226 val = read_8u (p);
227 ret = p + 8;
228 break;
230 case DW_EH_PE_sdata2:
231 val = read_2s (p);
232 ret = p + 2;
233 break;
234 case DW_EH_PE_sdata4:
235 val = read_4s (p);
236 ret = p + 4;
237 break;
238 case DW_EH_PE_sdata8:
239 val = read_8s (p);
240 ret = p + 8;
241 break;
243 default:
244 abort ();
247 if (val != 0)
248 switch (encoding & 0xf0)
250 case DW_EH_PE_absptr:
251 break;
252 case DW_EH_PE_pcrel:
253 val += (_Unwind_Ptr) p;
254 break;
255 case DW_EH_PE_textrel:
256 val += (_Unwind_Ptr) bases->tbase;
257 break;
258 case DW_EH_PE_datarel:
259 val += (_Unwind_Ptr) bases->dbase;
260 break;
261 case DW_EH_PE_funcrel:
262 val += (_Unwind_Ptr) bases->func;
263 break;
264 default:
265 abort ();
268 *pptr = (void *) (_Unwind_Ptr) val;
269 return ret;
272 /* Get the value of register REG as saved in CONTEXT. */
274 inline _Unwind_Word
275 _Unwind_GetGR (struct _Unwind_Context *context, int index)
277 /* This will segfault if the register hasn't been saved. */
278 return * (_Unwind_Word *) context->reg[index];
281 /* Overwrite the saved value for register REG in CONTEXT with VAL. */
283 inline void
284 _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
286 * (_Unwind_Word *) context->reg[index] = val;
289 /* Retrieve the return address for CONTEXT. */
291 inline _Unwind_Ptr
292 _Unwind_GetIP (struct _Unwind_Context *context)
294 return (_Unwind_Ptr) context->ra;
297 /* Overwrite the return address for CONTEXT with VAL. */
299 inline void
300 _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
302 context->ra = (void *) val;
305 void *
306 _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
308 return context->lsda;
311 _Unwind_Ptr
312 _Unwind_GetRegionStart (struct _Unwind_Context *context)
314 return (_Unwind_Ptr) context->bases.func;
318 /* Extract any interesting information from the CIE for the translation
319 unit F belongs to. Return a pointer to the byte after the augmentation,
320 or NULL if we encountered an undecipherable augmentation. */
322 static unsigned char *
323 extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context,
324 _Unwind_FrameState *fs)
326 unsigned char *aug = cie->augmentation;
327 unsigned char *p = aug + strlen (aug) + 1;
328 unsigned char *ret = NULL;
329 _Unwind_Word code_align;
330 _Unwind_Sword data_align;
332 /* Immediately following the augmentation are the code and
333 data alignment and return address column. */
334 p = read_uleb128 (p, &code_align);
335 p = read_sleb128 (p, &data_align);
336 fs->code_align = code_align;
337 fs->data_align = data_align;
338 fs->retaddr_column = *p++;
340 /* If the augmentation starts with 'z', then a uleb128 immediately
341 follows containing the length of the augmentation field following
342 the size. */
343 if (*aug == 'z')
345 _Unwind_Word i;
346 p = read_uleb128 (p, &i);
347 ret = p + i;
349 fs->saw_z = 1;
350 ++aug;
353 /* Iterate over recognized augmentation subsequences. */
354 while (*aug != '\0')
356 /* "eh" was used by g++ v2; recognize and skip. */
357 if (aug[0] == 'e' && aug[1] == 'h')
359 p += sizeof (void *);
360 aug += 2;
363 /* "R" indicates a byte indicating how addresses are encoded. */
364 else if (aug[0] == 'R')
366 fs->addr_encoding = *p++;
367 aug += 1;
370 /* "P" indicates a personality routine in the CIE augmentation
371 and an lsda pointer in the FDE augmentation. */
372 else if (aug[0] == 'P')
374 p = read_encoded_pointer (p, fs->addr_encoding, &context->bases,
375 (void **) &fs->personality);
376 fs->saw_lsda = 1;
377 aug += 1;
380 /* Otherwise we have an unknown augmentation string.
381 Bail unless we saw a 'z' prefix. */
382 else
383 return ret;
386 return ret ? ret : p;
390 /* Decode a DW_OP stack program. Return the top of stack. Push INITIAL
391 onto the stack to start. */
393 static _Unwind_Word
394 execute_stack_op (unsigned char *op_ptr, unsigned char *op_end,
395 struct _Unwind_Context *context, _Unwind_Word initial)
397 _Unwind_Word stack[64]; /* ??? Assume this is enough. */
398 int stack_elt;
400 stack[0] = initial;
401 stack_elt = 1;
403 while (op_ptr < op_end)
405 enum dwarf_location_atom op = *op_ptr++;
406 _Unwind_Word result, reg;
407 _Unwind_Sword offset;
409 switch (op)
411 case DW_OP_lit0:
412 case DW_OP_lit1:
413 case DW_OP_lit2:
414 case DW_OP_lit3:
415 case DW_OP_lit4:
416 case DW_OP_lit5:
417 case DW_OP_lit6:
418 case DW_OP_lit7:
419 case DW_OP_lit8:
420 case DW_OP_lit9:
421 case DW_OP_lit10:
422 case DW_OP_lit11:
423 case DW_OP_lit12:
424 case DW_OP_lit13:
425 case DW_OP_lit14:
426 case DW_OP_lit15:
427 case DW_OP_lit16:
428 case DW_OP_lit17:
429 case DW_OP_lit18:
430 case DW_OP_lit19:
431 case DW_OP_lit20:
432 case DW_OP_lit21:
433 case DW_OP_lit22:
434 case DW_OP_lit23:
435 case DW_OP_lit24:
436 case DW_OP_lit25:
437 case DW_OP_lit26:
438 case DW_OP_lit27:
439 case DW_OP_lit28:
440 case DW_OP_lit29:
441 case DW_OP_lit30:
442 case DW_OP_lit31:
443 result = op - DW_OP_lit0;
444 break;
446 case DW_OP_addr:
447 result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
448 op_ptr += sizeof (void *);
449 break;
451 case DW_OP_const1u:
452 result = read_1u (op_ptr);
453 op_ptr += 1;
454 break;
455 case DW_OP_const1s:
456 result = read_1s (op_ptr);
457 op_ptr += 1;
458 break;
459 case DW_OP_const2u:
460 result = read_2u (op_ptr);
461 op_ptr += 2;
462 break;
463 case DW_OP_const2s:
464 result = read_2s (op_ptr);
465 op_ptr += 2;
466 break;
467 case DW_OP_const4u:
468 result = read_4u (op_ptr);
469 op_ptr += 4;
470 break;
471 case DW_OP_const4s:
472 result = read_4s (op_ptr);
473 op_ptr += 4;
474 break;
475 case DW_OP_const8u:
476 result = read_8u (op_ptr);
477 op_ptr += 8;
478 break;
479 case DW_OP_const8s:
480 result = read_8s (op_ptr);
481 op_ptr += 8;
482 break;
483 case DW_OP_constu:
484 op_ptr = read_uleb128 (op_ptr, &result);
485 break;
486 case DW_OP_consts:
487 op_ptr = read_sleb128 (op_ptr, &offset);
488 result = offset;
489 break;
491 case DW_OP_reg0:
492 case DW_OP_reg1:
493 case DW_OP_reg2:
494 case DW_OP_reg3:
495 case DW_OP_reg4:
496 case DW_OP_reg5:
497 case DW_OP_reg6:
498 case DW_OP_reg7:
499 case DW_OP_reg8:
500 case DW_OP_reg9:
501 case DW_OP_reg10:
502 case DW_OP_reg11:
503 case DW_OP_reg12:
504 case DW_OP_reg13:
505 case DW_OP_reg14:
506 case DW_OP_reg15:
507 case DW_OP_reg16:
508 case DW_OP_reg17:
509 case DW_OP_reg18:
510 case DW_OP_reg19:
511 case DW_OP_reg20:
512 case DW_OP_reg21:
513 case DW_OP_reg22:
514 case DW_OP_reg23:
515 case DW_OP_reg24:
516 case DW_OP_reg25:
517 case DW_OP_reg26:
518 case DW_OP_reg27:
519 case DW_OP_reg28:
520 case DW_OP_reg29:
521 case DW_OP_reg30:
522 case DW_OP_reg31:
523 result = _Unwind_GetGR (context, op - DW_OP_reg0);
524 break;
525 case DW_OP_regx:
526 op_ptr = read_uleb128 (op_ptr, &reg);
527 result = _Unwind_GetGR (context, reg);
528 break;
530 case DW_OP_breg0:
531 case DW_OP_breg1:
532 case DW_OP_breg2:
533 case DW_OP_breg3:
534 case DW_OP_breg4:
535 case DW_OP_breg5:
536 case DW_OP_breg6:
537 case DW_OP_breg7:
538 case DW_OP_breg8:
539 case DW_OP_breg9:
540 case DW_OP_breg10:
541 case DW_OP_breg11:
542 case DW_OP_breg12:
543 case DW_OP_breg13:
544 case DW_OP_breg14:
545 case DW_OP_breg15:
546 case DW_OP_breg16:
547 case DW_OP_breg17:
548 case DW_OP_breg18:
549 case DW_OP_breg19:
550 case DW_OP_breg20:
551 case DW_OP_breg21:
552 case DW_OP_breg22:
553 case DW_OP_breg23:
554 case DW_OP_breg24:
555 case DW_OP_breg25:
556 case DW_OP_breg26:
557 case DW_OP_breg27:
558 case DW_OP_breg28:
559 case DW_OP_breg29:
560 case DW_OP_breg30:
561 case DW_OP_breg31:
562 op_ptr = read_sleb128 (op_ptr, &offset);
563 result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
564 break;
565 case DW_OP_bregx:
566 op_ptr = read_uleb128 (op_ptr, &reg);
567 op_ptr = read_sleb128 (op_ptr, &offset);
568 result = _Unwind_GetGR (context, reg) + offset;
569 break;
571 case DW_OP_dup:
572 if (stack_elt < 1)
573 abort ();
574 result = stack[stack_elt - 1];
575 break;
577 case DW_OP_drop:
578 if (--stack_elt < 0)
579 abort ();
580 goto no_push;
582 case DW_OP_pick:
583 offset = *op_ptr++;
584 if (offset >= stack_elt - 1)
585 abort ();
586 result = stack[stack_elt - 1 - offset];
587 break;
589 case DW_OP_over:
590 if (stack_elt < 2)
591 abort ();
592 result = stack[stack_elt - 2];
593 break;
595 case DW_OP_rot:
597 _Unwind_Word t1, t2, t3;
599 if (stack_elt < 3)
600 abort ();
601 t1 = stack[stack_elt - 1];
602 t2 = stack[stack_elt - 2];
603 t3 = stack[stack_elt - 3];
604 stack[stack_elt - 1] = t2;
605 stack[stack_elt - 2] = t3;
606 stack[stack_elt - 3] = t1;
607 goto no_push;
610 case DW_OP_deref:
611 case DW_OP_deref_size:
612 case DW_OP_abs:
613 case DW_OP_neg:
614 case DW_OP_not:
615 case DW_OP_plus_uconst:
616 /* Unary operations. */
617 if (--stack_elt < 0)
618 abort ();
619 result = stack[stack_elt];
621 switch (op)
623 case DW_OP_deref:
625 void *ptr = (void *)(_Unwind_Ptr) result;
626 result = (_Unwind_Ptr) read_pointer (ptr);
628 break;
630 case DW_OP_deref_size:
632 void *ptr = (void *)(_Unwind_Ptr) result;
633 switch (*op_ptr++)
635 case 1:
636 result = read_1u (ptr);
637 break;
638 case 2:
639 result = read_2u (ptr);
640 break;
641 case 4:
642 result = read_4u (ptr);
643 break;
644 case 8:
645 result = read_8u (ptr);
646 break;
647 default:
648 abort ();
651 break;
653 case DW_OP_abs:
654 if ((_Unwind_Sword) result < 0)
655 result = -result;
656 break;
657 case DW_OP_neg:
658 result = -result;
659 break;
660 case DW_OP_not:
661 result = ~result;
662 break;
663 case DW_OP_plus_uconst:
664 op_ptr = read_uleb128 (op_ptr, &reg);
665 result += reg;
666 break;
668 break;
670 case DW_OP_and:
671 case DW_OP_div:
672 case DW_OP_minus:
673 case DW_OP_mod:
674 case DW_OP_mul:
675 case DW_OP_or:
676 case DW_OP_plus:
677 case DW_OP_le:
678 case DW_OP_ge:
679 case DW_OP_eq:
680 case DW_OP_lt:
681 case DW_OP_gt:
682 case DW_OP_ne:
684 /* Binary operations. */
685 _Unwind_Word first, second;
686 if ((stack_elt -= 2) < 0)
687 abort ();
688 second = stack[stack_elt];
689 first = stack[stack_elt + 1];
691 switch (op)
693 case DW_OP_and:
694 result = second & first;
695 break;
696 case DW_OP_div:
697 result = (_Unwind_Sword)second / (_Unwind_Sword)first;
698 break;
699 case DW_OP_minus:
700 result = second - first;
701 break;
702 case DW_OP_mod:
703 result = (_Unwind_Sword)second % (_Unwind_Sword)first;
704 break;
705 case DW_OP_mul:
706 result = second * first;
707 break;
708 case DW_OP_or:
709 result = second | first;
710 break;
711 case DW_OP_plus:
712 result = second + first;
713 break;
714 case DW_OP_shl:
715 result = second << first;
716 break;
717 case DW_OP_shr:
718 result = second >> first;
719 break;
720 case DW_OP_shra:
721 result = (_Unwind_Sword)second >> first;
722 break;
723 case DW_OP_xor:
724 result = second ^ first;
725 break;
726 case DW_OP_le:
727 result = (_Unwind_Sword)first <= (_Unwind_Sword)second;
728 break;
729 case DW_OP_ge:
730 result = (_Unwind_Sword)first >= (_Unwind_Sword)second;
731 break;
732 case DW_OP_eq:
733 result = (_Unwind_Sword)first == (_Unwind_Sword)second;
734 break;
735 case DW_OP_lt:
736 result = (_Unwind_Sword)first < (_Unwind_Sword)second;
737 break;
738 case DW_OP_gt:
739 result = (_Unwind_Sword)first > (_Unwind_Sword)second;
740 break;
741 case DW_OP_ne:
742 result = (_Unwind_Sword)first != (_Unwind_Sword)second;
743 break;
746 break;
748 case DW_OP_skip:
749 offset = read_2s (op_ptr);
750 op_ptr += 2;
751 op_ptr += offset;
752 goto no_push;
754 case DW_OP_bra:
755 if (--stack_elt < 0)
756 abort ();
757 offset = read_2s (op_ptr);
758 op_ptr += 2;
759 if (stack[stack_elt] != 0)
760 op_ptr += offset;
761 goto no_push;
763 case DW_OP_nop:
764 goto no_push;
766 default:
767 abort ();
770 /* Most things push a result value. */
771 if ((size_t) stack_elt >= sizeof(stack)/sizeof(*stack))
772 abort ();
773 stack[++stack_elt] = result;
774 no_push:;
777 /* We were executing this program to get a value. It should be
778 at top of stack. */
779 if (--stack_elt < 0)
780 abort ();
781 return stack[stack_elt];
785 /* Decode DWARF 2 call frame information. Takes pointers the
786 instruction sequence to decode, current register information and
787 CIE info, and the PC range to evaluate. */
789 static void
790 execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end,
791 struct _Unwind_Context *context, _Unwind_FrameState *fs)
793 struct frame_state_reg_info *unused_rs = NULL;
795 /* Don't allow remember/restore between CIE and FDE programs. */
796 fs->regs.prev = NULL;
798 while (insn_ptr < insn_end && fs->pc < context->ra)
800 unsigned char insn = *insn_ptr++;
801 _Unwind_Word reg, uoffset;
802 _Unwind_Sword offset;
804 if (insn & DW_CFA_advance_loc)
805 fs->pc += (insn & 0x3f) * fs->code_align;
806 else if (insn & DW_CFA_offset)
808 reg = insn & 0x3f;
809 insn_ptr = read_uleb128 (insn_ptr, &uoffset);
810 offset = (_Unwind_Sword)uoffset * fs->data_align;
811 fs->regs.reg[reg].how = REG_SAVED_OFFSET;
812 fs->regs.reg[reg].loc.offset = offset;
814 else if (insn & DW_CFA_restore)
816 reg = insn & 0x3f;
817 fs->regs.reg[reg].how = REG_UNSAVED;
819 else switch (insn)
821 case DW_CFA_set_loc:
822 insn_ptr = read_encoded_pointer (insn_ptr, fs->addr_encoding,
823 &context->bases, &fs->pc);
824 break;
826 case DW_CFA_advance_loc1:
827 fs->pc += read_1u (insn_ptr);
828 insn_ptr += 1;
829 break;
830 case DW_CFA_advance_loc2:
831 fs->pc += read_2u (insn_ptr);
832 insn_ptr += 2;
833 break;
834 case DW_CFA_advance_loc4:
835 fs->pc += read_4u (insn_ptr);
836 insn_ptr += 4;
837 break;
839 case DW_CFA_offset_extended:
840 insn_ptr = read_uleb128 (insn_ptr, &reg);
841 insn_ptr = read_uleb128 (insn_ptr, &uoffset);
842 offset = (_Unwind_Sword)uoffset * fs->data_align;
843 fs->regs.reg[reg].how = REG_SAVED_OFFSET;
844 fs->regs.reg[reg].loc.offset = offset;
845 break;
847 case DW_CFA_restore_extended:
848 insn_ptr = read_uleb128 (insn_ptr, &reg);
849 fs->regs.reg[reg].how = REG_UNSAVED;
850 break;
852 case DW_CFA_undefined:
853 case DW_CFA_same_value:
854 case DW_CFA_nop:
855 break;
857 case DW_CFA_register:
859 _Unwind_Word reg2;
860 insn_ptr = read_uleb128 (insn_ptr, &reg);
861 insn_ptr = read_uleb128 (insn_ptr, &reg2);
862 fs->regs.reg[reg].how = REG_SAVED_REG;
863 fs->regs.reg[reg].loc.reg = reg2;
865 break;
867 case DW_CFA_remember_state:
869 struct frame_state_reg_info *new_rs;
870 if (unused_rs)
872 new_rs = unused_rs;
873 unused_rs = unused_rs->prev;
875 else
876 new_rs = alloca (sizeof (struct frame_state_reg_info));
878 *new_rs = fs->regs;
879 fs->regs.prev = new_rs;
881 break;
883 case DW_CFA_restore_state:
885 struct frame_state_reg_info *old_rs = fs->regs.prev;
886 fs->regs = *old_rs;
887 old_rs->prev = unused_rs;
888 unused_rs = old_rs;
890 break;
892 case DW_CFA_def_cfa:
893 insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
894 insn_ptr = read_uleb128 (insn_ptr, &uoffset);
895 fs->cfa_offset = uoffset;
896 fs->cfa_how = CFA_REG_OFFSET;
897 break;
899 case DW_CFA_def_cfa_register:
900 insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
901 fs->cfa_how = CFA_REG_OFFSET;
902 break;
904 case DW_CFA_def_cfa_offset:
905 insn_ptr = read_uleb128 (insn_ptr, &uoffset);
906 fs->cfa_offset = uoffset;
907 /* cfa_how deliberately not set. */
908 break;
910 case DW_CFA_def_cfa_expression:
911 insn_ptr = read_uleb128 (insn_ptr, &uoffset);
912 fs->cfa_exp = insn_ptr;
913 fs->cfa_how = CFA_EXP;
914 insn_ptr += uoffset;
915 break;
917 case DW_CFA_expression:
918 insn_ptr = read_uleb128 (insn_ptr, &reg);
919 insn_ptr = read_uleb128 (insn_ptr, &uoffset);
920 fs->regs.reg[reg].how = REG_SAVED_EXP;
921 fs->regs.reg[reg].loc.exp = insn_ptr;
922 insn_ptr += uoffset;
923 break;
925 /* From the 2.1 draft. */
926 case DW_CFA_offset_extended_sf:
927 insn_ptr = read_uleb128 (insn_ptr, &reg);
928 insn_ptr = read_sleb128 (insn_ptr, &offset);
929 offset *= fs->data_align;
930 fs->regs.reg[reg].how = REG_SAVED_OFFSET;
931 fs->regs.reg[reg].loc.offset = offset;
932 break;
934 case DW_CFA_def_cfa_sf:
935 insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
936 insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset);
937 fs->cfa_how = CFA_REG_OFFSET;
938 break;
940 case DW_CFA_def_cfa_offset_sf:
941 insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_offset);
942 /* cfa_how deliberately not set. */
943 break;
945 case DW_CFA_GNU_window_save:
946 /* ??? Hardcoded for SPARC register window configuration. */
947 for (reg = 16; reg < 32; ++reg)
949 fs->regs.reg[reg].how = REG_SAVED_OFFSET;
950 fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
952 break;
954 case DW_CFA_GNU_args_size:
955 insn_ptr = read_uleb128 (insn_ptr, &context->args_size);
956 break;
958 case DW_CFA_GNU_negative_offset_extended:
959 /* Obsoleted by DW_CFA_offset_extended_sf, but used by
960 older PowerPC code. */
961 insn_ptr = read_uleb128 (insn_ptr, &reg);
962 insn_ptr = read_uleb128 (insn_ptr, &uoffset);
963 offset = (_Unwind_Sword)uoffset * fs->data_align;
964 fs->regs.reg[reg].how = REG_SAVED_OFFSET;
965 fs->regs.reg[reg].loc.offset = -offset;
966 break;
968 default:
969 abort ();
974 static _Unwind_Reason_Code
975 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
977 struct dwarf_fde *fde;
978 struct dwarf_cie *cie;
979 unsigned char *aug, *insn, *end;
981 memset (fs, 0, sizeof (*fs));
982 context->args_size = 0;
983 context->lsda = 0;
985 fde = _Unwind_Find_FDE (context->ra - 1, &context->bases);
986 if (fde == NULL)
988 /* Couldn't find frame unwind info for this function. Try a
989 target-specific fallback mechanism. This will necessarily
990 not profide a personality routine or LSDA. */
991 #ifdef MD_FALLBACK_FRAME_STATE_FOR
992 MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
993 return _URC_END_OF_STACK;
994 success:
995 return _URC_NO_REASON;
996 #else
997 return _URC_END_OF_STACK;
998 #endif
1001 context->bases.func = fde->pc_begin;
1002 fs->pc = fde->pc_begin;
1004 cie = get_cie (fde);
1005 insn = extract_cie_info (cie, context, fs);
1006 if (insn == NULL)
1007 /* CIE contained unknown augmentation. */
1008 return _URC_FATAL_PHASE1_ERROR;
1010 /* First decode all the insns in the CIE. */
1011 end = (unsigned char *) next_fde ((struct dwarf_fde *) cie);
1012 execute_cfa_program (insn, end, context, fs);
1014 /* Locate augmentation for the fde. */
1015 aug = (unsigned char *)fde + sizeof (*fde);
1016 insn = NULL;
1017 if (fs->saw_z)
1019 _Unwind_Word i;
1020 aug = read_uleb128 (aug, &i);
1021 insn = aug + i;
1023 if (fs->saw_lsda)
1024 aug = read_encoded_pointer (aug, fs->addr_encoding,
1025 &context->bases, &context->lsda);
1027 /* Then the insns in the FDE up to our target PC. */
1028 if (insn == NULL)
1029 insn = aug;
1030 end = (unsigned char *) next_fde (fde);
1031 execute_cfa_program (insn, end, context, fs);
1033 return _URC_NO_REASON;
1037 static void
1038 uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1040 struct _Unwind_Context orig_context = *context;
1041 void *cfa;
1042 long i;
1044 /* Compute this frame's CFA. */
1045 switch (fs->cfa_how)
1047 case CFA_REG_OFFSET:
1048 /* Special handling here: Many machines do not use a frame pointer,
1049 and track the CFA only through offsets from the stack pointer from
1050 one frame to the next. In this case, the stack pointer is never
1051 stored, so it has no saved address in the context. What we do
1052 have is the CFA from the previous stack frame. */
1053 if (context->reg[fs->cfa_reg] == NULL)
1054 cfa = context->cfa;
1055 else
1056 cfa = (void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->cfa_reg);
1057 cfa += fs->cfa_offset;
1058 break;
1060 case CFA_EXP:
1061 /* ??? No way of knowing what register number is the stack pointer
1062 to do the same sort of handling as above. Assume that if the
1063 CFA calculation is so complicated as to require a stack program
1064 that this will not be a problem. */
1066 unsigned char *exp = fs->cfa_exp;
1067 _Unwind_Word len;
1069 exp = read_uleb128 (exp, &len);
1070 cfa = (void *) (_Unwind_Ptr)
1071 execute_stack_op (exp, exp + len, context, 0);
1072 break;
1075 default:
1076 abort ();
1078 context->cfa = cfa;
1080 /* Compute the addresses of all registers saved in this frame. */
1081 for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i)
1082 switch (fs->regs.reg[i].how)
1084 case REG_UNSAVED:
1085 break;
1086 case REG_SAVED_OFFSET:
1087 context->reg[i] = cfa + fs->regs.reg[i].loc.offset;
1088 break;
1089 case REG_SAVED_REG:
1090 context->reg[i] = orig_context.reg[fs->regs.reg[i].loc.reg];
1091 break;
1092 case REG_SAVED_EXP:
1094 unsigned char *exp = fs->regs.reg[i].loc.exp;
1095 _Unwind_Word len;
1096 _Unwind_Ptr val;
1098 exp = read_uleb128 (exp, &len);
1099 val = execute_stack_op (exp, exp + len, &orig_context,
1100 (_Unwind_Ptr) cfa);
1101 context->reg[i] = (void *) val;
1103 break;
1107 static void
1108 uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1110 uw_update_context_1 (context, fs);
1112 /* Compute the return address now, since the return address column
1113 can change from frame to frame. */
1114 context->ra = __builtin_extract_return_addr
1115 ((void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->retaddr_column));
1118 /* Fill in CONTEXT for top-of-stack. The only valid registers at this
1119 level will be the return address and the CFA. */
1121 #define uw_init_context(CONTEXT) \
1122 do { \
1123 /* Do any necessary initialization to access arbitrary stack frames. \
1124 On the SPARC, this means flushing the register windows. */ \
1125 __builtin_unwind_init (); \
1126 uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \
1127 __builtin_return_address (0)); \
1128 } while (0)
1130 static void
1131 uw_init_context_1 (struct _Unwind_Context *context,
1132 void *outer_cfa, void *outer_ra)
1134 void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
1135 _Unwind_FrameState fs;
1137 memset (context, 0, sizeof (struct _Unwind_Context));
1138 context->ra = ra;
1140 if (uw_frame_state_for (context, &fs) != _URC_NO_REASON)
1141 abort ();
1143 /* Force the frame state to use the known cfa value. */
1144 context->cfa = outer_cfa;
1145 fs.cfa_how = CFA_REG_OFFSET;
1146 fs.cfa_reg = 0;
1147 fs.cfa_offset = 0;
1149 uw_update_context_1 (context, &fs);
1151 /* If the return address column was saved in a register in the
1152 initialization context, then we can't see it in the given
1153 call frame data. So have the initialization context tell us. */
1154 context->ra = __builtin_extract_return_addr (outer_ra);
1158 /* Install TARGET into CURRENT so that we can return to it. This is a
1159 macro because __builtin_eh_return must be invoked in the context of
1160 our caller. */
1162 #define uw_install_context(CURRENT, TARGET) \
1163 do { \
1164 long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
1165 void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
1166 __builtin_eh_return (offset, handler); \
1167 } while (0)
1169 static inline void
1170 init_dwarf_reg_size_table (void)
1172 __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
1175 static long
1176 uw_install_context_1 (struct _Unwind_Context *current,
1177 struct _Unwind_Context *target)
1179 long i;
1181 #if __GTHREADS
1183 static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
1184 if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
1185 || dwarf_reg_size_table[0] == 0)
1186 init_dwarf_reg_size_table ();
1188 #else
1189 if (dwarf_reg_size_table[0] == 0)
1190 init_dwarf_reg_size_table ();
1191 #endif
1193 for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
1195 void *c = current->reg[i];
1196 void *t = target->reg[i];
1197 if (t && c && t != c)
1198 memcpy (c, t, dwarf_reg_size_table[i]);
1201 /* We adjust SP by the difference between CURRENT and TARGET's CFA. */
1202 if (STACK_GROWS_DOWNWARD)
1203 return target->cfa - current->cfa + target->args_size;
1204 else
1205 return current->cfa - target->cfa - target->args_size;
1208 static inline _Unwind_Ptr
1209 uw_identify_context (struct _Unwind_Context *context)
1211 return _Unwind_GetIP (context);
1215 #include "unwind.inc"
1217 #endif /* !USING_SJLJ_EXCEPTIONS */