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, ®);
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, ®);
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, ®);
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, ®);
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, ®);
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, ®);
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, ®);
1009*e4b17023SJohn Marino insn_ptr = read_uleb128 (insn_ptr, ®2);
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, ®);
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, ®);
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, ®);
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, ®);
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, ®);
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, ®);
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