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 GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 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 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
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 /* Dwarf frame registers used for pre gcc 3.0 compiled glibc. */
46 #ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
47 #define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS
50 /* This is the register and unwind state for a particular frame. */
51 struct _Unwind_Context
53 void *reg
[DWARF_FRAME_REGISTERS
+1];
57 struct dwarf_eh_bases bases
;
58 _Unwind_Word args_size
;
61 /* Byte size of every register managed by these routines. */
62 static unsigned char dwarf_reg_size_table
[DWARF_FRAME_REGISTERS
];
65 /* The result of interpreting the frame unwind info for a frame.
66 This is all symbolic at this point, as none of the values can
67 be resolved until the target pc is located. */
70 /* Each register save state can be described in terms of a CFA slot,
71 another register, or a location expression. */
72 struct frame_state_reg_info
78 const unsigned char *exp
;
86 } reg
[DWARF_FRAME_REGISTERS
+1];
88 /* Used to implement DW_CFA_remember_state. */
89 struct frame_state_reg_info
*prev
;
92 /* The CFA can be described in terms of a reg+offset or a
93 location expression. */
94 _Unwind_Sword cfa_offset
;
96 const unsigned char *cfa_exp
;
103 /* The PC described by the current frame state. */
106 /* The information we care about from the CIE/FDE. */
107 _Unwind_Personality_Fn personality
;
108 _Unwind_Sword data_align
;
109 _Unwind_Word code_align
;
110 unsigned char retaddr_column
;
111 unsigned char fde_encoding
;
112 unsigned char lsda_encoding
;
115 } _Unwind_FrameState
;
117 /* Read unaligned data from the instruction buffer. */
122 unsigned u2
__attribute__ ((mode (HI
)));
123 unsigned u4
__attribute__ ((mode (SI
)));
124 unsigned u8
__attribute__ ((mode (DI
)));
125 signed s2
__attribute__ ((mode (HI
)));
126 signed s4
__attribute__ ((mode (SI
)));
127 signed s8
__attribute__ ((mode (DI
)));
128 } __attribute__ ((packed
));
131 read_pointer (const void *p
) { const union unaligned
*up
= p
; return up
->p
; }
134 read_1u (const void *p
) { return *(const unsigned char *)p
; }
137 read_1s (const void *p
) { return *(const signed char *)p
; }
140 read_2u (const void *p
) { const union unaligned
*up
= p
; return up
->u2
; }
143 read_2s (const void *p
) { const union unaligned
*up
= p
; return up
->s2
; }
145 static inline unsigned int
146 read_4u (const void *p
) { const union unaligned
*up
= p
; return up
->u4
; }
149 read_4s (const void *p
) { const union unaligned
*up
= p
; return up
->s4
; }
151 static inline unsigned long
152 read_8u (const void *p
) { const union unaligned
*up
= p
; return up
->u8
; }
154 static inline unsigned long
155 read_8s (const void *p
) { const union unaligned
*up
= p
; return up
->s8
; }
157 /* Get the value of register REG as saved in CONTEXT. */
160 _Unwind_GetGR (struct _Unwind_Context
*context
, int index
)
162 /* This will segfault if the register hasn't been saved. */
163 return * (_Unwind_Word
*) context
->reg
[index
];
166 /* Overwrite the saved value for register REG in CONTEXT with VAL. */
169 _Unwind_SetGR (struct _Unwind_Context
*context
, int index
, _Unwind_Word val
)
171 * (_Unwind_Word
*) context
->reg
[index
] = val
;
174 /* Retrieve the return address for CONTEXT. */
177 _Unwind_GetIP (struct _Unwind_Context
*context
)
179 return (_Unwind_Ptr
) context
->ra
;
182 /* Overwrite the return address for CONTEXT with VAL. */
185 _Unwind_SetIP (struct _Unwind_Context
*context
, _Unwind_Ptr val
)
187 context
->ra
= (void *) val
;
191 _Unwind_GetLanguageSpecificData (struct _Unwind_Context
*context
)
193 return context
->lsda
;
197 _Unwind_GetRegionStart (struct _Unwind_Context
*context
)
199 return (_Unwind_Ptr
) context
->bases
.func
;
204 _Unwind_GetDataRelBase (struct _Unwind_Context
*context
)
206 return (_Unwind_Ptr
) context
->bases
.dbase
;
210 _Unwind_GetTextRelBase (struct _Unwind_Context
*context
)
212 return (_Unwind_Ptr
) context
->bases
.tbase
;
216 /* Extract any interesting information from the CIE for the translation
217 unit F belongs to. Return a pointer to the byte after the augmentation,
218 or NULL if we encountered an undecipherable augmentation. */
220 static const unsigned char *
221 extract_cie_info (struct dwarf_cie
*cie
, struct _Unwind_Context
*context
,
222 _Unwind_FrameState
*fs
)
224 const unsigned char *aug
= cie
->augmentation
;
225 const unsigned char *p
= aug
+ strlen (aug
) + 1;
226 const unsigned char *ret
= NULL
;
229 /* g++ v2 "eh" has pointer immediately following augmentation string,
230 so it must be handled first. */
231 if (aug
[0] == 'e' && aug
[1] == 'h')
233 fs
->eh_ptr
= read_pointer (p
);
234 p
+= sizeof (void *);
238 /* Immediately following the augmentation are the code and
239 data alignment and return address column. */
240 p
= read_uleb128 (p
, &fs
->code_align
);
241 p
= read_sleb128 (p
, &fs
->data_align
);
242 fs
->retaddr_column
= *p
++;
243 fs
->lsda_encoding
= DW_EH_PE_omit
;
245 /* If the augmentation starts with 'z', then a uleb128 immediately
246 follows containing the length of the augmentation field following
250 p
= read_uleb128 (p
, &utmp
);
257 /* Iterate over recognized augmentation subsequences. */
260 /* "L" indicates a byte showing how the LSDA pointer is encoded. */
263 fs
->lsda_encoding
= *p
++;
267 /* "R" indicates a byte indicating how FDE addresses are encoded. */
268 else if (aug
[0] == 'R')
270 fs
->fde_encoding
= *p
++;
274 /* "P" indicates a personality routine in the CIE augmentation. */
275 else if (aug
[0] == 'P')
277 p
= read_encoded_value (context
, *p
, p
+ 1,
278 (_Unwind_Ptr
*) &fs
->personality
);
282 /* Otherwise we have an unknown augmentation string.
283 Bail unless we saw a 'z' prefix. */
288 return ret
? ret
: p
;
292 /* Decode a DW_OP stack program. Return the top of stack. Push INITIAL
293 onto the stack to start. */
296 execute_stack_op (const unsigned char *op_ptr
, const unsigned char *op_end
,
297 struct _Unwind_Context
*context
, _Unwind_Word initial
)
299 _Unwind_Word stack
[64]; /* ??? Assume this is enough. */
305 while (op_ptr
< op_end
)
307 enum dwarf_location_atom op
= *op_ptr
++;
308 _Unwind_Word result
, reg
, utmp
;
309 _Unwind_Sword offset
, stmp
;
345 result
= op
- DW_OP_lit0
;
349 result
= (_Unwind_Word
) (_Unwind_Ptr
) read_pointer (op_ptr
);
350 op_ptr
+= sizeof (void *);
354 result
= read_1u (op_ptr
);
358 result
= read_1s (op_ptr
);
362 result
= read_2u (op_ptr
);
366 result
= read_2s (op_ptr
);
370 result
= read_4u (op_ptr
);
374 result
= read_4s (op_ptr
);
378 result
= read_8u (op_ptr
);
382 result
= read_8s (op_ptr
);
386 op_ptr
= read_uleb128 (op_ptr
, &result
);
389 op_ptr
= read_sleb128 (op_ptr
, &stmp
);
425 result
= _Unwind_GetGR (context
, op
- DW_OP_reg0
);
428 op_ptr
= read_uleb128 (op_ptr
, ®
);
429 result
= _Unwind_GetGR (context
, reg
);
464 op_ptr
= read_sleb128 (op_ptr
, &offset
);
465 result
= _Unwind_GetGR (context
, op
- DW_OP_breg0
) + offset
;
468 op_ptr
= read_uleb128 (op_ptr
, ®
);
469 op_ptr
= read_sleb128 (op_ptr
, &offset
);
470 result
= _Unwind_GetGR (context
, reg
) + offset
;
476 result
= stack
[stack_elt
- 1];
486 if (offset
>= stack_elt
- 1)
488 result
= stack
[stack_elt
- 1 - offset
];
494 result
= stack
[stack_elt
- 2];
499 _Unwind_Word t1
, t2
, t3
;
503 t1
= stack
[stack_elt
- 1];
504 t2
= stack
[stack_elt
- 2];
505 t3
= stack
[stack_elt
- 3];
506 stack
[stack_elt
- 1] = t2
;
507 stack
[stack_elt
- 2] = t3
;
508 stack
[stack_elt
- 3] = t1
;
513 case DW_OP_deref_size
:
517 case DW_OP_plus_uconst
:
518 /* Unary operations. */
521 result
= stack
[stack_elt
];
527 void *ptr
= (void *)(_Unwind_Ptr
) result
;
528 result
= (_Unwind_Ptr
) read_pointer (ptr
);
532 case DW_OP_deref_size
:
534 void *ptr
= (void *)(_Unwind_Ptr
) result
;
538 result
= read_1u (ptr
);
541 result
= read_2u (ptr
);
544 result
= read_4u (ptr
);
547 result
= read_8u (ptr
);
556 if ((_Unwind_Sword
) result
< 0)
565 case DW_OP_plus_uconst
:
566 op_ptr
= read_uleb128 (op_ptr
, &utmp
);
589 /* Binary operations. */
590 _Unwind_Word first
, second
;
591 if ((stack_elt
-= 2) < 0)
593 second
= stack
[stack_elt
];
594 first
= stack
[stack_elt
+ 1];
599 result
= second
& first
;
602 result
= (_Unwind_Sword
)second
/ (_Unwind_Sword
)first
;
605 result
= second
- first
;
608 result
= (_Unwind_Sword
)second
% (_Unwind_Sword
)first
;
611 result
= second
* first
;
614 result
= second
| first
;
617 result
= second
+ first
;
620 result
= second
<< first
;
623 result
= second
>> first
;
626 result
= (_Unwind_Sword
)second
>> first
;
629 result
= second
^ first
;
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
;
644 result
= (_Unwind_Sword
)first
> (_Unwind_Sword
)second
;
647 result
= (_Unwind_Sword
)first
!= (_Unwind_Sword
)second
;
657 offset
= read_2s (op_ptr
);
665 offset
= read_2s (op_ptr
);
667 if (stack
[stack_elt
] != 0)
678 /* Most things push a result value. */
679 if ((size_t) stack_elt
>= sizeof(stack
)/sizeof(*stack
))
681 stack
[++stack_elt
] = result
;
685 /* We were executing this program to get a value. It should be
689 return stack
[stack_elt
];
693 /* Decode DWARF 2 call frame information. Takes pointers the
694 instruction sequence to decode, current register information and
695 CIE info, and the PC range to evaluate. */
698 execute_cfa_program (const unsigned char *insn_ptr
,
699 const unsigned char *insn_end
,
700 struct _Unwind_Context
*context
,
701 _Unwind_FrameState
*fs
)
703 struct frame_state_reg_info
*unused_rs
= NULL
;
705 /* Don't allow remember/restore between CIE and FDE programs. */
706 fs
->regs
.prev
= NULL
;
708 while (insn_ptr
< insn_end
&& fs
->pc
<= context
->ra
)
710 unsigned char insn
= *insn_ptr
++;
711 _Unwind_Word reg
, utmp
;
712 _Unwind_Sword offset
, stmp
;
714 if ((insn
& 0xc0) == DW_CFA_advance_loc
)
715 fs
->pc
+= (insn
& 0x3f) * fs
->code_align
;
716 else if ((insn
& 0xc0) == DW_CFA_offset
)
719 insn_ptr
= read_uleb128 (insn_ptr
, &utmp
);
720 offset
= (_Unwind_Sword
)utmp
* fs
->data_align
;
721 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
722 fs
->regs
.reg
[reg
].loc
.offset
= offset
;
724 else if ((insn
& 0xc0) == DW_CFA_restore
)
727 fs
->regs
.reg
[reg
].how
= REG_UNSAVED
;
732 insn_ptr
= read_encoded_value (context
, fs
->fde_encoding
,
733 insn_ptr
, (_Unwind_Ptr
*) &fs
->pc
);
736 case DW_CFA_advance_loc1
:
737 fs
->pc
+= read_1u (insn_ptr
) * fs
->code_align
;
740 case DW_CFA_advance_loc2
:
741 fs
->pc
+= read_2u (insn_ptr
) * fs
->code_align
;
744 case DW_CFA_advance_loc4
:
745 fs
->pc
+= read_4u (insn_ptr
) * fs
->code_align
;
749 case DW_CFA_offset_extended
:
750 insn_ptr
= read_uleb128 (insn_ptr
, ®
);
751 insn_ptr
= read_uleb128 (insn_ptr
, &utmp
);
752 offset
= (_Unwind_Sword
)utmp
* fs
->data_align
;
753 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
754 fs
->regs
.reg
[reg
].loc
.offset
= offset
;
757 case DW_CFA_restore_extended
:
758 insn_ptr
= read_uleb128 (insn_ptr
, ®
);
759 fs
->regs
.reg
[reg
].how
= REG_UNSAVED
;
762 case DW_CFA_undefined
:
763 case DW_CFA_same_value
:
767 case DW_CFA_register
:
770 insn_ptr
= read_uleb128 (insn_ptr
, ®
);
771 insn_ptr
= read_uleb128 (insn_ptr
, ®2
);
772 fs
->regs
.reg
[reg
].how
= REG_SAVED_REG
;
773 fs
->regs
.reg
[reg
].loc
.reg
= reg2
;
777 case DW_CFA_remember_state
:
779 struct frame_state_reg_info
*new_rs
;
783 unused_rs
= unused_rs
->prev
;
786 new_rs
= __builtin_alloca (sizeof (struct frame_state_reg_info
));
789 fs
->regs
.prev
= new_rs
;
793 case DW_CFA_restore_state
:
795 struct frame_state_reg_info
*old_rs
= fs
->regs
.prev
;
797 old_rs
->prev
= unused_rs
;
803 insn_ptr
= read_uleb128 (insn_ptr
, &fs
->cfa_reg
);
804 insn_ptr
= read_uleb128 (insn_ptr
, &utmp
);
805 fs
->cfa_offset
= utmp
;
806 fs
->cfa_how
= CFA_REG_OFFSET
;
809 case DW_CFA_def_cfa_register
:
810 insn_ptr
= read_uleb128 (insn_ptr
, &fs
->cfa_reg
);
811 fs
->cfa_how
= CFA_REG_OFFSET
;
814 case DW_CFA_def_cfa_offset
:
815 insn_ptr
= read_uleb128 (insn_ptr
, &utmp
);
816 fs
->cfa_offset
= utmp
;
817 /* cfa_how deliberately not set. */
820 case DW_CFA_def_cfa_expression
:
821 insn_ptr
= read_uleb128 (insn_ptr
, &utmp
);
822 fs
->cfa_exp
= insn_ptr
;
823 fs
->cfa_how
= CFA_EXP
;
827 case DW_CFA_expression
:
828 insn_ptr
= read_uleb128 (insn_ptr
, ®
);
829 insn_ptr
= read_uleb128 (insn_ptr
, &utmp
);
830 fs
->regs
.reg
[reg
].how
= REG_SAVED_EXP
;
831 fs
->regs
.reg
[reg
].loc
.exp
= insn_ptr
;
835 /* From the 2.1 draft. */
836 case DW_CFA_offset_extended_sf
:
837 insn_ptr
= read_uleb128 (insn_ptr
, ®
);
838 insn_ptr
= read_sleb128 (insn_ptr
, &stmp
);
839 offset
= stmp
* fs
->data_align
;
840 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
841 fs
->regs
.reg
[reg
].loc
.offset
= offset
;
844 case DW_CFA_def_cfa_sf
:
845 insn_ptr
= read_uleb128 (insn_ptr
, &fs
->cfa_reg
);
846 insn_ptr
= read_sleb128 (insn_ptr
, &fs
->cfa_offset
);
847 fs
->cfa_how
= CFA_REG_OFFSET
;
850 case DW_CFA_def_cfa_offset_sf
:
851 insn_ptr
= read_sleb128 (insn_ptr
, &fs
->cfa_offset
);
852 /* cfa_how deliberately not set. */
855 case DW_CFA_GNU_window_save
:
856 /* ??? Hardcoded for SPARC register window configuration. */
857 for (reg
= 16; reg
< 32; ++reg
)
859 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
860 fs
->regs
.reg
[reg
].loc
.offset
= (reg
- 16) * sizeof (void *);
864 case DW_CFA_GNU_args_size
:
865 insn_ptr
= read_uleb128 (insn_ptr
, &context
->args_size
);
868 case DW_CFA_GNU_negative_offset_extended
:
869 /* Obsoleted by DW_CFA_offset_extended_sf, but used by
870 older PowerPC code. */
871 insn_ptr
= read_uleb128 (insn_ptr
, ®
);
872 insn_ptr
= read_uleb128 (insn_ptr
, &utmp
);
873 offset
= (_Unwind_Word
)utmp
* fs
->data_align
;
874 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
875 fs
->regs
.reg
[reg
].loc
.offset
= -offset
;
884 static _Unwind_Reason_Code
885 uw_frame_state_for (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
887 struct dwarf_fde
*fde
;
888 struct dwarf_cie
*cie
;
889 const unsigned char *aug
, *insn
, *end
;
891 memset (fs
, 0, sizeof (*fs
));
892 context
->args_size
= 0;
895 fde
= _Unwind_Find_FDE (context
->ra
- 1, &context
->bases
);
898 /* Couldn't find frame unwind info for this function. Try a
899 target-specific fallback mechanism. This will necessarily
900 not provide a personality routine or LSDA. */
901 #ifdef MD_FALLBACK_FRAME_STATE_FOR
902 MD_FALLBACK_FRAME_STATE_FOR (context
, fs
, success
);
903 return _URC_END_OF_STACK
;
905 return _URC_NO_REASON
;
907 return _URC_END_OF_STACK
;
911 fs
->pc
= context
->bases
.func
;
914 insn
= extract_cie_info (cie
, context
, fs
);
916 /* CIE contained unknown augmentation. */
917 return _URC_FATAL_PHASE1_ERROR
;
919 /* First decode all the insns in the CIE. */
920 end
= (unsigned char *) next_fde ((struct dwarf_fde
*) cie
);
921 execute_cfa_program (insn
, end
, context
, fs
);
923 /* Locate augmentation for the fde. */
924 aug
= (unsigned char *)fde
+ sizeof (*fde
);
925 aug
+= 2 * size_of_encoded_value (fs
->fde_encoding
);
930 aug
= read_uleb128 (aug
, &i
);
933 if (fs
->lsda_encoding
!= DW_EH_PE_omit
)
934 aug
= read_encoded_value (context
, fs
->lsda_encoding
, aug
,
935 (_Unwind_Ptr
*) &context
->lsda
);
937 /* Then the insns in the FDE up to our target PC. */
940 end
= (unsigned char *) next_fde (fde
);
941 execute_cfa_program (insn
, end
, context
, fs
);
943 return _URC_NO_REASON
;
946 typedef struct frame_state
952 long reg_or_offset
[PRE_GCC3_DWARF_FRAME_REGISTERS
+1];
953 unsigned short cfa_reg
;
954 unsigned short retaddr_column
;
955 char saved
[PRE_GCC3_DWARF_FRAME_REGISTERS
+1];
958 struct frame_state
* __frame_state_for (void *, struct frame_state
*);
960 /* Called from pre-G++ 3.0 __throw to find the registers to restore for
961 a given PC_TARGET. The caller should allocate a local variable of
962 `struct frame_state' and pass its address to STATE_IN. */
965 __frame_state_for (void *pc_target
, struct frame_state
*state_in
)
967 struct _Unwind_Context context
;
968 _Unwind_FrameState fs
;
971 memset (&context
, 0, sizeof (struct _Unwind_Context
));
972 context
.ra
= pc_target
+ 1;
974 if (uw_frame_state_for (&context
, &fs
) != _URC_NO_REASON
)
977 /* We have no way to pass a location expression for the CFA to our
978 caller. It wouldn't understand it anyway. */
979 if (fs
.cfa_how
== CFA_EXP
)
982 for (reg
= 0; reg
< PRE_GCC3_DWARF_FRAME_REGISTERS
+ 1; reg
++)
984 state_in
->saved
[reg
] = fs
.regs
.reg
[reg
].how
;
985 switch (state_in
->saved
[reg
])
988 state_in
->reg_or_offset
[reg
] = fs
.regs
.reg
[reg
].loc
.reg
;
990 case REG_SAVED_OFFSET
:
991 state_in
->reg_or_offset
[reg
] = fs
.regs
.reg
[reg
].loc
.offset
;
994 state_in
->reg_or_offset
[reg
] = 0;
999 state_in
->cfa_offset
= fs
.cfa_offset
;
1000 state_in
->cfa_reg
= fs
.cfa_reg
;
1001 state_in
->retaddr_column
= fs
.retaddr_column
;
1002 state_in
->args_size
= context
.args_size
;
1003 state_in
->eh_ptr
= fs
.eh_ptr
;
1009 uw_update_context_1 (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
1011 struct _Unwind_Context orig_context
= *context
;
1015 /* Compute this frame's CFA. */
1016 switch (fs
->cfa_how
)
1018 case CFA_REG_OFFSET
:
1019 /* Special handling here: Many machines do not use a frame pointer,
1020 and track the CFA only through offsets from the stack pointer from
1021 one frame to the next. In this case, the stack pointer is never
1022 stored, so it has no saved address in the context. What we do
1023 have is the CFA from the previous stack frame. */
1024 if (context
->reg
[fs
->cfa_reg
] == NULL
)
1027 cfa
= (void *) (_Unwind_Ptr
) _Unwind_GetGR (context
, fs
->cfa_reg
);
1028 cfa
+= fs
->cfa_offset
;
1032 /* ??? No way of knowing what register number is the stack pointer
1033 to do the same sort of handling as above. Assume that if the
1034 CFA calculation is so complicated as to require a stack program
1035 that this will not be a problem. */
1037 const unsigned char *exp
= fs
->cfa_exp
;
1040 exp
= read_uleb128 (exp
, &len
);
1041 cfa
= (void *) (_Unwind_Ptr
)
1042 execute_stack_op (exp
, exp
+ len
, context
, 0);
1051 /* Compute the addresses of all registers saved in this frame. */
1052 for (i
= 0; i
< DWARF_FRAME_REGISTERS
+ 1; ++i
)
1053 switch (fs
->regs
.reg
[i
].how
)
1057 case REG_SAVED_OFFSET
:
1058 context
->reg
[i
] = cfa
+ fs
->regs
.reg
[i
].loc
.offset
;
1061 context
->reg
[i
] = orig_context
.reg
[fs
->regs
.reg
[i
].loc
.reg
];
1065 const unsigned char *exp
= fs
->regs
.reg
[i
].loc
.exp
;
1069 exp
= read_uleb128 (exp
, &len
);
1070 val
= execute_stack_op (exp
, exp
+ len
, &orig_context
,
1072 context
->reg
[i
] = (void *) val
;
1079 uw_update_context (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
1081 uw_update_context_1 (context
, fs
);
1083 /* Compute the return address now, since the return address column
1084 can change from frame to frame. */
1085 context
->ra
= __builtin_extract_return_addr
1086 ((void *) (_Unwind_Ptr
) _Unwind_GetGR (context
, fs
->retaddr_column
));
1089 /* Fill in CONTEXT for top-of-stack. The only valid registers at this
1090 level will be the return address and the CFA. */
1092 #define uw_init_context(CONTEXT) \
1094 /* Do any necessary initialization to access arbitrary stack frames. \
1095 On the SPARC, this means flushing the register windows. */ \
1096 __builtin_unwind_init (); \
1097 uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \
1098 __builtin_return_address (0)); \
1102 uw_init_context_1 (struct _Unwind_Context
*context
,
1103 void *outer_cfa
, void *outer_ra
)
1105 void *ra
= __builtin_extract_return_addr (__builtin_return_address (0));
1106 _Unwind_FrameState fs
;
1108 memset (context
, 0, sizeof (struct _Unwind_Context
));
1111 if (uw_frame_state_for (context
, &fs
) != _URC_NO_REASON
)
1114 /* Force the frame state to use the known cfa value. */
1115 context
->cfa
= outer_cfa
;
1116 fs
.cfa_how
= CFA_REG_OFFSET
;
1120 uw_update_context_1 (context
, &fs
);
1122 /* If the return address column was saved in a register in the
1123 initialization context, then we can't see it in the given
1124 call frame data. So have the initialization context tell us. */
1125 context
->ra
= __builtin_extract_return_addr (outer_ra
);
1129 /* Install TARGET into CURRENT so that we can return to it. This is a
1130 macro because __builtin_eh_return must be invoked in the context of
1133 #define uw_install_context(CURRENT, TARGET) \
1135 long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
1136 void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
1137 __builtin_eh_return (offset, handler); \
1141 init_dwarf_reg_size_table (void)
1143 __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table
);
1147 uw_install_context_1 (struct _Unwind_Context
*current
,
1148 struct _Unwind_Context
*target
)
1154 static __gthread_once_t once_regsizes
= __GTHREAD_ONCE_INIT
;
1155 if (__gthread_once (&once_regsizes
, init_dwarf_reg_size_table
) != 0
1156 || dwarf_reg_size_table
[0] == 0)
1157 init_dwarf_reg_size_table ();
1160 if (dwarf_reg_size_table
[0] == 0)
1161 init_dwarf_reg_size_table ();
1164 for (i
= 0; i
< DWARF_FRAME_REGISTERS
; ++i
)
1166 void *c
= current
->reg
[i
];
1167 void *t
= target
->reg
[i
];
1168 if (t
&& c
&& t
!= c
)
1169 memcpy (c
, t
, dwarf_reg_size_table
[i
]);
1172 /* We adjust SP by the difference between CURRENT and TARGET's CFA. */
1173 if (STACK_GROWS_DOWNWARD
)
1174 return target
->cfa
- current
->cfa
+ target
->args_size
;
1176 return current
->cfa
- target
->cfa
- target
->args_size
;
1179 static inline _Unwind_Ptr
1180 uw_identify_context (struct _Unwind_Context
*context
)
1182 return _Unwind_GetIP (context
);
1186 #include "unwind.inc"
1188 #endif /* !USING_SJLJ_EXCEPTIONS */