1af526226Smrg /* DWARF2 exception handling and frame unwind runtime interface routines.
2*2f055536Smrg Copyright (C) 1997-2020 Free Software Foundation, Inc.
3af526226Smrg
4af526226Smrg This file is part of GCC.
5af526226Smrg
6af526226Smrg GCC is free software; you can redistribute it and/or modify it
7af526226Smrg under the terms of the GNU General Public License as published by
8af526226Smrg the Free Software Foundation; either version 3, or (at your option)
9af526226Smrg any later version.
10af526226Smrg
11af526226Smrg GCC is distributed in the hope that it will be useful, but WITHOUT
12af526226Smrg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13af526226Smrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14af526226Smrg License for more details.
15af526226Smrg
16af526226Smrg Under Section 7 of GPL version 3, you are granted additional
17af526226Smrg permissions described in the GCC Runtime Library Exception, version
18af526226Smrg 3.1, as published by the Free Software Foundation.
19af526226Smrg
20af526226Smrg You should have received a copy of the GNU General Public License and
21af526226Smrg a copy of the GCC Runtime Library Exception along with this program;
22af526226Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23af526226Smrg <http://www.gnu.org/licenses/>. */
24af526226Smrg
25af526226Smrg #include "tconfig.h"
26af526226Smrg #include "tsystem.h"
27af526226Smrg #include "coretypes.h"
28af526226Smrg #include "tm.h"
29af526226Smrg #include "dwarf2.h"
30af526226Smrg #include "unwind.h"
31af526226Smrg #ifdef __USING_SJLJ_EXCEPTIONS__
32af526226Smrg # define NO_SIZE_OF_ENCODED_VALUE
33af526226Smrg #endif
34af526226Smrg #include "unwind-pe.h"
35af526226Smrg #include "unwind-dw2-fde.h"
36af526226Smrg #include "gthr.h"
37af526226Smrg #include "unwind-dw2.h"
38af526226Smrg
39af526226Smrg #ifdef HAVE_SYS_SDT_H
40af526226Smrg #include <sys/sdt.h>
41af526226Smrg #endif
42af526226Smrg
43af526226Smrg #ifndef __USING_SJLJ_EXCEPTIONS__
44af526226Smrg
454646d632Smrg #ifndef __LIBGCC_STACK_GROWS_DOWNWARD__
464646d632Smrg #define __LIBGCC_STACK_GROWS_DOWNWARD__ 0
47af526226Smrg #else
484646d632Smrg #undef __LIBGCC_STACK_GROWS_DOWNWARD__
494646d632Smrg #define __LIBGCC_STACK_GROWS_DOWNWARD__ 1
50af526226Smrg #endif
51af526226Smrg
52af526226Smrg /* Dwarf frame registers used for pre gcc 3.0 compiled glibc. */
53af526226Smrg #ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
544646d632Smrg #define PRE_GCC3_DWARF_FRAME_REGISTERS __LIBGCC_DWARF_FRAME_REGISTERS__
55af526226Smrg #endif
56af526226Smrg
57af526226Smrg #ifndef DWARF_REG_TO_UNWIND_COLUMN
58af526226Smrg #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
59af526226Smrg #endif
60af526226Smrg
61af526226Smrg #ifdef REG_VALUE_IN_UNWIND_CONTEXT
62af526226Smrg typedef _Unwind_Word _Unwind_Context_Reg_Val;
63af526226Smrg
64af526226Smrg #ifndef ASSUME_EXTENDED_UNWIND_CONTEXT
65af526226Smrg #define ASSUME_EXTENDED_UNWIND_CONTEXT 1
66af526226Smrg #endif
67af526226Smrg
68af526226Smrg static inline _Unwind_Word
_Unwind_Get_Unwind_Word(_Unwind_Context_Reg_Val val)69af526226Smrg _Unwind_Get_Unwind_Word (_Unwind_Context_Reg_Val val)
70af526226Smrg {
71af526226Smrg return val;
72af526226Smrg }
73af526226Smrg
74af526226Smrg static inline _Unwind_Context_Reg_Val
_Unwind_Get_Unwind_Context_Reg_Val(_Unwind_Word val)75af526226Smrg _Unwind_Get_Unwind_Context_Reg_Val (_Unwind_Word val)
76af526226Smrg {
77af526226Smrg return val;
78af526226Smrg }
79af526226Smrg #else
80af526226Smrg typedef void *_Unwind_Context_Reg_Val;
81af526226Smrg
82af526226Smrg static inline _Unwind_Word
_Unwind_Get_Unwind_Word(_Unwind_Context_Reg_Val val)83af526226Smrg _Unwind_Get_Unwind_Word (_Unwind_Context_Reg_Val val)
84af526226Smrg {
85af526226Smrg return (_Unwind_Word) (_Unwind_Internal_Ptr) val;
86af526226Smrg }
87af526226Smrg
88af526226Smrg static inline _Unwind_Context_Reg_Val
_Unwind_Get_Unwind_Context_Reg_Val(_Unwind_Word val)89af526226Smrg _Unwind_Get_Unwind_Context_Reg_Val (_Unwind_Word val)
90af526226Smrg {
91af526226Smrg return (_Unwind_Context_Reg_Val) (_Unwind_Internal_Ptr) val;
92af526226Smrg }
93af526226Smrg #endif
94af526226Smrg
95af526226Smrg #ifndef ASSUME_EXTENDED_UNWIND_CONTEXT
96af526226Smrg #define ASSUME_EXTENDED_UNWIND_CONTEXT 0
97af526226Smrg #endif
98af526226Smrg
99af526226Smrg /* This is the register and unwind state for a particular frame. This
100af526226Smrg provides the information necessary to unwind up past a frame and return
101af526226Smrg to its caller. */
102af526226Smrg struct _Unwind_Context
103af526226Smrg {
1044646d632Smrg _Unwind_Context_Reg_Val reg[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
105af526226Smrg void *cfa;
106af526226Smrg void *ra;
107af526226Smrg void *lsda;
108af526226Smrg struct dwarf_eh_bases bases;
109af526226Smrg /* Signal frame context. */
110af526226Smrg #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
111af526226Smrg /* Context which has version/args_size/by_value fields. */
112af526226Smrg #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
113af526226Smrg _Unwind_Word flags;
114af526226Smrg /* 0 for now, can be increased when further fields are added to
115af526226Smrg struct _Unwind_Context. */
116af526226Smrg _Unwind_Word version;
117af526226Smrg _Unwind_Word args_size;
1184646d632Smrg char by_value[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
119af526226Smrg };
120af526226Smrg
121af526226Smrg /* Byte size of every register managed by these routines. */
1224646d632Smrg static unsigned char dwarf_reg_size_table[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
123af526226Smrg
124af526226Smrg
125af526226Smrg /* Read unaligned data from the instruction buffer. */
126af526226Smrg
127af526226Smrg union unaligned
128af526226Smrg {
129af526226Smrg void *p;
130af526226Smrg unsigned u2 __attribute__ ((mode (HI)));
131af526226Smrg unsigned u4 __attribute__ ((mode (SI)));
132af526226Smrg unsigned u8 __attribute__ ((mode (DI)));
133af526226Smrg signed s2 __attribute__ ((mode (HI)));
134af526226Smrg signed s4 __attribute__ ((mode (SI)));
135af526226Smrg signed s8 __attribute__ ((mode (DI)));
136af526226Smrg } __attribute__ ((packed));
137af526226Smrg
138af526226Smrg static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
139af526226Smrg static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
140af526226Smrg _Unwind_FrameState *);
141af526226Smrg
142af526226Smrg static inline void *
read_pointer(const void * p)143af526226Smrg read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
144af526226Smrg
145af526226Smrg static inline int
read_1u(const void * p)146af526226Smrg read_1u (const void *p) { return *(const unsigned char *) p; }
147af526226Smrg
148af526226Smrg static inline int
read_1s(const void * p)149af526226Smrg read_1s (const void *p) { return *(const signed char *) p; }
150af526226Smrg
151af526226Smrg static inline int
read_2u(const void * p)152af526226Smrg read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
153af526226Smrg
154af526226Smrg static inline int
read_2s(const void * p)155af526226Smrg read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
156af526226Smrg
157af526226Smrg static inline unsigned int
read_4u(const void * p)158af526226Smrg read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
159af526226Smrg
160af526226Smrg static inline int
read_4s(const void * p)161af526226Smrg read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
162af526226Smrg
163af526226Smrg static inline unsigned long
read_8u(const void * p)164af526226Smrg read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
165af526226Smrg
166af526226Smrg static inline unsigned long
read_8s(const void * p)167af526226Smrg read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
168af526226Smrg
169af526226Smrg static inline _Unwind_Word
_Unwind_IsSignalFrame(struct _Unwind_Context * context)170af526226Smrg _Unwind_IsSignalFrame (struct _Unwind_Context *context)
171af526226Smrg {
172af526226Smrg return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
173af526226Smrg }
174af526226Smrg
175af526226Smrg static inline void
_Unwind_SetSignalFrame(struct _Unwind_Context * context,int val)176af526226Smrg _Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
177af526226Smrg {
178af526226Smrg if (val)
179af526226Smrg context->flags |= SIGNAL_FRAME_BIT;
180af526226Smrg else
181af526226Smrg context->flags &= ~SIGNAL_FRAME_BIT;
182af526226Smrg }
183af526226Smrg
184af526226Smrg static inline _Unwind_Word
_Unwind_IsExtendedContext(struct _Unwind_Context * context)185af526226Smrg _Unwind_IsExtendedContext (struct _Unwind_Context *context)
186af526226Smrg {
187af526226Smrg return (ASSUME_EXTENDED_UNWIND_CONTEXT
188af526226Smrg || (context->flags & EXTENDED_CONTEXT_BIT));
189af526226Smrg }
190af526226Smrg
191af526226Smrg /* Get the value of register INDEX as saved in CONTEXT. */
192af526226Smrg
193af526226Smrg inline _Unwind_Word
_Unwind_GetGR(struct _Unwind_Context * context,int index)194af526226Smrg _Unwind_GetGR (struct _Unwind_Context *context, int index)
195af526226Smrg {
196af526226Smrg int size;
197af526226Smrg _Unwind_Context_Reg_Val val;
198af526226Smrg
199af526226Smrg #ifdef DWARF_ZERO_REG
200af526226Smrg if (index == DWARF_ZERO_REG)
201af526226Smrg return 0;
202af526226Smrg #endif
203af526226Smrg
204af526226Smrg index = DWARF_REG_TO_UNWIND_COLUMN (index);
205af526226Smrg gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
206af526226Smrg size = dwarf_reg_size_table[index];
207af526226Smrg val = context->reg[index];
208af526226Smrg
209af526226Smrg if (_Unwind_IsExtendedContext (context) && context->by_value[index])
210af526226Smrg return _Unwind_Get_Unwind_Word (val);
211af526226Smrg
212af526226Smrg /* This will segfault if the register hasn't been saved. */
213af526226Smrg if (size == sizeof(_Unwind_Ptr))
214af526226Smrg return * (_Unwind_Ptr *) (_Unwind_Internal_Ptr) val;
215af526226Smrg else
216af526226Smrg {
217af526226Smrg gcc_assert (size == sizeof(_Unwind_Word));
218af526226Smrg return * (_Unwind_Word *) (_Unwind_Internal_Ptr) val;
219af526226Smrg }
220af526226Smrg }
221af526226Smrg
222af526226Smrg static inline void *
_Unwind_GetPtr(struct _Unwind_Context * context,int index)223af526226Smrg _Unwind_GetPtr (struct _Unwind_Context *context, int index)
224af526226Smrg {
225af526226Smrg return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index);
226af526226Smrg }
227af526226Smrg
228af526226Smrg /* Get the value of the CFA as saved in CONTEXT. */
229af526226Smrg
230af526226Smrg _Unwind_Word
_Unwind_GetCFA(struct _Unwind_Context * context)231af526226Smrg _Unwind_GetCFA (struct _Unwind_Context *context)
232af526226Smrg {
233af526226Smrg return (_Unwind_Ptr) context->cfa;
234af526226Smrg }
235af526226Smrg
236af526226Smrg /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */
237af526226Smrg
238af526226Smrg inline void
_Unwind_SetGR(struct _Unwind_Context * context,int index,_Unwind_Word val)239af526226Smrg _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
240af526226Smrg {
241af526226Smrg int size;
242af526226Smrg void *ptr;
243af526226Smrg
244af526226Smrg index = DWARF_REG_TO_UNWIND_COLUMN (index);
245af526226Smrg gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
246af526226Smrg size = dwarf_reg_size_table[index];
247af526226Smrg
248af526226Smrg if (_Unwind_IsExtendedContext (context) && context->by_value[index])
249af526226Smrg {
250af526226Smrg context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val);
251af526226Smrg return;
252af526226Smrg }
253af526226Smrg
254af526226Smrg ptr = (void *) (_Unwind_Internal_Ptr) context->reg[index];
255af526226Smrg
256af526226Smrg if (size == sizeof(_Unwind_Ptr))
257af526226Smrg * (_Unwind_Ptr *) ptr = val;
258af526226Smrg else
259af526226Smrg {
260af526226Smrg #if defined( __CR16C__ )
261af526226Smrg if (size == sizeof(_Unwind_Word))
262af526226Smrg * (_Unwind_Word *) ptr = val;
263af526226Smrg else
264af526226Smrg {
265af526226Smrg typedef unsigned _CR16_Unwind_Word __attribute__((__mode__(__word__)));
266af526226Smrg gcc_assert (index + 1 < (int) sizeof(dwarf_reg_size_table));
267af526226Smrg * (_CR16_Unwind_Word *) ptr = val & 0xffff ; /* low 16-bit */
268af526226Smrg ptr = context->reg[index + 1];
269af526226Smrg * (_CR16_Unwind_Word *) ptr = val >> 16 ; /* high 16-bit */
270af526226Smrg }
271af526226Smrg #else
272af526226Smrg gcc_assert (size == sizeof(_Unwind_Word));
273af526226Smrg * (_Unwind_Word *) ptr = val;
274af526226Smrg #endif
275af526226Smrg }
276af526226Smrg }
277af526226Smrg
278af526226Smrg /* Get the pointer to a register INDEX as saved in CONTEXT. */
279af526226Smrg
280af526226Smrg static inline void *
_Unwind_GetGRPtr(struct _Unwind_Context * context,int index)281af526226Smrg _Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
282af526226Smrg {
283af526226Smrg index = DWARF_REG_TO_UNWIND_COLUMN (index);
284af526226Smrg if (_Unwind_IsExtendedContext (context) && context->by_value[index])
285af526226Smrg return &context->reg[index];
286af526226Smrg return (void *) (_Unwind_Internal_Ptr) context->reg[index];
287af526226Smrg }
288af526226Smrg
289af526226Smrg /* Set the pointer to a register INDEX as saved in CONTEXT. */
290af526226Smrg
291af526226Smrg static inline void
_Unwind_SetGRPtr(struct _Unwind_Context * context,int index,void * p)292af526226Smrg _Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
293af526226Smrg {
294af526226Smrg index = DWARF_REG_TO_UNWIND_COLUMN (index);
295af526226Smrg if (_Unwind_IsExtendedContext (context))
296af526226Smrg context->by_value[index] = 0;
297af526226Smrg context->reg[index] = (_Unwind_Context_Reg_Val) (_Unwind_Internal_Ptr) p;
298af526226Smrg }
299af526226Smrg
300af526226Smrg /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */
301af526226Smrg
302af526226Smrg static inline void
_Unwind_SetGRValue(struct _Unwind_Context * context,int index,_Unwind_Word val)303af526226Smrg _Unwind_SetGRValue (struct _Unwind_Context *context, int index,
304af526226Smrg _Unwind_Word val)
305af526226Smrg {
306af526226Smrg index = DWARF_REG_TO_UNWIND_COLUMN (index);
307af526226Smrg gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
308af526226Smrg gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Context_Reg_Val));
309af526226Smrg
310af526226Smrg context->by_value[index] = 1;
311af526226Smrg context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val);
312af526226Smrg }
313af526226Smrg
314af526226Smrg /* Return nonzero if register INDEX is stored by value rather than
315af526226Smrg by reference. */
316af526226Smrg
317af526226Smrg static inline int
_Unwind_GRByValue(struct _Unwind_Context * context,int index)318af526226Smrg _Unwind_GRByValue (struct _Unwind_Context *context, int index)
319af526226Smrg {
320af526226Smrg index = DWARF_REG_TO_UNWIND_COLUMN (index);
321af526226Smrg return context->by_value[index];
322af526226Smrg }
323af526226Smrg
324af526226Smrg /* Retrieve the return address for CONTEXT. */
325af526226Smrg
326af526226Smrg inline _Unwind_Ptr
_Unwind_GetIP(struct _Unwind_Context * context)327af526226Smrg _Unwind_GetIP (struct _Unwind_Context *context)
328af526226Smrg {
329af526226Smrg return (_Unwind_Ptr) context->ra;
330af526226Smrg }
331af526226Smrg
332af526226Smrg /* Retrieve the return address and flag whether that IP is before
333af526226Smrg or after first not yet fully executed instruction. */
334af526226Smrg
335af526226Smrg inline _Unwind_Ptr
_Unwind_GetIPInfo(struct _Unwind_Context * context,int * ip_before_insn)336af526226Smrg _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
337af526226Smrg {
338af526226Smrg *ip_before_insn = _Unwind_IsSignalFrame (context);
339af526226Smrg return (_Unwind_Ptr) context->ra;
340af526226Smrg }
341af526226Smrg
342af526226Smrg /* Overwrite the return address for CONTEXT with VAL. */
343af526226Smrg
344af526226Smrg inline void
_Unwind_SetIP(struct _Unwind_Context * context,_Unwind_Ptr val)345af526226Smrg _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
346af526226Smrg {
347af526226Smrg context->ra = (void *) val;
348af526226Smrg }
349af526226Smrg
350f062cf65Sjoerg _Unwind_Ptr
_Unwind_GetLanguageSpecificData(struct _Unwind_Context * context)351af526226Smrg _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
352af526226Smrg {
353af526226Smrg return context->lsda;
354af526226Smrg }
355af526226Smrg
356af526226Smrg _Unwind_Ptr
_Unwind_GetRegionStart(struct _Unwind_Context * context)357af526226Smrg _Unwind_GetRegionStart (struct _Unwind_Context *context)
358af526226Smrg {
359af526226Smrg return (_Unwind_Ptr) context->bases.func;
360af526226Smrg }
361af526226Smrg
362af526226Smrg void *
_Unwind_FindEnclosingFunction(void * pc)363af526226Smrg _Unwind_FindEnclosingFunction (void *pc)
364af526226Smrg {
365af526226Smrg struct dwarf_eh_bases bases;
366af526226Smrg const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
367af526226Smrg if (fde)
368af526226Smrg return bases.func;
369af526226Smrg else
370af526226Smrg return NULL;
371af526226Smrg }
372af526226Smrg
373af526226Smrg _Unwind_Ptr
_Unwind_GetDataRelBase(struct _Unwind_Context * context)374af526226Smrg _Unwind_GetDataRelBase (struct _Unwind_Context *context)
375af526226Smrg {
376af526226Smrg return (_Unwind_Ptr) context->bases.dbase;
377af526226Smrg }
378af526226Smrg
379af526226Smrg _Unwind_Ptr
_Unwind_GetTextRelBase(struct _Unwind_Context * context)380af526226Smrg _Unwind_GetTextRelBase (struct _Unwind_Context *context)
381af526226Smrg {
382af526226Smrg return (_Unwind_Ptr) context->bases.tbase;
383af526226Smrg }
384af526226Smrg
385af526226Smrg #include "md-unwind-support.h"
386af526226Smrg
387af526226Smrg /* Extract any interesting information from the CIE for the translation
388af526226Smrg unit F belongs to. Return a pointer to the byte after the augmentation,
389af526226Smrg or NULL if we encountered an undecipherable augmentation. */
390af526226Smrg
391af526226Smrg static const unsigned char *
extract_cie_info(const struct dwarf_cie * cie,struct _Unwind_Context * context,_Unwind_FrameState * fs)392af526226Smrg extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
393af526226Smrg _Unwind_FrameState *fs)
394af526226Smrg {
395af526226Smrg const unsigned char *aug = cie->augmentation;
396af526226Smrg const unsigned char *p = aug + strlen ((const char *)aug) + 1;
397af526226Smrg const unsigned char *ret = NULL;
398af526226Smrg _uleb128_t utmp;
399af526226Smrg _sleb128_t stmp;
400af526226Smrg
401af526226Smrg /* g++ v2 "eh" has pointer immediately following augmentation string,
402af526226Smrg so it must be handled first. */
403af526226Smrg if (aug[0] == 'e' && aug[1] == 'h')
404af526226Smrg {
405af526226Smrg fs->eh_ptr = read_pointer (p);
406af526226Smrg p += sizeof (void *);
407af526226Smrg aug += 2;
408af526226Smrg }
409af526226Smrg
410af526226Smrg /* After the augmentation resp. pointer for "eh" augmentation
411af526226Smrg follows for CIE version >= 4 address size byte and
412af526226Smrg segment size byte. */
413af526226Smrg if (__builtin_expect (cie->version >= 4, 0))
414af526226Smrg {
415af526226Smrg if (p[0] != sizeof (void *) || p[1] != 0)
416af526226Smrg return NULL;
417af526226Smrg p += 2;
418af526226Smrg }
419af526226Smrg /* Immediately following this are the code and
420af526226Smrg data alignment and return address column. */
421af526226Smrg p = read_uleb128 (p, &utmp);
422af526226Smrg fs->code_align = (_Unwind_Word)utmp;
423af526226Smrg p = read_sleb128 (p, &stmp);
424af526226Smrg fs->data_align = (_Unwind_Sword)stmp;
425af526226Smrg if (cie->version == 1)
426af526226Smrg fs->retaddr_column = *p++;
427af526226Smrg else
428af526226Smrg {
429af526226Smrg p = read_uleb128 (p, &utmp);
430af526226Smrg fs->retaddr_column = (_Unwind_Word)utmp;
431af526226Smrg }
432af526226Smrg fs->lsda_encoding = DW_EH_PE_omit;
433af526226Smrg
434af526226Smrg /* If the augmentation starts with 'z', then a uleb128 immediately
435af526226Smrg follows containing the length of the augmentation field following
436af526226Smrg the size. */
437af526226Smrg if (*aug == 'z')
438af526226Smrg {
439af526226Smrg p = read_uleb128 (p, &utmp);
440af526226Smrg ret = p + utmp;
441af526226Smrg
442af526226Smrg fs->saw_z = 1;
443af526226Smrg ++aug;
444af526226Smrg }
445af526226Smrg
446af526226Smrg /* Iterate over recognized augmentation subsequences. */
447af526226Smrg while (*aug != '\0')
448af526226Smrg {
449af526226Smrg /* "L" indicates a byte showing how the LSDA pointer is encoded. */
450af526226Smrg if (aug[0] == 'L')
451af526226Smrg {
452af526226Smrg fs->lsda_encoding = *p++;
453af526226Smrg aug += 1;
454af526226Smrg }
455af526226Smrg
456af526226Smrg /* "R" indicates a byte indicating how FDE addresses are encoded. */
457af526226Smrg else if (aug[0] == 'R')
458af526226Smrg {
459af526226Smrg fs->fde_encoding = *p++;
460af526226Smrg aug += 1;
461af526226Smrg }
462af526226Smrg
463af526226Smrg /* "P" indicates a personality routine in the CIE augmentation. */
464af526226Smrg else if (aug[0] == 'P')
465af526226Smrg {
466af526226Smrg _Unwind_Ptr personality;
467af526226Smrg
468af526226Smrg p = read_encoded_value (context, *p, p + 1, &personality);
469af526226Smrg fs->personality = (_Unwind_Personality_Fn) personality;
470af526226Smrg aug += 1;
471af526226Smrg }
472af526226Smrg
473af526226Smrg /* "S" indicates a signal frame. */
474af526226Smrg else if (aug[0] == 'S')
475af526226Smrg {
476af526226Smrg fs->signal_frame = 1;
477af526226Smrg aug += 1;
478af526226Smrg }
479af526226Smrg
480af526226Smrg /* Otherwise we have an unknown augmentation string.
481af526226Smrg Bail unless we saw a 'z' prefix. */
482af526226Smrg else
483af526226Smrg return ret;
484af526226Smrg }
485af526226Smrg
486af526226Smrg return ret ? ret : p;
487af526226Smrg }
488af526226Smrg
489af526226Smrg
490af526226Smrg /* Decode a DW_OP stack program. Return the top of stack. Push INITIAL
491af526226Smrg onto the stack to start. */
492af526226Smrg
493af526226Smrg static _Unwind_Word
execute_stack_op(const unsigned char * op_ptr,const unsigned char * op_end,struct _Unwind_Context * context,_Unwind_Word initial)494af526226Smrg execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
495af526226Smrg struct _Unwind_Context *context, _Unwind_Word initial)
496af526226Smrg {
497af526226Smrg _Unwind_Word stack[64]; /* ??? Assume this is enough. */
498af526226Smrg int stack_elt;
499af526226Smrg
500af526226Smrg stack[0] = initial;
501af526226Smrg stack_elt = 1;
502af526226Smrg
503af526226Smrg while (op_ptr < op_end)
504af526226Smrg {
505af526226Smrg enum dwarf_location_atom op = *op_ptr++;
506af526226Smrg _Unwind_Word result;
507af526226Smrg _uleb128_t reg, utmp;
508af526226Smrg _sleb128_t offset, stmp;
509af526226Smrg
510af526226Smrg switch (op)
511af526226Smrg {
512af526226Smrg case DW_OP_lit0:
513af526226Smrg case DW_OP_lit1:
514af526226Smrg case DW_OP_lit2:
515af526226Smrg case DW_OP_lit3:
516af526226Smrg case DW_OP_lit4:
517af526226Smrg case DW_OP_lit5:
518af526226Smrg case DW_OP_lit6:
519af526226Smrg case DW_OP_lit7:
520af526226Smrg case DW_OP_lit8:
521af526226Smrg case DW_OP_lit9:
522af526226Smrg case DW_OP_lit10:
523af526226Smrg case DW_OP_lit11:
524af526226Smrg case DW_OP_lit12:
525af526226Smrg case DW_OP_lit13:
526af526226Smrg case DW_OP_lit14:
527af526226Smrg case DW_OP_lit15:
528af526226Smrg case DW_OP_lit16:
529af526226Smrg case DW_OP_lit17:
530af526226Smrg case DW_OP_lit18:
531af526226Smrg case DW_OP_lit19:
532af526226Smrg case DW_OP_lit20:
533af526226Smrg case DW_OP_lit21:
534af526226Smrg case DW_OP_lit22:
535af526226Smrg case DW_OP_lit23:
536af526226Smrg case DW_OP_lit24:
537af526226Smrg case DW_OP_lit25:
538af526226Smrg case DW_OP_lit26:
539af526226Smrg case DW_OP_lit27:
540af526226Smrg case DW_OP_lit28:
541af526226Smrg case DW_OP_lit29:
542af526226Smrg case DW_OP_lit30:
543af526226Smrg case DW_OP_lit31:
544af526226Smrg result = op - DW_OP_lit0;
545af526226Smrg break;
546af526226Smrg
547af526226Smrg case DW_OP_addr:
548af526226Smrg result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
549af526226Smrg op_ptr += sizeof (void *);
550af526226Smrg break;
551af526226Smrg
552af526226Smrg case DW_OP_GNU_encoded_addr:
553af526226Smrg {
554af526226Smrg _Unwind_Ptr presult;
555af526226Smrg op_ptr = read_encoded_value (context, *op_ptr, op_ptr+1, &presult);
556af526226Smrg result = presult;
557af526226Smrg }
558af526226Smrg break;
559af526226Smrg
560af526226Smrg case DW_OP_const1u:
561af526226Smrg result = read_1u (op_ptr);
562af526226Smrg op_ptr += 1;
563af526226Smrg break;
564af526226Smrg case DW_OP_const1s:
565af526226Smrg result = read_1s (op_ptr);
566af526226Smrg op_ptr += 1;
567af526226Smrg break;
568af526226Smrg case DW_OP_const2u:
569af526226Smrg result = read_2u (op_ptr);
570af526226Smrg op_ptr += 2;
571af526226Smrg break;
572af526226Smrg case DW_OP_const2s:
573af526226Smrg result = read_2s (op_ptr);
574af526226Smrg op_ptr += 2;
575af526226Smrg break;
576af526226Smrg case DW_OP_const4u:
577af526226Smrg result = read_4u (op_ptr);
578af526226Smrg op_ptr += 4;
579af526226Smrg break;
580af526226Smrg case DW_OP_const4s:
581af526226Smrg result = read_4s (op_ptr);
582af526226Smrg op_ptr += 4;
583af526226Smrg break;
584af526226Smrg case DW_OP_const8u:
585af526226Smrg result = read_8u (op_ptr);
586af526226Smrg op_ptr += 8;
587af526226Smrg break;
588af526226Smrg case DW_OP_const8s:
589af526226Smrg result = read_8s (op_ptr);
590af526226Smrg op_ptr += 8;
591af526226Smrg break;
592af526226Smrg case DW_OP_constu:
593af526226Smrg op_ptr = read_uleb128 (op_ptr, &utmp);
594af526226Smrg result = (_Unwind_Word)utmp;
595af526226Smrg break;
596af526226Smrg case DW_OP_consts:
597af526226Smrg op_ptr = read_sleb128 (op_ptr, &stmp);
598af526226Smrg result = (_Unwind_Sword)stmp;
599af526226Smrg break;
600af526226Smrg
601af526226Smrg case DW_OP_reg0:
602af526226Smrg case DW_OP_reg1:
603af526226Smrg case DW_OP_reg2:
604af526226Smrg case DW_OP_reg3:
605af526226Smrg case DW_OP_reg4:
606af526226Smrg case DW_OP_reg5:
607af526226Smrg case DW_OP_reg6:
608af526226Smrg case DW_OP_reg7:
609af526226Smrg case DW_OP_reg8:
610af526226Smrg case DW_OP_reg9:
611af526226Smrg case DW_OP_reg10:
612af526226Smrg case DW_OP_reg11:
613af526226Smrg case DW_OP_reg12:
614af526226Smrg case DW_OP_reg13:
615af526226Smrg case DW_OP_reg14:
616af526226Smrg case DW_OP_reg15:
617af526226Smrg case DW_OP_reg16:
618af526226Smrg case DW_OP_reg17:
619af526226Smrg case DW_OP_reg18:
620af526226Smrg case DW_OP_reg19:
621af526226Smrg case DW_OP_reg20:
622af526226Smrg case DW_OP_reg21:
623af526226Smrg case DW_OP_reg22:
624af526226Smrg case DW_OP_reg23:
625af526226Smrg case DW_OP_reg24:
626af526226Smrg case DW_OP_reg25:
627af526226Smrg case DW_OP_reg26:
628af526226Smrg case DW_OP_reg27:
629af526226Smrg case DW_OP_reg28:
630af526226Smrg case DW_OP_reg29:
631af526226Smrg case DW_OP_reg30:
632af526226Smrg case DW_OP_reg31:
633af526226Smrg result = _Unwind_GetGR (context, op - DW_OP_reg0);
634af526226Smrg break;
635af526226Smrg case DW_OP_regx:
636af526226Smrg op_ptr = read_uleb128 (op_ptr, ®);
637af526226Smrg result = _Unwind_GetGR (context, reg);
638af526226Smrg break;
639af526226Smrg
640af526226Smrg case DW_OP_breg0:
641af526226Smrg case DW_OP_breg1:
642af526226Smrg case DW_OP_breg2:
643af526226Smrg case DW_OP_breg3:
644af526226Smrg case DW_OP_breg4:
645af526226Smrg case DW_OP_breg5:
646af526226Smrg case DW_OP_breg6:
647af526226Smrg case DW_OP_breg7:
648af526226Smrg case DW_OP_breg8:
649af526226Smrg case DW_OP_breg9:
650af526226Smrg case DW_OP_breg10:
651af526226Smrg case DW_OP_breg11:
652af526226Smrg case DW_OP_breg12:
653af526226Smrg case DW_OP_breg13:
654af526226Smrg case DW_OP_breg14:
655af526226Smrg case DW_OP_breg15:
656af526226Smrg case DW_OP_breg16:
657af526226Smrg case DW_OP_breg17:
658af526226Smrg case DW_OP_breg18:
659af526226Smrg case DW_OP_breg19:
660af526226Smrg case DW_OP_breg20:
661af526226Smrg case DW_OP_breg21:
662af526226Smrg case DW_OP_breg22:
663af526226Smrg case DW_OP_breg23:
664af526226Smrg case DW_OP_breg24:
665af526226Smrg case DW_OP_breg25:
666af526226Smrg case DW_OP_breg26:
667af526226Smrg case DW_OP_breg27:
668af526226Smrg case DW_OP_breg28:
669af526226Smrg case DW_OP_breg29:
670af526226Smrg case DW_OP_breg30:
671af526226Smrg case DW_OP_breg31:
672af526226Smrg op_ptr = read_sleb128 (op_ptr, &offset);
673af526226Smrg result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
674af526226Smrg break;
675af526226Smrg case DW_OP_bregx:
676af526226Smrg op_ptr = read_uleb128 (op_ptr, ®);
677af526226Smrg op_ptr = read_sleb128 (op_ptr, &offset);
678af526226Smrg result = _Unwind_GetGR (context, reg) + (_Unwind_Word)offset;
679af526226Smrg break;
680af526226Smrg
681af526226Smrg case DW_OP_dup:
682af526226Smrg gcc_assert (stack_elt);
683af526226Smrg result = stack[stack_elt - 1];
684af526226Smrg break;
685af526226Smrg
686af526226Smrg case DW_OP_drop:
687af526226Smrg gcc_assert (stack_elt);
688af526226Smrg stack_elt -= 1;
689af526226Smrg goto no_push;
690af526226Smrg
691af526226Smrg case DW_OP_pick:
692af526226Smrg offset = *op_ptr++;
693af526226Smrg gcc_assert (offset < stack_elt - 1);
694af526226Smrg result = stack[stack_elt - 1 - offset];
695af526226Smrg break;
696af526226Smrg
697af526226Smrg case DW_OP_over:
698af526226Smrg gcc_assert (stack_elt >= 2);
699af526226Smrg result = stack[stack_elt - 2];
700af526226Smrg break;
701af526226Smrg
702af526226Smrg case DW_OP_swap:
703af526226Smrg {
704af526226Smrg _Unwind_Word t;
705af526226Smrg gcc_assert (stack_elt >= 2);
706af526226Smrg t = stack[stack_elt - 1];
707af526226Smrg stack[stack_elt - 1] = stack[stack_elt - 2];
708af526226Smrg stack[stack_elt - 2] = t;
709af526226Smrg goto no_push;
710af526226Smrg }
711af526226Smrg
712af526226Smrg case DW_OP_rot:
713af526226Smrg {
714af526226Smrg _Unwind_Word t1, t2, t3;
715af526226Smrg
716af526226Smrg gcc_assert (stack_elt >= 3);
717af526226Smrg t1 = stack[stack_elt - 1];
718af526226Smrg t2 = stack[stack_elt - 2];
719af526226Smrg t3 = stack[stack_elt - 3];
720af526226Smrg stack[stack_elt - 1] = t2;
721af526226Smrg stack[stack_elt - 2] = t3;
722af526226Smrg stack[stack_elt - 3] = t1;
723af526226Smrg goto no_push;
724af526226Smrg }
725af526226Smrg
726af526226Smrg case DW_OP_deref:
727af526226Smrg case DW_OP_deref_size:
728af526226Smrg case DW_OP_abs:
729af526226Smrg case DW_OP_neg:
730af526226Smrg case DW_OP_not:
731af526226Smrg case DW_OP_plus_uconst:
732af526226Smrg /* Unary operations. */
733af526226Smrg gcc_assert (stack_elt);
734af526226Smrg stack_elt -= 1;
735af526226Smrg
736af526226Smrg result = stack[stack_elt];
737af526226Smrg
738af526226Smrg switch (op)
739af526226Smrg {
740af526226Smrg case DW_OP_deref:
741af526226Smrg {
742af526226Smrg void *ptr = (void *) (_Unwind_Ptr) result;
743af526226Smrg result = (_Unwind_Ptr) read_pointer (ptr);
744af526226Smrg }
745af526226Smrg break;
746af526226Smrg
747af526226Smrg case DW_OP_deref_size:
748af526226Smrg {
749af526226Smrg void *ptr = (void *) (_Unwind_Ptr) result;
750af526226Smrg switch (*op_ptr++)
751af526226Smrg {
752af526226Smrg case 1:
753af526226Smrg result = read_1u (ptr);
754af526226Smrg break;
755af526226Smrg case 2:
756af526226Smrg result = read_2u (ptr);
757af526226Smrg break;
758af526226Smrg case 4:
759af526226Smrg result = read_4u (ptr);
760af526226Smrg break;
761af526226Smrg case 8:
762af526226Smrg result = read_8u (ptr);
763af526226Smrg break;
764af526226Smrg default:
765af526226Smrg gcc_unreachable ();
766af526226Smrg }
767af526226Smrg }
768af526226Smrg break;
769af526226Smrg
770af526226Smrg case DW_OP_abs:
771af526226Smrg if ((_Unwind_Sword) result < 0)
772af526226Smrg result = -result;
773af526226Smrg break;
774af526226Smrg case DW_OP_neg:
775af526226Smrg result = -result;
776af526226Smrg break;
777af526226Smrg case DW_OP_not:
778af526226Smrg result = ~result;
779af526226Smrg break;
780af526226Smrg case DW_OP_plus_uconst:
781af526226Smrg op_ptr = read_uleb128 (op_ptr, &utmp);
782af526226Smrg result += (_Unwind_Word)utmp;
783af526226Smrg break;
784af526226Smrg
785af526226Smrg default:
786af526226Smrg gcc_unreachable ();
787af526226Smrg }
788af526226Smrg break;
789af526226Smrg
790af526226Smrg case DW_OP_and:
791af526226Smrg case DW_OP_div:
792af526226Smrg case DW_OP_minus:
793af526226Smrg case DW_OP_mod:
794af526226Smrg case DW_OP_mul:
795af526226Smrg case DW_OP_or:
796af526226Smrg case DW_OP_plus:
797af526226Smrg case DW_OP_shl:
798af526226Smrg case DW_OP_shr:
799af526226Smrg case DW_OP_shra:
800af526226Smrg case DW_OP_xor:
801af526226Smrg case DW_OP_le:
802af526226Smrg case DW_OP_ge:
803af526226Smrg case DW_OP_eq:
804af526226Smrg case DW_OP_lt:
805af526226Smrg case DW_OP_gt:
806af526226Smrg case DW_OP_ne:
807af526226Smrg {
808af526226Smrg /* Binary operations. */
809af526226Smrg _Unwind_Word first, second;
810af526226Smrg gcc_assert (stack_elt >= 2);
811af526226Smrg stack_elt -= 2;
812af526226Smrg
813af526226Smrg second = stack[stack_elt];
814af526226Smrg first = stack[stack_elt + 1];
815af526226Smrg
816af526226Smrg switch (op)
817af526226Smrg {
818af526226Smrg case DW_OP_and:
819af526226Smrg result = second & first;
820af526226Smrg break;
821af526226Smrg case DW_OP_div:
822af526226Smrg result = (_Unwind_Sword) second / (_Unwind_Sword) first;
823af526226Smrg break;
824af526226Smrg case DW_OP_minus:
825af526226Smrg result = second - first;
826af526226Smrg break;
827af526226Smrg case DW_OP_mod:
828af526226Smrg result = second % first;
829af526226Smrg break;
830af526226Smrg case DW_OP_mul:
831af526226Smrg result = second * first;
832af526226Smrg break;
833af526226Smrg case DW_OP_or:
834af526226Smrg result = second | first;
835af526226Smrg break;
836af526226Smrg case DW_OP_plus:
837af526226Smrg result = second + first;
838af526226Smrg break;
839af526226Smrg case DW_OP_shl:
840af526226Smrg result = second << first;
841af526226Smrg break;
842af526226Smrg case DW_OP_shr:
843af526226Smrg result = second >> first;
844af526226Smrg break;
845af526226Smrg case DW_OP_shra:
846af526226Smrg result = (_Unwind_Sword) second >> first;
847af526226Smrg break;
848af526226Smrg case DW_OP_xor:
849af526226Smrg result = second ^ first;
850af526226Smrg break;
851af526226Smrg case DW_OP_le:
852af526226Smrg result = (_Unwind_Sword) second <= (_Unwind_Sword) first;
853af526226Smrg break;
854af526226Smrg case DW_OP_ge:
855af526226Smrg result = (_Unwind_Sword) second >= (_Unwind_Sword) first;
856af526226Smrg break;
857af526226Smrg case DW_OP_eq:
858af526226Smrg result = (_Unwind_Sword) second == (_Unwind_Sword) first;
859af526226Smrg break;
860af526226Smrg case DW_OP_lt:
861af526226Smrg result = (_Unwind_Sword) second < (_Unwind_Sword) first;
862af526226Smrg break;
863af526226Smrg case DW_OP_gt:
864af526226Smrg result = (_Unwind_Sword) second > (_Unwind_Sword) first;
865af526226Smrg break;
866af526226Smrg case DW_OP_ne:
867af526226Smrg result = (_Unwind_Sword) second != (_Unwind_Sword) first;
868af526226Smrg break;
869af526226Smrg
870af526226Smrg default:
871af526226Smrg gcc_unreachable ();
872af526226Smrg }
873af526226Smrg }
874af526226Smrg break;
875af526226Smrg
876af526226Smrg case DW_OP_skip:
877af526226Smrg offset = read_2s (op_ptr);
878af526226Smrg op_ptr += 2;
879af526226Smrg op_ptr += offset;
880af526226Smrg goto no_push;
881af526226Smrg
882af526226Smrg case DW_OP_bra:
883af526226Smrg gcc_assert (stack_elt);
884af526226Smrg stack_elt -= 1;
885af526226Smrg
886af526226Smrg offset = read_2s (op_ptr);
887af526226Smrg op_ptr += 2;
888af526226Smrg if (stack[stack_elt] != 0)
889af526226Smrg op_ptr += offset;
890af526226Smrg goto no_push;
891af526226Smrg
892af526226Smrg case DW_OP_nop:
893af526226Smrg goto no_push;
894af526226Smrg
895af526226Smrg default:
896af526226Smrg gcc_unreachable ();
897af526226Smrg }
898af526226Smrg
899af526226Smrg /* Most things push a result value. */
900af526226Smrg gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack));
901af526226Smrg stack[stack_elt++] = result;
902af526226Smrg no_push:;
903af526226Smrg }
904af526226Smrg
905af526226Smrg /* We were executing this program to get a value. It should be
906af526226Smrg at top of stack. */
907af526226Smrg gcc_assert (stack_elt);
908af526226Smrg stack_elt -= 1;
909af526226Smrg return stack[stack_elt];
910af526226Smrg }
911af526226Smrg
912af526226Smrg
913af526226Smrg /* Decode DWARF 2 call frame information. Takes pointers the
914af526226Smrg instruction sequence to decode, current register information and
915af526226Smrg CIE info, and the PC range to evaluate. */
916af526226Smrg
917af526226Smrg static void
execute_cfa_program(const unsigned char * insn_ptr,const unsigned char * insn_end,struct _Unwind_Context * context,_Unwind_FrameState * fs)918af526226Smrg execute_cfa_program (const unsigned char *insn_ptr,
919af526226Smrg const unsigned char *insn_end,
920af526226Smrg struct _Unwind_Context *context,
921af526226Smrg _Unwind_FrameState *fs)
922af526226Smrg {
923af526226Smrg struct frame_state_reg_info *unused_rs = NULL;
924af526226Smrg
925af526226Smrg /* Don't allow remember/restore between CIE and FDE programs. */
926af526226Smrg fs->regs.prev = NULL;
927af526226Smrg
928af526226Smrg /* The comparison with the return address uses < rather than <= because
929af526226Smrg we are only interested in the effects of code before the call; for a
930af526226Smrg noreturn function, the return address may point to unrelated code with
931af526226Smrg a different stack configuration that we are not interested in. We
932af526226Smrg assume that the call itself is unwind info-neutral; if not, or if
933af526226Smrg there are delay instructions that adjust the stack, these must be
934af526226Smrg reflected at the point immediately before the call insn.
935af526226Smrg In signal frames, return address is after last completed instruction,
936af526226Smrg so we add 1 to return address to make the comparison <=. */
937af526226Smrg while (insn_ptr < insn_end
938af526226Smrg && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
939af526226Smrg {
940af526226Smrg unsigned char insn = *insn_ptr++;
941af526226Smrg _uleb128_t reg, utmp;
942af526226Smrg _sleb128_t offset, stmp;
943af526226Smrg
944af526226Smrg if ((insn & 0xc0) == DW_CFA_advance_loc)
945af526226Smrg fs->pc += (insn & 0x3f) * fs->code_align;
946af526226Smrg else if ((insn & 0xc0) == DW_CFA_offset)
947af526226Smrg {
948af526226Smrg reg = insn & 0x3f;
949af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
950af526226Smrg offset = (_Unwind_Sword) utmp * fs->data_align;
951af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
952af526226Smrg = REG_SAVED_OFFSET;
953af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
954af526226Smrg }
955af526226Smrg else if ((insn & 0xc0) == DW_CFA_restore)
956af526226Smrg {
957af526226Smrg reg = insn & 0x3f;
958af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED;
959af526226Smrg }
960af526226Smrg else switch (insn)
961af526226Smrg {
962af526226Smrg case DW_CFA_set_loc:
963af526226Smrg {
964af526226Smrg _Unwind_Ptr pc;
965af526226Smrg
966af526226Smrg insn_ptr = read_encoded_value (context, fs->fde_encoding,
967af526226Smrg insn_ptr, &pc);
968af526226Smrg fs->pc = (void *) pc;
969af526226Smrg }
970af526226Smrg break;
971af526226Smrg
972af526226Smrg case DW_CFA_advance_loc1:
973af526226Smrg fs->pc += read_1u (insn_ptr) * fs->code_align;
974af526226Smrg insn_ptr += 1;
975af526226Smrg break;
976af526226Smrg case DW_CFA_advance_loc2:
977af526226Smrg fs->pc += read_2u (insn_ptr) * fs->code_align;
978af526226Smrg insn_ptr += 2;
979af526226Smrg break;
980af526226Smrg case DW_CFA_advance_loc4:
981af526226Smrg fs->pc += read_4u (insn_ptr) * fs->code_align;
982af526226Smrg insn_ptr += 4;
983af526226Smrg break;
984af526226Smrg
985af526226Smrg case DW_CFA_offset_extended:
986af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®);
987af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
988af526226Smrg offset = (_Unwind_Sword) utmp * fs->data_align;
989af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
990af526226Smrg = REG_SAVED_OFFSET;
991af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
992af526226Smrg break;
993af526226Smrg
994af526226Smrg case DW_CFA_restore_extended:
995af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®);
996af526226Smrg /* FIXME, this is wrong; the CIE might have said that the
997af526226Smrg register was saved somewhere. */
998af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
999af526226Smrg break;
1000af526226Smrg
1001af526226Smrg case DW_CFA_same_value:
1002af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®);
1003af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED;
1004af526226Smrg break;
1005af526226Smrg
1006af526226Smrg case DW_CFA_undefined:
1007af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®);
1008af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNDEFINED;
1009af526226Smrg break;
1010af526226Smrg
1011af526226Smrg case DW_CFA_nop:
1012af526226Smrg break;
1013af526226Smrg
1014af526226Smrg case DW_CFA_register:
1015af526226Smrg {
1016af526226Smrg _uleb128_t reg2;
1017af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®);
1018af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®2);
1019af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG;
1020af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.reg =
1021af526226Smrg (_Unwind_Word)reg2;
1022af526226Smrg }
1023af526226Smrg break;
1024af526226Smrg
1025af526226Smrg case DW_CFA_remember_state:
1026af526226Smrg {
1027af526226Smrg struct frame_state_reg_info *new_rs;
1028af526226Smrg if (unused_rs)
1029af526226Smrg {
1030af526226Smrg new_rs = unused_rs;
1031af526226Smrg unused_rs = unused_rs->prev;
1032af526226Smrg }
1033af526226Smrg else
1034af526226Smrg new_rs = alloca (sizeof (struct frame_state_reg_info));
1035af526226Smrg
1036af526226Smrg *new_rs = fs->regs;
1037af526226Smrg fs->regs.prev = new_rs;
1038af526226Smrg }
1039af526226Smrg break;
1040af526226Smrg
1041af526226Smrg case DW_CFA_restore_state:
1042af526226Smrg {
1043af526226Smrg struct frame_state_reg_info *old_rs = fs->regs.prev;
1044af526226Smrg fs->regs = *old_rs;
1045af526226Smrg old_rs->prev = unused_rs;
1046af526226Smrg unused_rs = old_rs;
1047af526226Smrg }
1048af526226Smrg break;
1049af526226Smrg
1050af526226Smrg case DW_CFA_def_cfa:
1051af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
1052af526226Smrg fs->regs.cfa_reg = (_Unwind_Word)utmp;
1053af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
1054af526226Smrg fs->regs.cfa_offset = (_Unwind_Word)utmp;
1055af526226Smrg fs->regs.cfa_how = CFA_REG_OFFSET;
1056af526226Smrg break;
1057af526226Smrg
1058af526226Smrg case DW_CFA_def_cfa_register:
1059af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
1060af526226Smrg fs->regs.cfa_reg = (_Unwind_Word)utmp;
1061af526226Smrg fs->regs.cfa_how = CFA_REG_OFFSET;
1062af526226Smrg break;
1063af526226Smrg
1064af526226Smrg case DW_CFA_def_cfa_offset:
1065af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
1066af526226Smrg fs->regs.cfa_offset = utmp;
1067af526226Smrg /* cfa_how deliberately not set. */
1068af526226Smrg break;
1069af526226Smrg
1070af526226Smrg case DW_CFA_def_cfa_expression:
1071af526226Smrg fs->regs.cfa_exp = insn_ptr;
1072af526226Smrg fs->regs.cfa_how = CFA_EXP;
1073af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
1074af526226Smrg insn_ptr += utmp;
1075af526226Smrg break;
1076af526226Smrg
1077af526226Smrg case DW_CFA_expression:
1078af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®);
1079af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP;
1080af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
1081af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
1082af526226Smrg insn_ptr += utmp;
1083af526226Smrg break;
1084af526226Smrg
1085af526226Smrg /* Dwarf3. */
1086af526226Smrg case DW_CFA_offset_extended_sf:
1087af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®);
1088af526226Smrg insn_ptr = read_sleb128 (insn_ptr, &stmp);
1089af526226Smrg offset = stmp * fs->data_align;
1090af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1091af526226Smrg = REG_SAVED_OFFSET;
1092af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
1093af526226Smrg break;
1094af526226Smrg
1095af526226Smrg case DW_CFA_def_cfa_sf:
1096af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
1097af526226Smrg fs->regs.cfa_reg = (_Unwind_Word)utmp;
1098af526226Smrg insn_ptr = read_sleb128 (insn_ptr, &stmp);
1099af526226Smrg fs->regs.cfa_offset = (_Unwind_Sword)stmp;
1100af526226Smrg fs->regs.cfa_how = CFA_REG_OFFSET;
1101af526226Smrg fs->regs.cfa_offset *= fs->data_align;
1102af526226Smrg break;
1103af526226Smrg
1104af526226Smrg case DW_CFA_def_cfa_offset_sf:
1105af526226Smrg insn_ptr = read_sleb128 (insn_ptr, &stmp);
1106af526226Smrg fs->regs.cfa_offset = (_Unwind_Sword)stmp;
1107af526226Smrg fs->regs.cfa_offset *= fs->data_align;
1108af526226Smrg /* cfa_how deliberately not set. */
1109af526226Smrg break;
1110af526226Smrg
1111af526226Smrg case DW_CFA_val_offset:
1112af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®);
1113af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
1114af526226Smrg offset = (_Unwind_Sword) utmp * fs->data_align;
1115af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1116af526226Smrg = REG_SAVED_VAL_OFFSET;
1117af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
1118af526226Smrg break;
1119af526226Smrg
1120af526226Smrg case DW_CFA_val_offset_sf:
1121af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®);
1122af526226Smrg insn_ptr = read_sleb128 (insn_ptr, &stmp);
1123af526226Smrg offset = stmp * fs->data_align;
1124af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1125af526226Smrg = REG_SAVED_VAL_OFFSET;
1126af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
1127af526226Smrg break;
1128af526226Smrg
1129af526226Smrg case DW_CFA_val_expression:
1130af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®);
1131af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1132af526226Smrg = REG_SAVED_VAL_EXP;
1133af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
1134af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
1135af526226Smrg insn_ptr += utmp;
1136af526226Smrg break;
1137af526226Smrg
1138af526226Smrg case DW_CFA_GNU_window_save:
1139af526226Smrg /* ??? Hardcoded for SPARC register window configuration. */
1140af526226Smrg for (reg = 16; reg < 32; ++reg)
1141af526226Smrg {
1142af526226Smrg fs->regs.reg[reg].how = REG_SAVED_OFFSET;
1143af526226Smrg fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
1144af526226Smrg }
1145af526226Smrg break;
1146af526226Smrg
1147af526226Smrg case DW_CFA_GNU_args_size:
1148af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
1149af526226Smrg context->args_size = (_Unwind_Word)utmp;
1150af526226Smrg break;
1151af526226Smrg
1152af526226Smrg case DW_CFA_GNU_negative_offset_extended:
1153af526226Smrg /* Obsoleted by DW_CFA_offset_extended_sf, but used by
1154af526226Smrg older PowerPC code. */
1155af526226Smrg insn_ptr = read_uleb128 (insn_ptr, ®);
1156af526226Smrg insn_ptr = read_uleb128 (insn_ptr, &utmp);
1157af526226Smrg offset = (_Unwind_Word) utmp * fs->data_align;
1158af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
1159af526226Smrg = REG_SAVED_OFFSET;
1160af526226Smrg fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset;
1161af526226Smrg break;
1162af526226Smrg
1163af526226Smrg default:
1164af526226Smrg gcc_unreachable ();
1165af526226Smrg }
1166af526226Smrg }
1167af526226Smrg }
1168af526226Smrg
1169af526226Smrg /* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
1170af526226Smrg its caller and decode it into FS. This function also sets the
1171af526226Smrg args_size and lsda members of CONTEXT, as they are really information
1172af526226Smrg about the caller's frame. */
1173af526226Smrg
1174af526226Smrg static _Unwind_Reason_Code
uw_frame_state_for(struct _Unwind_Context * context,_Unwind_FrameState * fs)1175af526226Smrg uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1176af526226Smrg {
1177af526226Smrg const struct dwarf_fde *fde;
1178af526226Smrg const struct dwarf_cie *cie;
1179af526226Smrg const unsigned char *aug, *insn, *end;
1180af526226Smrg
1181af526226Smrg memset (fs, 0, sizeof (*fs));
1182af526226Smrg context->args_size = 0;
1183af526226Smrg context->lsda = 0;
1184af526226Smrg
1185af526226Smrg if (context->ra == 0)
1186af526226Smrg return _URC_END_OF_STACK;
1187af526226Smrg
1188af526226Smrg fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
1189af526226Smrg &context->bases);
1190af526226Smrg if (fde == NULL)
1191af526226Smrg {
1192af526226Smrg #ifdef MD_FALLBACK_FRAME_STATE_FOR
1193af526226Smrg /* Couldn't find frame unwind info for this function. Try a
1194af526226Smrg target-specific fallback mechanism. This will necessarily
1195af526226Smrg not provide a personality routine or LSDA. */
1196af526226Smrg return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
1197af526226Smrg #else
1198af526226Smrg return _URC_END_OF_STACK;
1199af526226Smrg #endif
1200af526226Smrg }
1201af526226Smrg
1202af526226Smrg fs->pc = context->bases.func;
1203af526226Smrg
1204af526226Smrg cie = get_cie (fde);
1205af526226Smrg insn = extract_cie_info (cie, context, fs);
1206af526226Smrg if (insn == NULL)
1207af526226Smrg /* CIE contained unknown augmentation. */
1208af526226Smrg return _URC_FATAL_PHASE1_ERROR;
1209af526226Smrg
1210af526226Smrg /* First decode all the insns in the CIE. */
1211af526226Smrg end = (const unsigned char *) next_fde ((const struct dwarf_fde *) cie);
1212af526226Smrg execute_cfa_program (insn, end, context, fs);
1213af526226Smrg
1214af526226Smrg /* Locate augmentation for the fde. */
1215af526226Smrg aug = (const unsigned char *) fde + sizeof (*fde);
1216af526226Smrg aug += 2 * size_of_encoded_value (fs->fde_encoding);
1217af526226Smrg insn = NULL;
1218af526226Smrg if (fs->saw_z)
1219af526226Smrg {
1220af526226Smrg _uleb128_t i;
1221af526226Smrg aug = read_uleb128 (aug, &i);
1222af526226Smrg insn = aug + i;
1223af526226Smrg }
1224af526226Smrg if (fs->lsda_encoding != DW_EH_PE_omit)
1225af526226Smrg {
1226af526226Smrg _Unwind_Ptr lsda;
1227af526226Smrg
1228af526226Smrg aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
1229af526226Smrg context->lsda = (void *) lsda;
1230af526226Smrg }
1231af526226Smrg
1232af526226Smrg /* Then the insns in the FDE up to our target PC. */
1233af526226Smrg if (insn == NULL)
1234af526226Smrg insn = aug;
1235af526226Smrg end = (const unsigned char *) next_fde (fde);
1236af526226Smrg execute_cfa_program (insn, end, context, fs);
1237af526226Smrg
1238af526226Smrg return _URC_NO_REASON;
1239af526226Smrg }
1240af526226Smrg
1241af526226Smrg typedef struct frame_state
1242af526226Smrg {
1243af526226Smrg void *cfa;
1244af526226Smrg void *eh_ptr;
1245af526226Smrg long cfa_offset;
1246af526226Smrg long args_size;
1247af526226Smrg long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
1248af526226Smrg unsigned short cfa_reg;
1249af526226Smrg unsigned short retaddr_column;
1250af526226Smrg char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
1251af526226Smrg } frame_state;
1252af526226Smrg
1253af526226Smrg struct frame_state * __frame_state_for (void *, struct frame_state *);
1254af526226Smrg
1255af526226Smrg /* Called from pre-G++ 3.0 __throw to find the registers to restore for
1256af526226Smrg a given PC_TARGET. The caller should allocate a local variable of
1257af526226Smrg `struct frame_state' and pass its address to STATE_IN. */
1258af526226Smrg
1259af526226Smrg struct frame_state *
__frame_state_for(void * pc_target,struct frame_state * state_in)1260af526226Smrg __frame_state_for (void *pc_target, struct frame_state *state_in)
1261af526226Smrg {
1262af526226Smrg struct _Unwind_Context context;
1263af526226Smrg _Unwind_FrameState fs;
1264af526226Smrg int reg;
1265af526226Smrg
1266af526226Smrg memset (&context, 0, sizeof (struct _Unwind_Context));
1267af526226Smrg if (!ASSUME_EXTENDED_UNWIND_CONTEXT)
1268af526226Smrg context.flags = EXTENDED_CONTEXT_BIT;
1269af526226Smrg context.ra = pc_target + 1;
1270af526226Smrg
1271af526226Smrg if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
1272af526226Smrg return 0;
1273af526226Smrg
1274af526226Smrg /* We have no way to pass a location expression for the CFA to our
1275af526226Smrg caller. It wouldn't understand it anyway. */
1276af526226Smrg if (fs.regs.cfa_how == CFA_EXP)
1277af526226Smrg return 0;
1278af526226Smrg
1279af526226Smrg for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++)
1280af526226Smrg {
1281af526226Smrg state_in->saved[reg] = fs.regs.reg[reg].how;
1282af526226Smrg switch (state_in->saved[reg])
1283af526226Smrg {
1284af526226Smrg case REG_SAVED_REG:
1285af526226Smrg state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
1286af526226Smrg break;
1287af526226Smrg case REG_SAVED_OFFSET:
1288af526226Smrg state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
1289af526226Smrg break;
1290af526226Smrg default:
1291af526226Smrg state_in->reg_or_offset[reg] = 0;
1292af526226Smrg break;
1293af526226Smrg }
1294af526226Smrg }
1295af526226Smrg
1296af526226Smrg state_in->cfa_offset = fs.regs.cfa_offset;
1297af526226Smrg state_in->cfa_reg = fs.regs.cfa_reg;
1298af526226Smrg state_in->retaddr_column = fs.retaddr_column;
1299af526226Smrg state_in->args_size = context.args_size;
1300af526226Smrg state_in->eh_ptr = fs.eh_ptr;
1301af526226Smrg
1302af526226Smrg return state_in;
1303af526226Smrg }
1304af526226Smrg
1305af526226Smrg typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
1306af526226Smrg
1307af526226Smrg static inline void
_Unwind_SetSpColumn(struct _Unwind_Context * context,void * cfa,_Unwind_SpTmp * tmp_sp)1308af526226Smrg _Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
1309af526226Smrg _Unwind_SpTmp *tmp_sp)
1310af526226Smrg {
1311af526226Smrg int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
1312af526226Smrg
1313af526226Smrg if (size == sizeof(_Unwind_Ptr))
1314af526226Smrg tmp_sp->ptr = (_Unwind_Ptr) cfa;
1315af526226Smrg else
1316af526226Smrg {
1317af526226Smrg gcc_assert (size == sizeof(_Unwind_Word));
1318af526226Smrg tmp_sp->word = (_Unwind_Ptr) cfa;
1319af526226Smrg }
1320af526226Smrg _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp);
1321af526226Smrg }
1322af526226Smrg
1323af526226Smrg static void
uw_update_context_1(struct _Unwind_Context * context,_Unwind_FrameState * fs)1324af526226Smrg uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1325af526226Smrg {
1326af526226Smrg struct _Unwind_Context orig_context = *context;
1327af526226Smrg void *cfa;
1328af526226Smrg long i;
1329af526226Smrg
13304646d632Smrg #ifdef __LIBGCC_EH_RETURN_STACKADJ_RTX__
1331af526226Smrg /* Special handling here: Many machines do not use a frame pointer,
1332af526226Smrg and track the CFA only through offsets from the stack pointer from
1333af526226Smrg one frame to the next. In this case, the stack pointer is never
1334af526226Smrg stored, so it has no saved address in the context. What we do
1335af526226Smrg have is the CFA from the previous stack frame.
1336af526226Smrg
1337af526226Smrg In very special situations (such as unwind info for signal return),
1338af526226Smrg there may be location expressions that use the stack pointer as well.
1339af526226Smrg
1340af526226Smrg Do this conditionally for one frame. This allows the unwind info
1341af526226Smrg for one frame to save a copy of the stack pointer from the previous
1342af526226Smrg frame, and be able to use much easier CFA mechanisms to do it.
1343af526226Smrg Always zap the saved stack pointer value for the next frame; carrying
1344af526226Smrg the value over from one frame to another doesn't make sense. */
1345af526226Smrg
1346af526226Smrg _Unwind_SpTmp tmp_sp;
1347af526226Smrg
1348af526226Smrg if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
1349af526226Smrg _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp);
1350af526226Smrg _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL);
1351af526226Smrg #endif
1352af526226Smrg
1353af526226Smrg /* Compute this frame's CFA. */
1354af526226Smrg switch (fs->regs.cfa_how)
1355af526226Smrg {
1356af526226Smrg case CFA_REG_OFFSET:
1357af526226Smrg cfa = _Unwind_GetPtr (&orig_context, fs->regs.cfa_reg);
1358af526226Smrg cfa += fs->regs.cfa_offset;
1359af526226Smrg break;
1360af526226Smrg
1361af526226Smrg case CFA_EXP:
1362af526226Smrg {
1363af526226Smrg const unsigned char *exp = fs->regs.cfa_exp;
1364af526226Smrg _uleb128_t len;
1365af526226Smrg
1366af526226Smrg exp = read_uleb128 (exp, &len);
1367af526226Smrg cfa = (void *) (_Unwind_Ptr)
1368af526226Smrg execute_stack_op (exp, exp + len, &orig_context, 0);
1369af526226Smrg break;
1370af526226Smrg }
1371af526226Smrg
1372af526226Smrg default:
1373af526226Smrg gcc_unreachable ();
1374af526226Smrg }
1375af526226Smrg context->cfa = cfa;
1376af526226Smrg
1377af526226Smrg /* Compute the addresses of all registers saved in this frame. */
13784646d632Smrg for (i = 0; i < __LIBGCC_DWARF_FRAME_REGISTERS__ + 1; ++i)
1379af526226Smrg switch (fs->regs.reg[i].how)
1380af526226Smrg {
1381af526226Smrg case REG_UNSAVED:
1382af526226Smrg case REG_UNDEFINED:
1383af526226Smrg break;
1384af526226Smrg
1385af526226Smrg case REG_SAVED_OFFSET:
1386af526226Smrg _Unwind_SetGRPtr (context, i,
1387af526226Smrg (void *) (cfa + fs->regs.reg[i].loc.offset));
1388af526226Smrg break;
1389af526226Smrg
1390af526226Smrg case REG_SAVED_REG:
1391af526226Smrg if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
1392af526226Smrg _Unwind_SetGRValue (context, i,
1393af526226Smrg _Unwind_GetGR (&orig_context,
1394af526226Smrg fs->regs.reg[i].loc.reg));
1395af526226Smrg else
1396af526226Smrg _Unwind_SetGRPtr (context, i,
1397af526226Smrg _Unwind_GetGRPtr (&orig_context,
1398af526226Smrg fs->regs.reg[i].loc.reg));
1399af526226Smrg break;
1400af526226Smrg
1401af526226Smrg case REG_SAVED_EXP:
1402af526226Smrg {
1403af526226Smrg const unsigned char *exp = fs->regs.reg[i].loc.exp;
1404af526226Smrg _uleb128_t len;
1405af526226Smrg _Unwind_Ptr val;
1406af526226Smrg
1407af526226Smrg exp = read_uleb128 (exp, &len);
1408af526226Smrg val = execute_stack_op (exp, exp + len, &orig_context,
1409af526226Smrg (_Unwind_Ptr) cfa);
1410af526226Smrg _Unwind_SetGRPtr (context, i, (void *) val);
1411af526226Smrg }
1412af526226Smrg break;
1413af526226Smrg
1414af526226Smrg case REG_SAVED_VAL_OFFSET:
1415af526226Smrg _Unwind_SetGRValue (context, i,
1416af526226Smrg (_Unwind_Internal_Ptr)
1417af526226Smrg (cfa + fs->regs.reg[i].loc.offset));
1418af526226Smrg break;
1419af526226Smrg
1420af526226Smrg case REG_SAVED_VAL_EXP:
1421af526226Smrg {
1422af526226Smrg const unsigned char *exp = fs->regs.reg[i].loc.exp;
1423af526226Smrg _uleb128_t len;
1424af526226Smrg _Unwind_Ptr val;
1425af526226Smrg
1426af526226Smrg exp = read_uleb128 (exp, &len);
1427af526226Smrg val = execute_stack_op (exp, exp + len, &orig_context,
1428af526226Smrg (_Unwind_Ptr) cfa);
1429af526226Smrg _Unwind_SetGRValue (context, i, val);
1430af526226Smrg }
1431af526226Smrg break;
1432af526226Smrg }
1433af526226Smrg
1434af526226Smrg _Unwind_SetSignalFrame (context, fs->signal_frame);
1435af526226Smrg
1436af526226Smrg #ifdef MD_FROB_UPDATE_CONTEXT
1437af526226Smrg MD_FROB_UPDATE_CONTEXT (context, fs);
1438af526226Smrg #endif
1439af526226Smrg }
1440af526226Smrg
1441af526226Smrg /* CONTEXT describes the unwind state for a frame, and FS describes the FDE
1442af526226Smrg of its caller. Update CONTEXT to refer to the caller as well. Note
1443af526226Smrg that the args_size and lsda members are not updated here, but later in
1444af526226Smrg uw_frame_state_for. */
1445af526226Smrg
1446af526226Smrg static void
uw_update_context(struct _Unwind_Context * context,_Unwind_FrameState * fs)1447af526226Smrg uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1448af526226Smrg {
1449af526226Smrg uw_update_context_1 (context, fs);
1450af526226Smrg
1451af526226Smrg /* In general this unwinder doesn't make any distinction between
1452af526226Smrg undefined and same_value rule. Call-saved registers are assumed
1453af526226Smrg to have same_value rule by default and explicit undefined
1454af526226Smrg rule is handled like same_value. The only exception is
1455af526226Smrg DW_CFA_undefined on retaddr_column which is supposed to
1456af526226Smrg mark outermost frame in DWARF 3. */
1457af526226Smrg if (fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (fs->retaddr_column)].how
1458af526226Smrg == REG_UNDEFINED)
1459af526226Smrg /* uw_frame_state_for uses context->ra == 0 check to find outermost
1460af526226Smrg stack frame. */
1461af526226Smrg context->ra = 0;
1462af526226Smrg else
1463af526226Smrg /* Compute the return address now, since the return address column
1464af526226Smrg can change from frame to frame. */
1465af526226Smrg context->ra = __builtin_extract_return_addr
1466af526226Smrg (_Unwind_GetPtr (context, fs->retaddr_column));
1467af526226Smrg #if defined( __CR16C__ )
1468af526226Smrg context->ra = (void*)( ( (unsigned)context->ra ) << 1 ) ;
1469af526226Smrg #endif
1470af526226Smrg }
1471af526226Smrg
1472af526226Smrg static void
uw_advance_context(struct _Unwind_Context * context,_Unwind_FrameState * fs)1473af526226Smrg uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
1474af526226Smrg {
1475af526226Smrg uw_update_context (context, fs);
1476af526226Smrg }
1477af526226Smrg
1478af526226Smrg /* Fill in CONTEXT for top-of-stack. The only valid registers at this
1479af526226Smrg level will be the return address and the CFA. */
1480af526226Smrg
1481af526226Smrg #define uw_init_context(CONTEXT) \
1482af526226Smrg do \
1483af526226Smrg { \
1484af526226Smrg /* Do any necessary initialization to access arbitrary stack frames. \
1485af526226Smrg On the SPARC, this means flushing the register windows. */ \
1486af526226Smrg __builtin_unwind_init (); \
1487af526226Smrg uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \
1488af526226Smrg __builtin_return_address (0)); \
1489af526226Smrg } \
1490af526226Smrg while (0)
1491af526226Smrg
1492af526226Smrg static inline void
init_dwarf_reg_size_table(void)1493af526226Smrg init_dwarf_reg_size_table (void)
1494af526226Smrg {
1495af526226Smrg __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
1496af526226Smrg }
1497af526226Smrg
1498af526226Smrg static void __attribute__((noinline))
uw_init_context_1(struct _Unwind_Context * context,void * outer_cfa,void * outer_ra)1499af526226Smrg uw_init_context_1 (struct _Unwind_Context *context,
1500af526226Smrg void *outer_cfa, void *outer_ra)
1501af526226Smrg {
1502af526226Smrg void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
1503af526226Smrg _Unwind_FrameState fs;
1504af526226Smrg _Unwind_SpTmp sp_slot;
1505af526226Smrg _Unwind_Reason_Code code;
1506af526226Smrg
1507af526226Smrg memset (context, 0, sizeof (struct _Unwind_Context));
1508af526226Smrg context->ra = ra;
1509af526226Smrg if (!ASSUME_EXTENDED_UNWIND_CONTEXT)
1510af526226Smrg context->flags = EXTENDED_CONTEXT_BIT;
1511af526226Smrg
1512af526226Smrg code = uw_frame_state_for (context, &fs);
1513af526226Smrg gcc_assert (code == _URC_NO_REASON);
1514af526226Smrg
1515af526226Smrg #if __GTHREADS
1516af526226Smrg {
1517af526226Smrg static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
1518af526226Smrg if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
1519af526226Smrg && dwarf_reg_size_table[0] == 0)
1520af526226Smrg init_dwarf_reg_size_table ();
1521af526226Smrg }
1522af526226Smrg #else
1523af526226Smrg if (dwarf_reg_size_table[0] == 0)
1524af526226Smrg init_dwarf_reg_size_table ();
1525af526226Smrg #endif
1526af526226Smrg
1527af526226Smrg /* Force the frame state to use the known cfa value. */
1528af526226Smrg _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
1529af526226Smrg fs.regs.cfa_how = CFA_REG_OFFSET;
1530af526226Smrg fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
1531af526226Smrg #if !defined( __CR16C__ )
1532af526226Smrg fs.regs.cfa_offset = 0;
1533af526226Smrg #else
1534af526226Smrg fs.regs.cfa_offset -= context->args_size ;
1535af526226Smrg #endif
1536af526226Smrg
1537af526226Smrg uw_update_context_1 (context, &fs);
1538af526226Smrg
1539af526226Smrg /* If the return address column was saved in a register in the
1540af526226Smrg initialization context, then we can't see it in the given
1541af526226Smrg call frame data. So have the initialization context tell us. */
1542af526226Smrg context->ra = __builtin_extract_return_addr (outer_ra);
1543af526226Smrg }
1544af526226Smrg
1545af526226Smrg static void _Unwind_DebugHook (void *, void *)
1546af526226Smrg __attribute__ ((__noinline__, __used__, __noclone__));
1547af526226Smrg
1548af526226Smrg /* This function is called during unwinding. It is intended as a hook
1549af526226Smrg for a debugger to intercept exceptions. CFA is the CFA of the
1550af526226Smrg target frame. HANDLER is the PC to which control will be
1551af526226Smrg transferred. */
1552af526226Smrg static void
_Unwind_DebugHook(void * cfa,void * handler)1553af526226Smrg _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
1554af526226Smrg void *handler __attribute__ ((__unused__)))
1555af526226Smrg {
1556af526226Smrg /* We only want to use stap probes starting with v3. Earlier
1557af526226Smrg versions added too much startup cost. */
1558af526226Smrg #if defined (HAVE_SYS_SDT_H) && defined (STAP_PROBE2) && _SDT_NOTE_TYPE >= 3
1559af526226Smrg STAP_PROBE2 (libgcc, unwind, cfa, handler);
1560af526226Smrg #else
1561af526226Smrg asm ("");
1562af526226Smrg #endif
1563af526226Smrg }
1564af526226Smrg
1565af526226Smrg /* Install TARGET into CURRENT so that we can return to it. This is a
1566af526226Smrg macro because __builtin_eh_return must be invoked in the context of
1567af526226Smrg our caller. */
1568af526226Smrg #if defined( __CR16C__ )
1569af526226Smrg
1570e56e5d0aSmrg #define uw_install_context(CURRENT, TARGET, FRAMES) \
1571af526226Smrg do \
1572af526226Smrg { \
1573af526226Smrg long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
1574af526226Smrg void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
1575af526226Smrg handler = (void*)( ( (unsigned)handler ) >> 1 ) ; \
1576af526226Smrg _Unwind_DebugHook ((TARGET)->cfa, handler); \
1577af526226Smrg __builtin_eh_return (offset, handler); \
1578af526226Smrg } \
1579af526226Smrg while (0)
1580af526226Smrg #else
1581e56e5d0aSmrg #define uw_install_context(CURRENT, TARGET, FRAMES) \
1582af526226Smrg do \
1583af526226Smrg { \
1584af526226Smrg long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
1585af526226Smrg void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
1586af526226Smrg _Unwind_DebugHook ((TARGET)->cfa, handler); \
1587af526226Smrg __builtin_eh_return (offset, handler); \
1588af526226Smrg } \
1589af526226Smrg while (0)
1590af526226Smrg #endif /* __CR16C__ */
1591af526226Smrg
1592af526226Smrg static long
uw_install_context_1(struct _Unwind_Context * current,struct _Unwind_Context * target)1593af526226Smrg uw_install_context_1 (struct _Unwind_Context *current,
1594af526226Smrg struct _Unwind_Context *target)
1595af526226Smrg {
1596af526226Smrg long i;
1597af526226Smrg _Unwind_SpTmp sp_slot;
1598af526226Smrg
1599af526226Smrg /* If the target frame does not have a saved stack pointer,
1600af526226Smrg then set up the target's CFA. */
1601af526226Smrg if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
1602af526226Smrg _Unwind_SetSpColumn (target, target->cfa, &sp_slot);
1603af526226Smrg
16044646d632Smrg for (i = 0; i < __LIBGCC_DWARF_FRAME_REGISTERS__; ++i)
1605af526226Smrg {
1606af526226Smrg void *c = (void *) (_Unwind_Internal_Ptr) current->reg[i];
1607af526226Smrg void *t = (void *) (_Unwind_Internal_Ptr)target->reg[i];
1608af526226Smrg
1609af526226Smrg gcc_assert (current->by_value[i] == 0);
1610af526226Smrg if (target->by_value[i] && c)
1611af526226Smrg {
1612af526226Smrg _Unwind_Word w;
1613af526226Smrg _Unwind_Ptr p;
1614af526226Smrg if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
1615af526226Smrg {
1616af526226Smrg w = (_Unwind_Internal_Ptr) t;
1617af526226Smrg memcpy (c, &w, sizeof (_Unwind_Word));
1618af526226Smrg }
1619af526226Smrg else
1620af526226Smrg {
1621af526226Smrg gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
1622af526226Smrg p = (_Unwind_Internal_Ptr) t;
1623af526226Smrg memcpy (c, &p, sizeof (_Unwind_Ptr));
1624af526226Smrg }
1625af526226Smrg }
1626af526226Smrg else if (t && c && t != c)
1627af526226Smrg memcpy (c, t, dwarf_reg_size_table[i]);
1628af526226Smrg }
1629af526226Smrg
1630af526226Smrg /* If the current frame doesn't have a saved stack pointer, then we
1631af526226Smrg need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
1632af526226Smrg pointer value reloaded. */
1633af526226Smrg if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ()))
1634af526226Smrg {
1635af526226Smrg void *target_cfa;
1636af526226Smrg
1637af526226Smrg target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ());
1638af526226Smrg
1639af526226Smrg /* We adjust SP by the difference between CURRENT and TARGET's CFA. */
16404646d632Smrg if (__LIBGCC_STACK_GROWS_DOWNWARD__)
1641af526226Smrg return target_cfa - current->cfa + target->args_size;
1642af526226Smrg else
1643af526226Smrg return current->cfa - target_cfa - target->args_size;
1644af526226Smrg }
1645af526226Smrg return 0;
1646af526226Smrg }
1647af526226Smrg
1648af526226Smrg static inline _Unwind_Ptr
uw_identify_context(struct _Unwind_Context * context)1649af526226Smrg uw_identify_context (struct _Unwind_Context *context)
1650af526226Smrg {
1651af526226Smrg /* The CFA is not sufficient to disambiguate the context of a function
1652af526226Smrg interrupted by a signal before establishing its frame and the context
1653af526226Smrg of the signal itself. */
16544646d632Smrg if (__LIBGCC_STACK_GROWS_DOWNWARD__)
1655af526226Smrg return _Unwind_GetCFA (context) - _Unwind_IsSignalFrame (context);
1656af526226Smrg else
1657af526226Smrg return _Unwind_GetCFA (context) + _Unwind_IsSignalFrame (context);
1658af526226Smrg }
1659af526226Smrg
1660af526226Smrg
1661af526226Smrg #include "unwind.inc"
1662af526226Smrg
1663af526226Smrg #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
1664af526226Smrg alias (_Unwind_Backtrace);
1665af526226Smrg alias (_Unwind_DeleteException);
1666af526226Smrg alias (_Unwind_FindEnclosingFunction);
1667af526226Smrg alias (_Unwind_ForcedUnwind);
1668af526226Smrg alias (_Unwind_GetDataRelBase);
1669af526226Smrg alias (_Unwind_GetTextRelBase);
1670af526226Smrg alias (_Unwind_GetCFA);
1671af526226Smrg alias (_Unwind_GetGR);
1672af526226Smrg alias (_Unwind_GetIP);
1673af526226Smrg alias (_Unwind_GetLanguageSpecificData);
1674af526226Smrg alias (_Unwind_GetRegionStart);
1675af526226Smrg alias (_Unwind_RaiseException);
1676af526226Smrg alias (_Unwind_Resume);
1677af526226Smrg alias (_Unwind_Resume_or_Rethrow);
1678af526226Smrg alias (_Unwind_SetGR);
1679af526226Smrg alias (_Unwind_SetIP);
1680af526226Smrg #endif
1681af526226Smrg
1682af526226Smrg #endif /* !USING_SJLJ_EXCEPTIONS */
1683