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, &reg);
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, &reg);
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, &reg);
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, &reg);
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, &reg);
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, &reg);
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, &reg);
1018af526226Smrg 	    insn_ptr = read_uleb128 (insn_ptr, &reg2);
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, &reg);
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, &reg);
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, &reg);
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, &reg);
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, &reg);
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, &reg);
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