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