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. */
28 #include <unwind-pe.h>
29 #include <unwind-dw2-fde.h>
35 #include "unwind-pe.h"
36 #include "unwind-dw2-fde.h"
40 #if !USING_SJLJ_EXCEPTIONS
42 #ifndef STACK_GROWS_DOWNWARD
43 #define STACK_GROWS_DOWNWARD 0
45 #undef STACK_GROWS_DOWNWARD
46 #define STACK_GROWS_DOWNWARD 1
49 /* A target can override (perhaps for backward compatibility) how
50 many dwarf2 columns are unwound. */
51 #ifndef DWARF_FRAME_REGISTERS
52 #define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
55 /* This is the register and unwind state for a particular frame. */
56 struct _Unwind_Context
58 void *reg
[DWARF_FRAME_REGISTERS
+1];
62 struct dwarf_eh_bases bases
;
63 _Unwind_Word args_size
;
67 /* Byte size of every register managed by these routines. */
68 static unsigned char dwarf_reg_size_table
[DWARF_FRAME_REGISTERS
];
72 /* The result of interpreting the frame unwind info for a frame.
73 This is all symbolic at this point, as none of the values can
74 be resolved until the target pc is located. */
77 /* Each register save state can be described in terms of a CFA slot,
78 another register, or a location expression. */
79 struct frame_state_reg_info
85 const unsigned char *exp
;
93 } reg
[DWARF_FRAME_REGISTERS
+1];
95 /* Used to implement DW_CFA_remember_state. */
96 struct frame_state_reg_info
*prev
;
99 /* The CFA can be described in terms of a reg+offset or a
100 location expression. */
101 _Unwind_Sword cfa_offset
;
102 _Unwind_Word cfa_reg
;
103 const unsigned char *cfa_exp
;
110 /* The PC described by the current frame state. */
113 /* The information we care about from the CIE/FDE. */
114 _Unwind_Personality_Fn personality
;
115 signed int data_align
;
116 unsigned int code_align
;
117 unsigned char retaddr_column
;
118 unsigned char fde_encoding
;
119 unsigned char lsda_encoding
;
122 } _Unwind_FrameState
;
124 /* Read unaligned data from the instruction buffer. */
129 unsigned u2
__attribute__ ((mode (HI
)));
130 unsigned u4
__attribute__ ((mode (SI
)));
131 unsigned u8
__attribute__ ((mode (DI
)));
132 signed s2
__attribute__ ((mode (HI
)));
133 signed s4
__attribute__ ((mode (SI
)));
134 signed s8
__attribute__ ((mode (DI
)));
135 } __attribute__ ((packed
));
138 read_pointer (const void *p
) { const union unaligned
*up
= p
; return up
->p
; }
141 read_1u (const void *p
) { return *(const unsigned char *)p
; }
144 read_1s (const void *p
) { return *(const signed char *)p
; }
147 read_2u (const void *p
) { const union unaligned
*up
= p
; return up
->u2
; }
150 read_2s (const void *p
) { const union unaligned
*up
= p
; return up
->s2
; }
152 static inline unsigned int
153 read_4u (const void *p
) { const union unaligned
*up
= p
; return up
->u4
; }
156 read_4s (const void *p
) { const union unaligned
*up
= p
; return up
->s4
; }
158 static inline unsigned long
159 read_8u (const void *p
) { const union unaligned
*up
= p
; return up
->u8
; }
161 static inline unsigned long
162 read_8s (const void *p
) { const union unaligned
*up
= p
; return up
->s8
; }
164 /* Get the value of register REG as saved in CONTEXT. */
167 _Unwind_GetGR (struct _Unwind_Context
*context
, int index
)
169 /* This will segfault if the register hasn't been saved. */
170 return * (_Unwind_Word
*) context
->reg
[index
];
173 /* Overwrite the saved value for register REG in CONTEXT with VAL. */
176 _Unwind_SetGR (struct _Unwind_Context
*context
, int index
, _Unwind_Word val
)
178 * (_Unwind_Word
*) context
->reg
[index
] = val
;
181 /* Retrieve the return address for CONTEXT. */
184 _Unwind_GetIP (struct _Unwind_Context
*context
)
186 return (_Unwind_Ptr
) context
->ra
;
189 /* Overwrite the return address for CONTEXT with VAL. */
192 _Unwind_SetIP (struct _Unwind_Context
*context
, _Unwind_Ptr val
)
194 context
->ra
= (void *) val
;
198 _Unwind_GetLanguageSpecificData (struct _Unwind_Context
*context
)
200 return context
->lsda
;
204 _Unwind_GetRegionStart (struct _Unwind_Context
*context
)
206 return (_Unwind_Ptr
) context
->bases
.func
;
211 _Unwind_GetDataRelBase (struct _Unwind_Context
*context
)
213 return (_Unwind_Ptr
) context
->bases
.dbase
;
217 _Unwind_GetTextRelBase (struct _Unwind_Context
*context
)
219 return (_Unwind_Ptr
) context
->bases
.tbase
;
223 /* Extract any interesting information from the CIE for the translation
224 unit F belongs to. Return a pointer to the byte after the augmentation,
225 or NULL if we encountered an undecipherable augmentation. */
227 static const unsigned char *
228 extract_cie_info (struct dwarf_cie
*cie
, struct _Unwind_Context
*context
,
229 _Unwind_FrameState
*fs
)
231 const unsigned char *aug
= cie
->augmentation
;
232 const unsigned char *p
= aug
+ strlen (aug
) + 1;
233 const unsigned char *ret
= NULL
;
236 /* g++ v2 "eh" has pointer immediately following augmentation string,
237 so it must be handled first. */
238 if (aug
[0] == 'e' && aug
[1] == 'h')
240 fs
->eh_ptr
= read_pointer (p
);
241 p
+= sizeof (void *);
245 /* Immediately following the augmentation are the code and
246 data alignment and return address column. */
247 p
= read_uleb128 (p
, &tmp
); fs
->code_align
= tmp
;
248 p
= read_sleb128 (p
, &tmp
); fs
->data_align
= (saddr
) tmp
;
249 fs
->retaddr_column
= *p
++;
250 fs
->lsda_encoding
= DW_EH_PE_omit
;
252 /* If the augmentation starts with 'z', then a uleb128 immediately
253 follows containing the length of the augmentation field following
257 p
= read_uleb128 (p
, &tmp
);
264 /* Iterate over recognized augmentation subsequences. */
267 /* "L" indicates a byte showing how the LSDA pointer is encoded. */
270 fs
->lsda_encoding
= *p
++;
274 /* "R" indicates a byte indicating how FDE addresses are encoded. */
275 else if (aug
[0] == 'R')
277 fs
->fde_encoding
= *p
++;
281 /* "P" indicates a personality routine in the CIE augmentation. */
282 else if (aug
[0] == 'P')
284 p
= read_encoded_value (context
, *p
, p
+ 1,
285 (_Unwind_Ptr
*) &fs
->personality
);
289 /* Otherwise we have an unknown augmentation string.
290 Bail unless we saw a 'z' prefix. */
295 return ret
? ret
: p
;
299 /* Decode a DW_OP stack program. Return the top of stack. Push INITIAL
300 onto the stack to start. */
303 execute_stack_op (const unsigned char *op_ptr
, const unsigned char *op_end
,
304 struct _Unwind_Context
*context
, _Unwind_Word initial
)
306 _Unwind_Word stack
[64]; /* ??? Assume this is enough. */
312 while (op_ptr
< op_end
)
314 enum dwarf_location_atom op
= *op_ptr
++;
315 _Unwind_Word result
= 0, reg
;
316 _Unwind_Sword offset
;
353 result
= op
- DW_OP_lit0
;
357 result
= (_Unwind_Word
) (_Unwind_Ptr
) read_pointer (op_ptr
);
358 op_ptr
+= sizeof (void *);
362 result
= read_1u (op_ptr
);
366 result
= read_1s (op_ptr
);
370 result
= read_2u (op_ptr
);
374 result
= read_2s (op_ptr
);
378 result
= read_4u (op_ptr
);
382 result
= read_4s (op_ptr
);
386 result
= read_8u (op_ptr
);
390 result
= read_8s (op_ptr
);
394 op_ptr
= read_uleb128 (op_ptr
, &ptrtmp
);
398 op_ptr
= read_sleb128 (op_ptr
, &ptrtmp
);
399 result
= (saddr
)ptrtmp
;
434 result
= _Unwind_GetGR (context
, op
- DW_OP_reg0
);
437 op_ptr
= read_uleb128 (op_ptr
, &ptrtmp
); reg
= ptrtmp
;
438 result
= _Unwind_GetGR (context
, reg
);
473 op_ptr
= read_sleb128 (op_ptr
, &ptrtmp
); offset
= (saddr
)ptrtmp
;
474 result
= _Unwind_GetGR (context
, op
- DW_OP_breg0
) + offset
;
477 op_ptr
= read_uleb128 (op_ptr
, &ptrtmp
); reg
= ptrtmp
;
478 op_ptr
= read_sleb128 (op_ptr
, &ptrtmp
); offset
= (saddr
)ptrtmp
;
479 result
= _Unwind_GetGR (context
, reg
) + offset
;
485 result
= stack
[stack_elt
- 1];
495 if (offset
>= stack_elt
- 1)
497 result
= stack
[stack_elt
- 1 - offset
];
503 result
= stack
[stack_elt
- 2];
508 _Unwind_Word t1
, t2
, t3
;
512 t1
= stack
[stack_elt
- 1];
513 t2
= stack
[stack_elt
- 2];
514 t3
= stack
[stack_elt
- 3];
515 stack
[stack_elt
- 1] = t2
;
516 stack
[stack_elt
- 2] = t3
;
517 stack
[stack_elt
- 3] = t1
;
522 case DW_OP_deref_size
:
526 case DW_OP_plus_uconst
:
527 /* Unary operations. */
530 result
= stack
[stack_elt
];
536 void *ptr
= (void *)(_Unwind_Ptr
) result
;
537 result
= (_Unwind_Ptr
) read_pointer (ptr
);
541 case DW_OP_deref_size
:
543 void *ptr
= (void *)(_Unwind_Ptr
) result
;
547 result
= read_1u (ptr
);
550 result
= read_2u (ptr
);
553 result
= read_4u (ptr
);
556 result
= read_8u (ptr
);
565 if ((_Unwind_Sword
) result
< 0)
574 case DW_OP_plus_uconst
:
575 op_ptr
= read_uleb128 (op_ptr
, &ptrtmp
); reg
= ptrtmp
;
578 /* Avoid warnings. */
598 /* Binary operations. */
599 _Unwind_Word first
, second
;
600 if ((stack_elt
-= 2) < 0)
602 second
= stack
[stack_elt
];
603 first
= stack
[stack_elt
+ 1];
608 result
= second
& first
;
611 result
= (_Unwind_Sword
)second
/ (_Unwind_Sword
)first
;
614 result
= second
- first
;
617 result
= (_Unwind_Sword
)second
% (_Unwind_Sword
)first
;
620 result
= second
* first
;
623 result
= second
| first
;
626 result
= second
+ first
;
629 result
= second
<< first
;
632 result
= second
>> first
;
635 result
= (_Unwind_Sword
)second
>> first
;
638 result
= second
^ first
;
641 result
= (_Unwind_Sword
)first
<= (_Unwind_Sword
)second
;
644 result
= (_Unwind_Sword
)first
>= (_Unwind_Sword
)second
;
647 result
= (_Unwind_Sword
)first
== (_Unwind_Sword
)second
;
650 result
= (_Unwind_Sword
)first
< (_Unwind_Sword
)second
;
653 result
= (_Unwind_Sword
)first
> (_Unwind_Sword
)second
;
656 result
= (_Unwind_Sword
)first
!= (_Unwind_Sword
)second
;
659 /* Avoid warnings. */
666 offset
= read_2s (op_ptr
);
674 offset
= read_2s (op_ptr
);
676 if (stack
[stack_elt
] != 0)
687 /* Most things push a result value. */
688 if ((size_t) stack_elt
>= sizeof(stack
)/sizeof(*stack
))
690 stack
[++stack_elt
] = result
;
694 /* We were executing this program to get a value. It should be
698 return stack
[stack_elt
];
702 /* Decode DWARF 2 call frame information. Takes pointers the
703 instruction sequence to decode, current register information and
704 CIE info, and the PC range to evaluate. */
707 execute_cfa_program (const unsigned char *insn_ptr
,
708 const unsigned char *insn_end
,
709 struct _Unwind_Context
*context
,
710 _Unwind_FrameState
*fs
)
712 struct frame_state_reg_info
*unused_rs
= NULL
;
714 /* Don't allow remember/restore between CIE and FDE programs. */
715 fs
->regs
.prev
= NULL
;
717 while (insn_ptr
< insn_end
&& fs
->pc
< context
->ra
)
719 unsigned char insn
= *insn_ptr
++;
721 _Unwind_Sword offset
;
724 if ((insn
& 0xc0) == DW_CFA_advance_loc
)
725 fs
->pc
+= (insn
& 0x3f) * fs
->code_align
;
726 else if ((insn
& 0xc0) == DW_CFA_offset
)
729 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
730 offset
= ptrtmp
* fs
->data_align
;
731 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
732 fs
->regs
.reg
[reg
].loc
.offset
= offset
;
734 else if ((insn
& 0xc0) == DW_CFA_restore
)
737 fs
->regs
.reg
[reg
].how
= REG_UNSAVED
;
742 insn_ptr
= read_encoded_value (context
, fs
->fde_encoding
,
743 insn_ptr
, (_Unwind_Ptr
*) &fs
->pc
);
746 case DW_CFA_advance_loc1
:
747 fs
->pc
+= read_1u (insn_ptr
) * fs
->code_align
;
750 case DW_CFA_advance_loc2
:
751 fs
->pc
+= read_2u (insn_ptr
) * fs
->code_align
;
754 case DW_CFA_advance_loc4
:
755 fs
->pc
+= read_4u (insn_ptr
) * fs
->code_align
;
759 case DW_CFA_offset_extended
:
760 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
761 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
762 offset
= ptrtmp
* fs
->data_align
;
763 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
764 fs
->regs
.reg
[reg
].loc
.offset
= offset
;
767 case DW_CFA_restore_extended
:
768 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
769 fs
->regs
.reg
[reg
].how
= REG_UNSAVED
;
772 case DW_CFA_undefined
:
773 case DW_CFA_same_value
:
777 case DW_CFA_register
:
780 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
781 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg2
= ptrtmp
;
782 fs
->regs
.reg
[reg
].how
= REG_SAVED_REG
;
783 fs
->regs
.reg
[reg
].loc
.reg
= reg2
;
787 case DW_CFA_remember_state
:
789 struct frame_state_reg_info
*new_rs
;
793 unused_rs
= unused_rs
->prev
;
796 new_rs
= alloca (sizeof (struct frame_state_reg_info
));
799 fs
->regs
.prev
= new_rs
;
803 case DW_CFA_restore_state
:
805 struct frame_state_reg_info
*old_rs
= fs
->regs
.prev
;
807 old_rs
->prev
= unused_rs
;
813 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
814 fs
->cfa_reg
= ptrtmp
;
815 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
816 fs
->cfa_offset
= ptrtmp
;
817 fs
->cfa_how
= CFA_REG_OFFSET
;
820 case DW_CFA_def_cfa_register
:
821 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
822 fs
->cfa_reg
= ptrtmp
;
823 fs
->cfa_how
= CFA_REG_OFFSET
;
826 case DW_CFA_def_cfa_offset
:
827 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
828 fs
->cfa_offset
= ptrtmp
;
829 /* cfa_how deliberately not set. */
832 case DW_CFA_def_cfa_expression
:
833 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
834 fs
->cfa_exp
= insn_ptr
;
835 fs
->cfa_how
= CFA_EXP
;
839 case DW_CFA_expression
:
840 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
841 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
842 fs
->regs
.reg
[reg
].how
= REG_SAVED_EXP
;
843 fs
->regs
.reg
[reg
].loc
.exp
= insn_ptr
;
847 /* From the 2.1 draft. */
848 case DW_CFA_offset_extended_sf
:
849 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
850 insn_ptr
= read_sleb128 (insn_ptr
, &ptrtmp
);
851 offset
= (saddr
)ptrtmp
* fs
->data_align
;
852 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
853 fs
->regs
.reg
[reg
].loc
.offset
= offset
;
856 case DW_CFA_def_cfa_sf
:
857 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
858 fs
->cfa_reg
= ptrtmp
;
859 insn_ptr
= read_sleb128 (insn_ptr
, &ptrtmp
);
860 fs
->cfa_offset
= (saddr
)ptrtmp
;
861 fs
->cfa_how
= CFA_REG_OFFSET
;
864 case DW_CFA_def_cfa_offset_sf
:
865 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
866 fs
->cfa_offset
= ptrtmp
;
867 /* cfa_how deliberately not set. */
870 case DW_CFA_GNU_window_save
:
871 /* ??? Hardcoded for SPARC register window configuration. */
872 for (reg
= 16; reg
< 32; ++reg
)
874 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
875 fs
->regs
.reg
[reg
].loc
.offset
= (reg
- 16) * sizeof (void *);
879 case DW_CFA_GNU_args_size
:
880 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
881 context
->args_size
= ptrtmp
;
884 case DW_CFA_GNU_negative_offset_extended
:
885 /* Obsoleted by DW_CFA_offset_extended_sf, but used by
886 older PowerPC code. */
887 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
); reg
= ptrtmp
;
888 insn_ptr
= read_uleb128 (insn_ptr
, &ptrtmp
);
889 offset
= ptrtmp
* fs
->data_align
;
890 fs
->regs
.reg
[reg
].how
= REG_SAVED_OFFSET
;
891 fs
->regs
.reg
[reg
].loc
.offset
= -offset
;
900 static _Unwind_Reason_Code
901 uw_frame_state_for (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
903 struct dwarf_fde
*fde
;
904 struct dwarf_cie
*cie
;
905 const unsigned char *aug
, *insn
, *end
;
907 memset (fs
, 0, sizeof (*fs
));
908 context
->args_size
= 0;
911 fde
= _Unwind_Find_FDE (context
->ra
- 1, &context
->bases
);
914 /* Couldn't find frame unwind info for this function. Try a
915 target-specific fallback mechanism. This will necessarily
916 not profide a personality routine or LSDA. */
917 #ifdef MD_FALLBACK_FRAME_STATE_FOR
918 MD_FALLBACK_FRAME_STATE_FOR (context
, fs
, success
);
919 return _URC_END_OF_STACK
;
921 return _URC_NO_REASON
;
923 return _URC_END_OF_STACK
;
927 fs
->pc
= context
->bases
.func
;
930 insn
= extract_cie_info (cie
, context
, fs
);
932 /* CIE contained unknown augmentation. */
933 return _URC_FATAL_PHASE1_ERROR
;
935 /* First decode all the insns in the CIE. */
936 end
= (unsigned char *) next_fde ((struct dwarf_fde
*) cie
);
937 execute_cfa_program (insn
, end
, context
, fs
);
939 /* Locate augmentation for the fde. */
940 aug
= (unsigned char *)fde
+ sizeof (*fde
);
941 aug
+= 2 * size_of_encoded_value (fs
->fde_encoding
);
946 aug
= read_uleb128 (aug
, &i
);
949 if (fs
->lsda_encoding
!= DW_EH_PE_omit
)
950 aug
= read_encoded_value (context
, fs
->lsda_encoding
, aug
,
951 (_Unwind_Ptr
*) &context
->lsda
);
953 /* Then the insns in the FDE up to our target PC. */
956 end
= (unsigned char *) next_fde (fde
);
957 execute_cfa_program (insn
, end
, context
, fs
);
959 return _URC_NO_REASON
;
962 typedef struct frame_state
968 long reg_or_offset
[DWARF_FRAME_REGISTERS
+1];
969 unsigned short cfa_reg
;
970 unsigned short retaddr_column
;
971 char saved
[DWARF_FRAME_REGISTERS
+1];
974 struct frame_state
* __frame_state_for (void *, struct frame_state
*);
976 /* Called from pre-G++ 3.0 __throw to find the registers to restore for
977 a given PC_TARGET. The caller should allocate a local variable of
978 `struct frame_state' and pass its address to STATE_IN. */
981 __frame_state_for (void *pc_target
, struct frame_state
*state_in
)
983 struct _Unwind_Context context
;
984 _Unwind_FrameState fs
;
987 memset (&context
, 0, sizeof (struct _Unwind_Context
));
988 context
.ra
= pc_target
+ 1;
990 if (uw_frame_state_for (&context
, &fs
) != _URC_NO_REASON
)
993 /* We have no way to pass a location expression for the CFA to our
994 caller. It wouldn't understand it anyway. */
995 if (fs
.cfa_how
== CFA_EXP
)
998 for (reg
= 0; reg
< DWARF_FRAME_REGISTERS
+ 1; reg
++)
1000 state_in
->saved
[reg
] = fs
.regs
.reg
[reg
].how
;
1001 switch (state_in
->saved
[reg
])
1004 state_in
->reg_or_offset
[reg
] = fs
.regs
.reg
[reg
].loc
.reg
;
1006 case REG_SAVED_OFFSET
:
1007 state_in
->reg_or_offset
[reg
] = fs
.regs
.reg
[reg
].loc
.offset
;
1010 state_in
->reg_or_offset
[reg
] = 0;
1015 state_in
->cfa_offset
= fs
.cfa_offset
;
1016 state_in
->cfa_reg
= fs
.cfa_reg
;
1017 state_in
->retaddr_column
= fs
.retaddr_column
;
1018 state_in
->args_size
= context
.args_size
;
1019 state_in
->eh_ptr
= fs
.eh_ptr
;
1027 uw_update_context_1 (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
1029 struct _Unwind_Context orig_context
= *context
;
1033 /* Compute this frame's CFA. */
1034 switch (fs
->cfa_how
)
1036 case CFA_REG_OFFSET
:
1037 /* Special handling here: Many machines do not use a frame pointer,
1038 and track the CFA only through offsets from the stack pointer from
1039 one frame to the next. In this case, the stack pointer is never
1040 stored, so it has no saved address in the context. What we do
1041 have is the CFA from the previous stack frame. */
1042 if (context
->reg
[fs
->cfa_reg
] == NULL
)
1045 cfa
= (void *) (_Unwind_Ptr
) _Unwind_GetGR (context
, fs
->cfa_reg
);
1046 cfa
+= fs
->cfa_offset
;
1050 /* ??? No way of knowing what register number is the stack pointer
1051 to do the same sort of handling as above. Assume that if the
1052 CFA calculation is so complicated as to require a stack program
1053 that this will not be a problem. */
1055 const unsigned char *exp
= fs
->cfa_exp
;
1058 exp
= read_uleb128 (exp
, &len
);
1059 cfa
= (void *) (_Unwind_Ptr
)
1060 execute_stack_op (exp
, exp
+ len
, context
, 0);
1069 /* Compute the addresses of all registers saved in this frame. */
1070 for (i
= 0; i
< DWARF_FRAME_REGISTERS
+ 1; ++i
)
1071 switch (fs
->regs
.reg
[i
].how
)
1075 case REG_SAVED_OFFSET
:
1076 context
->reg
[i
] = cfa
+ fs
->regs
.reg
[i
].loc
.offset
;
1079 context
->reg
[i
] = orig_context
.reg
[fs
->regs
.reg
[i
].loc
.reg
];
1083 const unsigned char *exp
= fs
->regs
.reg
[i
].loc
.exp
;
1087 exp
= read_uleb128 (exp
, &len
);
1088 val
= execute_stack_op (exp
, exp
+ len
, &orig_context
,
1090 context
->reg
[i
] = (void *) val
;
1097 uw_update_context (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
1099 uw_update_context_1 (context
, fs
);
1101 /* Compute the return address now, since the return address column
1102 can change from frame to frame. */
1103 context
->ra
= __builtin_extract_return_addr
1104 ((void *) (_Unwind_Ptr
) _Unwind_GetGR (context
, fs
->retaddr_column
));
1107 /* Fill in CONTEXT for top-of-stack. The only valid registers at this
1108 level will be the return address and the CFA. */
1110 #define uw_init_context(CONTEXT) \
1112 /* Do any necessary initialization to access arbitrary stack frames. \
1113 On the SPARC, this means flushing the register windows. */ \
1114 __builtin_unwind_init (); \
1115 uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \
1116 __builtin_return_address (0)); \
1120 uw_init_context_1 (struct _Unwind_Context
*context
,
1121 void *outer_cfa
, void *outer_ra
)
1123 void *ra
= __builtin_extract_return_addr (__builtin_return_address (0));
1124 _Unwind_FrameState fs
;
1126 memset (context
, 0, sizeof (struct _Unwind_Context
));
1129 if (uw_frame_state_for (context
, &fs
) != _URC_NO_REASON
)
1132 /* Force the frame state to use the known cfa value. */
1133 context
->cfa
= outer_cfa
;
1134 fs
.cfa_how
= CFA_REG_OFFSET
;
1138 uw_update_context_1 (context
, &fs
);
1140 /* If the return address column was saved in a register in the
1141 initialization context, then we can't see it in the given
1142 call frame data. So have the initialization context tell us. */
1143 context
->ra
= __builtin_extract_return_addr (outer_ra
);
1147 /* Install TARGET into CURRENT so that we can return to it. This is a
1148 macro because __builtin_eh_return must be invoked in the context of
1151 #define uw_install_context(CURRENT, TARGET) \
1153 long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
1154 void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
1155 __builtin_eh_return (offset, handler); \
1159 init_dwarf_reg_size_table (void)
1161 __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table
);
1165 uw_install_context_1 (struct _Unwind_Context
*current
,
1166 struct _Unwind_Context
*target
)
1172 static __gthread_once_t once_regsizes
= __GTHREAD_ONCE_INIT
;
1173 if (__gthread_once (&once_regsizes
, init_dwarf_reg_size_table
) != 0
1174 || dwarf_reg_size_table
[0] == 0)
1175 init_dwarf_reg_size_table ();
1178 if (dwarf_reg_size_table
[0] == 0)
1179 init_dwarf_reg_size_table ();
1182 for (i
= 0; i
< DWARF_FRAME_REGISTERS
; ++i
)
1184 void *c
= current
->reg
[i
];
1185 void *t
= target
->reg
[i
];
1186 if (t
&& c
&& t
!= c
)
1187 memcpy (c
, t
, dwarf_reg_size_table
[i
]);
1190 /* We adjust SP by the difference between CURRENT and TARGET's CFA. */
1191 if (STACK_GROWS_DOWNWARD
)
1192 return target
->cfa
- current
->cfa
+ target
->args_size
;
1194 return current
->cfa
- target
->cfa
- target
->args_size
;
1197 static inline _Unwind_Ptr
1198 uw_identify_context (struct _Unwind_Context
*context
)
1200 return _Unwind_GetIP (context
);
1204 #include "unwind.inc"
1207 #endif /* !USING_SJLJ_EXCEPTIONS */