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)
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. */
25 #include "unwind-pe.h"
26 #include "unwind-dw2-fde.h"
30 #if !USING_SJLJ_EXCEPTIONS
32 #ifndef STACK_GROWS_DOWNWARD
33 #define STACK_GROWS_DOWNWARD 0
35 #undef STACK_GROWS_DOWNWARD
36 #define STACK_GROWS_DOWNWARD 1
39 /* A target can override (perhaps for backward compatibility) how
40 many dwarf2 columns are unwound. */
41 #ifndef DWARF_FRAME_REGISTERS
42 #define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
45 /* This is the register and unwind state for a particular frame. */
46 struct _Unwind_Context
48 void *reg
[DWARF_FRAME_REGISTERS
+1];
52 struct dwarf_eh_bases bases
;
53 _Unwind_Word args_size
;
56 /* Byte size of every register managed by these routines. */
57 static unsigned char dwarf_reg_size_table
[DWARF_FRAME_REGISTERS
];
60 /* The result of interpreting the frame unwind info for a frame.
61 This is all symbolic at this point, as none of the values can
62 be resolved until the target pc is located. */
65 /* Each register save state can be described in terms of a CFA slot,
66 another register, or a location expression. */
67 struct frame_state_reg_info
73 const unsigned char *exp
;
81 } reg
[DWARF_FRAME_REGISTERS
+1];
83 /* Used to implement DW_CFA_remember_state. */
84 struct frame_state_reg_info
*prev
;
87 /* The CFA can be described in terms of a reg+offset or a
88 location expression. */
89 _Unwind_Sword cfa_offset
;
91 const unsigned char *cfa_exp
;
98 /* The PC described by the current frame state. */
101 /* The information we care about from the CIE/FDE. */
102 _Unwind_Personality_Fn personality
;
103 signed int data_align
;
104 unsigned int code_align
;
105 unsigned char retaddr_column
;
106 unsigned char fde_encoding
;
107 unsigned char lsda_encoding
;
110 } _Unwind_FrameState
;
112 /* Read unaligned data from the instruction buffer. */
117 unsigned u2
__attribute__ ((mode (HI
)));
118 unsigned u4
__attribute__ ((mode (SI
)));
119 unsigned u8
__attribute__ ((mode (DI
)));
120 signed s2
__attribute__ ((mode (HI
)));
121 signed s4
__attribute__ ((mode (SI
)));
122 signed s8
__attribute__ ((mode (DI
)));
123 } __attribute__ ((packed
));
126 read_pointer (const void *p
) { const union unaligned
*up
= p
; return up
->p
; }
129 read_1u (const void *p
) { return *(const unsigned char *)p
; }
132 read_1s (const void *p
) { return *(const signed char *)p
; }
135 read_2u (const void *p
) { const union unaligned
*up
= p
; return up
->u2
; }
138 read_2s (const void *p
) { const union unaligned
*up
= p
; return up
->s2
; }
140 static inline unsigned int
141 read_4u (const void *p
) { const union unaligned
*up
= p
; return up
->u4
; }
144 read_4s (const void *p
) { const union unaligned
*up
= p
; return up
->s4
; }
146 static inline unsigned long
147 read_8u (const void *p
) { const union unaligned
*up
= p
; return up
->u8
; }
149 static inline unsigned long
150 read_8s (const void *p
) { const union unaligned
*up
= p
; return up
->s8
; }
152 /* Get the value of register REG as saved in CONTEXT. */
155 _Unwind_GetGR (struct _Unwind_Context
*context
, int index
)
157 /* This will segfault if the register hasn't been saved. */
158 return * (_Unwind_Word
*) context
->reg
[index
];
161 /* Overwrite the saved value for register REG in CONTEXT with VAL. */
164 _Unwind_SetGR (struct _Unwind_Context
*context
, int index
, _Unwind_Word val
)
166 * (_Unwind_Word
*) context
->reg
[index
] = val
;
169 /* Retrieve the return address for CONTEXT. */
172 _Unwind_GetIP (struct _Unwind_Context
*context
)
174 return (_Unwind_Ptr
) context
->ra
;
177 /* Overwrite the return address for CONTEXT with VAL. */
180 _Unwind_SetIP (struct _Unwind_Context
*context
, _Unwind_Ptr val
)
182 context
->ra
= (void *) val
;
186 _Unwind_GetLanguageSpecificData (struct _Unwind_Context
*context
)
188 return context
->lsda
;
192 _Unwind_GetRegionStart (struct _Unwind_Context
*context
)
194 return (_Unwind_Ptr
) context
->bases
.func
;
199 _Unwind_GetDataRelBase (struct _Unwind_Context
*context
)
201 return (_Unwind_Ptr
) context
->bases
.dbase
;
205 _Unwind_GetTextRelBase (struct _Unwind_Context
*context
)
207 return (_Unwind_Ptr
) context
->bases
.tbase
;
211 /* Extract any interesting information from the CIE for the translation
212 unit F belongs to. Return a pointer to the byte after the augmentation,
213 or NULL if we encountered an undecipherable augmentation. */
215 static const unsigned char *
216 extract_cie_info (struct dwarf_cie
*cie
, struct _Unwind_Context
*context
,
217 _Unwind_FrameState
*fs
)
219 const unsigned char *aug
= cie
->augmentation
;
220 const unsigned char *p
= aug
+ strlen (aug
) + 1;
221 const unsigned char *ret
= NULL
;
224 /* g++ v2 "eh" has pointer immediately following augmentation string,
225 so it must be handled first. */
226 if (aug
[0] == 'e' && aug
[1] == 'h')
228 fs
->eh_ptr
= read_pointer (p
);
229 p
+= sizeof (void *);
233 /* Immediately following the augmentation are the code and
234 data alignment and return address column. */
235 p
= read_uleb128 (p
, &tmp
); fs
->code_align
= tmp
;
236 p
= read_sleb128 (p
, &tmp
); fs
->data_align
= (saddr
) tmp
;
237 fs
->retaddr_column
= *p
++;
238 fs
->lsda_encoding
= DW_EH_PE_omit
;
240 /* If the augmentation starts with 'z', then a uleb128 immediately
241 follows containing the length of the augmentation field following
245 p
= read_uleb128 (p
, &tmp
);
252 /* Iterate over recognized augmentation subsequences. */
255 /* "L" indicates a byte showing how the LSDA pointer is encoded. */
258 fs
->lsda_encoding
= *p
++;
262 /* "R" indicates a byte indicating how FDE addresses are encoded. */
263 else if (aug
[0] == 'R')
265 fs
->fde_encoding
= *p
++;
269 /* "P" indicates a personality routine in the CIE augmentation. */
270 else if (aug
[0] == 'P')
272 p
= read_encoded_value (context
, *p
, p
+ 1,
273 (_Unwind_Ptr
*) &fs
->personality
);
277 /* Otherwise we have an unknown augmentation string.
278 Bail unless we saw a 'z' prefix. */
283 return ret
? ret
: p
;
287 /* Decode a DW_OP stack program. Return the top of stack. Push INITIAL
288 onto the stack to start. */
291 execute_stack_op (const unsigned char *op_ptr
, const unsigned char *op_end
,
292 struct _Unwind_Context
*context
, _Unwind_Word initial
)
294 _Unwind_Word stack
[64]; /* ??? Assume this is enough. */
300 while (op_ptr
< op_end
)
302 enum dwarf_location_atom op
= *op_ptr
++;
303 _Unwind_Word result
, reg
;
304 _Unwind_Sword offset
;
341 result
= op
- DW_OP_lit0
;
345 result
= (_Unwind_Word
) (_Unwind_Ptr
) read_pointer (op_ptr
);
346 op_ptr
+= sizeof (void *);
350 result
= read_1u (op_ptr
);
354 result
= read_1s (op_ptr
);
358 result
= read_2u (op_ptr
);
362 result
= read_2s (op_ptr
);
366 result
= read_4u (op_ptr
);
370 result
= read_4s (op_ptr
);
374 result
= read_8u (op_ptr
);
378 result
= read_8s (op_ptr
);
382 op_ptr
= read_uleb128 (op_ptr
, &ptrtmp
);
386 op_ptr
= read_sleb128 (op_ptr
, &ptrtmp
);
387 result
= (saddr
)ptrtmp
;
422 result
= _Unwind_GetGR (context
, op
- DW_OP_reg0
);
425 op_ptr
= read_uleb128 (op_ptr
, &ptrtmp
); reg
= ptrtmp
;
426 result
= _Unwind_GetGR (context
, reg
);
461 op_ptr
= read_sleb128 (op_ptr
, &ptrtmp
); offset
= (saddr
)ptrtmp
;
462 result
= _Unwind_GetGR (context
, op
- DW_OP_breg0
) + offset
;
465 op_ptr
= read_uleb128 (op_ptr
, &ptrtmp
); reg
= ptrtmp
;
466 op_ptr
= read_sleb128 (op_ptr
, &ptrtmp
); offset
= (saddr
)ptrtmp
;
467 result
= _Unwind_GetGR (context
, reg
) + offset
;
473 result
= stack
[stack_elt
- 1];
483 if (offset
>= stack_elt
- 1)
485 result
= stack
[stack_elt
- 1 - offset
];
491 result
= stack
[stack_elt
- 2];
496 _Unwind_Word t1
, t2
, t3
;
500 t1
= stack
[stack_elt
- 1];
501 t2
= stack
[stack_elt
- 2];
502 t3
= stack
[stack_elt
- 3];
503 stack
[stack_elt
- 1] = t2
;
504 stack
[stack_elt
- 2] = t3
;
505 stack
[stack_elt
- 3] = t1
;
510 case DW_OP_deref_size
:
514 case DW_OP_plus_uconst
:
515 /* Unary operations. */
518 result
= stack
[stack_elt
];
524 void *ptr
= (void *)(_Unwind_Ptr
) result
;
525 result
= (_Unwind_Ptr
) read_pointer (ptr
);
529 case DW_OP_deref_size
:
531 void *ptr
= (void *)(_Unwind_Ptr
) result
;
535 result
= read_1u (ptr
);
538 result
= read_2u (ptr
);
541 result
= read_4u (ptr
);
544 result
= read_8u (ptr
);
553 if ((_Unwind_Sword
) result
< 0)
562 case DW_OP_plus_uconst
:
563 op_ptr
= read_uleb128 (op_ptr
, &ptrtmp
); reg
= ptrtmp
;
583 /* Binary operations. */
584 _Unwind_Word first
, second
;
585 if ((stack_elt
-= 2) < 0)
587 second
= stack
[stack_elt
];
588 first
= stack
[stack_elt
+ 1];
593 result
= second
& first
;
596 result
= (_Unwind_Sword
)second
/ (_Unwind_Sword
)first
;
599 result
= second
- first
;
602 result
= (_Unwind_Sword
)second
% (_Unwind_Sword
)first
;
605 result
= second
* first
;
608 result
= second
| first
;
611 result
= second
+ first
;
614 result
= second
<< first
;
617 result
= second
>> first
;
620 result
= (_Unwind_Sword
)second
>> first
;
623 result
= second
^ first
;
626 result
= (_Unwind_Sword
)first
<= (_Unwind_Sword
)second
;
629 result
= (_Unwind_Sword
)first
>= (_Unwind_Sword
)second
;
632 result
= (_Unwind_Sword
)first
== (_Unwind_Sword
)second
;
635 result
= (_Unwind_Sword
)first
< (_Unwind_Sword
)second
;
638 result
= (_Unwind_Sword
)first
> (_Unwind_Sword
)second
;
641 result
= (_Unwind_Sword
)first
!= (_Unwind_Sword
)second
;
648 offset
= read_2s (op_ptr
);
656 offset
= read_2s (op_ptr
);
658 if (stack
[stack_elt
] != 0)
669 /* Most things push a result value. */
670 if ((size_t) stack_elt
>= sizeof(stack
)/sizeof(*stack
))
672 stack
[++stack_elt
] = result
;
676 /* We were executing this program to get a value. It should be
680 return stack
[stack_elt
];
684 /* Decode DWARF 2 call frame information. Takes pointers the
685 instruction sequence to decode, current register information and
686 CIE info, and the PC range to evaluate. */
689 execute_cfa_program (const unsigned char *insn_ptr
,
690 const unsigned char *insn_end
,
691 struct _Unwind_Context
*context
,
692 _Unwind_FrameState
*fs
)
694 struct frame_state_reg_info
*unused_rs
= NULL
;
696 /* Don't allow remember/restore between CIE and FDE programs. */
697 fs
->regs
.prev
= NULL
;
699 while (insn_ptr
< insn_end
&& fs
->pc
< context
->ra
)
701 unsigned char insn
= *insn_ptr
++;
703 _Unwind_Sword offset
;
706 if (insn
& DW_CFA_advance_loc
)
707 fs
->pc
+= (insn
& 0x3f) * fs
->code_align
;
708 else if (insn
& DW_CFA_offset
)
711 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
712 offset
= ptrtmp
* fs
->data_align
;
713 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
714 fs
->regs
.reg
[reg
].loc
.offset
= offset
;
716 else if (insn
& DW_CFA_restore
)
719 fs
->regs
.reg
[reg
].how
= REG_UNSAVED
;
724 insn_ptr
= read_encoded_value (context
, fs
->fde_encoding
,
725 insn_ptr
, (_Unwind_Ptr
*) &fs
->pc
);
728 case DW_CFA_advance_loc1
:
729 fs
->pc
+= read_1u (insn_ptr
) * fs
->code_align
;
732 case DW_CFA_advance_loc2
:
733 fs
->pc
+= read_2u (insn_ptr
) * fs
->code_align
;
736 case DW_CFA_advance_loc4
:
737 fs
->pc
+= read_4u (insn_ptr
) * fs
->code_align
;
741 case DW_CFA_offset_extended
:
742 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
743 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
744 offset
= ptrtmp
* fs
->data_align
;
745 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
746 fs
->regs
.reg
[reg
].loc
.offset
= offset
;
749 case DW_CFA_restore_extended
:
750 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
751 fs
->regs
.reg
[reg
].how
= REG_UNSAVED
;
754 case DW_CFA_undefined
:
755 case DW_CFA_same_value
:
759 case DW_CFA_register
:
762 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
763 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg2
= ptrtmp
;
764 fs
->regs
.reg
[reg
].how
= REG_SAVED_REG
;
765 fs
->regs
.reg
[reg
].loc
.reg
= reg2
;
769 case DW_CFA_remember_state
:
771 struct frame_state_reg_info
*new_rs
;
775 unused_rs
= unused_rs
->prev
;
778 new_rs
= alloca (sizeof (struct frame_state_reg_info
));
781 fs
->regs
.prev
= new_rs
;
785 case DW_CFA_restore_state
:
787 struct frame_state_reg_info
*old_rs
= fs
->regs
.prev
;
789 old_rs
->prev
= unused_rs
;
795 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
796 fs
->cfa_reg
= ptrtmp
;
797 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
798 fs
->cfa_offset
= ptrtmp
;
799 fs
->cfa_how
= CFA_REG_OFFSET
;
802 case DW_CFA_def_cfa_register
:
803 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
804 fs
->cfa_reg
= ptrtmp
;
805 fs
->cfa_how
= CFA_REG_OFFSET
;
808 case DW_CFA_def_cfa_offset
:
809 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
810 fs
->cfa_offset
= ptrtmp
;
811 /* cfa_how deliberately not set. */
814 case DW_CFA_def_cfa_expression
:
815 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
816 fs
->cfa_exp
= insn_ptr
;
817 fs
->cfa_how
= CFA_EXP
;
821 case DW_CFA_expression
:
822 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
823 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
824 fs
->regs
.reg
[reg
].how
= REG_SAVED_EXP
;
825 fs
->regs
.reg
[reg
].loc
.exp
= insn_ptr
;
829 /* From the 2.1 draft. */
830 case DW_CFA_offset_extended_sf
:
831 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
832 insn_ptr
= read_sleb128 (insn_ptr
, &ptrtmp
);
833 offset
= (saddr
)ptrtmp
* fs
->data_align
;
834 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
835 fs
->regs
.reg
[reg
].loc
.offset
= offset
;
838 case DW_CFA_def_cfa_sf
:
839 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
840 fs
->cfa_reg
= ptrtmp
;
841 insn_ptr
= read_sleb128 (insn_ptr
, &ptrtmp
);
842 fs
->cfa_offset
= (saddr
)ptrtmp
;
843 fs
->cfa_how
= CFA_REG_OFFSET
;
846 case DW_CFA_def_cfa_offset_sf
:
847 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
848 fs
->cfa_offset
= ptrtmp
;
849 /* cfa_how deliberately not set. */
852 case DW_CFA_GNU_window_save
:
853 /* ??? Hardcoded for SPARC register window configuration. */
854 for (reg
= 16; reg
< 32; ++reg
)
856 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
857 fs
->regs
.reg
[reg
].loc
.offset
= (reg
- 16) * sizeof (void *);
861 case DW_CFA_GNU_args_size
:
862 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
863 context
->args_size
= ptrtmp
;
866 case DW_CFA_GNU_negative_offset_extended
:
867 /* Obsoleted by DW_CFA_offset_extended_sf, but used by
868 older PowerPC code. */
869 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
870 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
871 offset
= ptrtmp
* fs
->data_align
;
872 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
873 fs
->regs
.reg
[reg
].loc
.offset
= -offset
;
882 static _Unwind_Reason_Code
883 uw_frame_state_for (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
885 struct dwarf_fde
*fde
;
886 struct dwarf_cie
*cie
;
887 const unsigned char *aug
, *insn
, *end
;
889 memset (fs
, 0, sizeof (*fs
));
890 context
->args_size
= 0;
893 fde
= _Unwind_Find_FDE (context
->ra
- 1, &context
->bases
);
896 /* Couldn't find frame unwind info for this function. Try a
897 target-specific fallback mechanism. This will necessarily
898 not profide a personality routine or LSDA. */
899 #ifdef MD_FALLBACK_FRAME_STATE_FOR
900 MD_FALLBACK_FRAME_STATE_FOR (context
, fs
, success
);
901 return _URC_END_OF_STACK
;
903 return _URC_NO_REASON
;
905 return _URC_END_OF_STACK
;
909 fs
->pc
= context
->bases
.func
;
912 insn
= extract_cie_info (cie
, context
, fs
);
914 /* CIE contained unknown augmentation. */
915 return _URC_FATAL_PHASE1_ERROR
;
917 /* First decode all the insns in the CIE. */
918 end
= (unsigned char *) next_fde ((struct dwarf_fde
*) cie
);
919 execute_cfa_program (insn
, end
, context
, fs
);
921 /* Locate augmentation for the fde. */
922 aug
= (unsigned char *)fde
+ sizeof (*fde
);
923 aug
+= 2 * size_of_encoded_value (fs
->fde_encoding
);
928 aug
= read_uleb128 (aug
, &i
);
931 if (fs
->lsda_encoding
!= DW_EH_PE_omit
)
932 aug
= read_encoded_value (context
, fs
->lsda_encoding
, aug
,
933 (_Unwind_Ptr
*) &context
->lsda
);
935 /* Then the insns in the FDE up to our target PC. */
938 end
= (unsigned char *) next_fde (fde
);
939 execute_cfa_program (insn
, end
, context
, fs
);
941 return _URC_NO_REASON
;
944 typedef struct frame_state
950 long reg_or_offset
[DWARF_FRAME_REGISTERS
+1];
951 unsigned short cfa_reg
;
952 unsigned short retaddr_column
;
953 char saved
[DWARF_FRAME_REGISTERS
+1];
956 struct frame_state
* __frame_state_for (void *, struct frame_state
*);
958 /* Called from pre-G++ 3.0 __throw to find the registers to restore for
959 a given PC_TARGET. The caller should allocate a local variable of
960 `struct frame_state' and pass its address to STATE_IN. */
963 __frame_state_for (void *pc_target
, struct frame_state
*state_in
)
965 struct _Unwind_Context context
;
966 _Unwind_FrameState fs
;
969 memset (&context
, 0, sizeof (struct _Unwind_Context
));
970 context
.ra
= pc_target
+ 1;
972 if (uw_frame_state_for (&context
, &fs
) != _URC_NO_REASON
)
975 /* We have no way to pass a location expression for the CFA to our
976 caller. It wouldn't understand it anyway. */
977 if (fs
.cfa_how
== CFA_EXP
)
980 for (reg
= 0; reg
< DWARF_FRAME_REGISTERS
+ 1; reg
++)
982 state_in
->saved
[reg
] = fs
.regs
.reg
[reg
].how
;
983 switch (state_in
->saved
[reg
])
986 state_in
->reg_or_offset
[reg
] = fs
.regs
.reg
[reg
].loc
.reg
;
988 case REG_SAVED_OFFSET
:
989 state_in
->reg_or_offset
[reg
] = fs
.regs
.reg
[reg
].loc
.offset
;
992 state_in
->reg_or_offset
[reg
] = 0;
997 state_in
->cfa_offset
= fs
.cfa_offset
;
998 state_in
->cfa_reg
= fs
.cfa_reg
;
999 state_in
->retaddr_column
= fs
.retaddr_column
;
1000 state_in
->args_size
= context
.args_size
;
1001 state_in
->eh_ptr
= fs
.eh_ptr
;
1007 uw_update_context_1 (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
1009 struct _Unwind_Context orig_context
= *context
;
1013 /* Compute this frame's CFA. */
1014 switch (fs
->cfa_how
)
1016 case CFA_REG_OFFSET
:
1017 /* Special handling here: Many machines do not use a frame pointer,
1018 and track the CFA only through offsets from the stack pointer from
1019 one frame to the next. In this case, the stack pointer is never
1020 stored, so it has no saved address in the context. What we do
1021 have is the CFA from the previous stack frame. */
1022 if (context
->reg
[fs
->cfa_reg
] == NULL
)
1025 cfa
= (void *) (_Unwind_Ptr
) _Unwind_GetGR (context
, fs
->cfa_reg
);
1026 cfa
+= fs
->cfa_offset
;
1030 /* ??? No way of knowing what register number is the stack pointer
1031 to do the same sort of handling as above. Assume that if the
1032 CFA calculation is so complicated as to require a stack program
1033 that this will not be a problem. */
1035 const unsigned char *exp
= fs
->cfa_exp
;
1038 exp
= read_uleb128 (exp
, &len
);
1039 cfa
= (void *) (_Unwind_Ptr
)
1040 execute_stack_op (exp
, exp
+ len
, context
, 0);
1049 /* Compute the addresses of all registers saved in this frame. */
1050 for (i
= 0; i
< DWARF_FRAME_REGISTERS
+ 1; ++i
)
1051 switch (fs
->regs
.reg
[i
].how
)
1055 case REG_SAVED_OFFSET
:
1056 context
->reg
[i
] = cfa
+ fs
->regs
.reg
[i
].loc
.offset
;
1059 context
->reg
[i
] = orig_context
.reg
[fs
->regs
.reg
[i
].loc
.reg
];
1063 const unsigned char *exp
= fs
->regs
.reg
[i
].loc
.exp
;
1067 exp
= read_uleb128 (exp
, &len
);
1068 val
= execute_stack_op (exp
, exp
+ len
, &orig_context
,
1070 context
->reg
[i
] = (void *) val
;
1077 uw_update_context (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
1079 uw_update_context_1 (context
, fs
);
1081 /* Compute the return address now, since the return address column
1082 can change from frame to frame. */
1083 context
->ra
= __builtin_extract_return_addr
1084 ((void *) (_Unwind_Ptr
) _Unwind_GetGR (context
, fs
->retaddr_column
));
1087 /* Fill in CONTEXT for top-of-stack. The only valid registers at this
1088 level will be the return address and the CFA. */
1090 #define uw_init_context(CONTEXT) \
1092 /* Do any necessary initialization to access arbitrary stack frames. \
1093 On the SPARC, this means flushing the register windows. */ \
1094 __builtin_unwind_init (); \
1095 uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \
1096 __builtin_return_address (0)); \
1100 uw_init_context_1 (struct _Unwind_Context
*context
,
1101 void *outer_cfa
, void *outer_ra
)
1103 void *ra
= __builtin_extract_return_addr (__builtin_return_address (0));
1104 _Unwind_FrameState fs
;
1106 memset (context
, 0, sizeof (struct _Unwind_Context
));
1109 if (uw_frame_state_for (context
, &fs
) != _URC_NO_REASON
)
1112 /* Force the frame state to use the known cfa value. */
1113 context
->cfa
= outer_cfa
;
1114 fs
.cfa_how
= CFA_REG_OFFSET
;
1118 uw_update_context_1 (context
, &fs
);
1120 /* If the return address column was saved in a register in the
1121 initialization context, then we can't see it in the given
1122 call frame data. So have the initialization context tell us. */
1123 context
->ra
= __builtin_extract_return_addr (outer_ra
);
1127 /* Install TARGET into CURRENT so that we can return to it. This is a
1128 macro because __builtin_eh_return must be invoked in the context of
1131 #define uw_install_context(CURRENT, TARGET) \
1133 long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
1134 void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
1135 __builtin_eh_return (offset, handler); \
1139 init_dwarf_reg_size_table (void)
1141 __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table
);
1145 uw_install_context_1 (struct _Unwind_Context
*current
,
1146 struct _Unwind_Context
*target
)
1152 static __gthread_once_t once_regsizes
= __GTHREAD_ONCE_INIT
;
1153 if (__gthread_once (&once_regsizes
, init_dwarf_reg_size_table
) != 0
1154 || dwarf_reg_size_table
[0] == 0)
1155 init_dwarf_reg_size_table ();
1158 if (dwarf_reg_size_table
[0] == 0)
1159 init_dwarf_reg_size_table ();
1162 for (i
= 0; i
< DWARF_FRAME_REGISTERS
; ++i
)
1164 void *c
= current
->reg
[i
];
1165 void *t
= target
->reg
[i
];
1166 if (t
&& c
&& t
!= c
)
1167 memcpy (c
, t
, dwarf_reg_size_table
[i
]);
1170 /* We adjust SP by the difference between CURRENT and TARGET's CFA. */
1171 if (STACK_GROWS_DOWNWARD
)
1172 return target
->cfa
- current
->cfa
+ target
->args_size
;
1174 return current
->cfa
- target
->cfa
- target
->args_size
;
1177 static inline _Unwind_Ptr
1178 uw_identify_context (struct _Unwind_Context
*context
)
1180 return _Unwind_GetIP (context
);
1184 #include "unwind.inc"
1186 #endif /* !USING_SJLJ_EXCEPTIONS */