unwind-dw2-xtensa.c revision 1.2.8.2 1 1.2.8.2 tls /* DWARF2 exception handling and frame unwinding for Xtensa.
2 1.2.8.2 tls Copyright (C) 1997-2013 Free Software Foundation, Inc.
3 1.2.8.2 tls
4 1.2.8.2 tls This file is part of GCC.
5 1.2.8.2 tls
6 1.2.8.2 tls GCC is free software; you can redistribute it and/or modify it
7 1.2.8.2 tls under the terms of the GNU General Public License as published by
8 1.2.8.2 tls the Free Software Foundation; either version 3, or (at your option)
9 1.2.8.2 tls any later version.
10 1.2.8.2 tls
11 1.2.8.2 tls GCC is distributed in the hope that it will be useful, but WITHOUT
12 1.2.8.2 tls ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 1.2.8.2 tls or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 1.2.8.2 tls License for more details.
15 1.2.8.2 tls
16 1.2.8.2 tls Under Section 7 of GPL version 3, you are granted additional
17 1.2.8.2 tls permissions described in the GCC Runtime Library Exception, version
18 1.2.8.2 tls 3.1, as published by the Free Software Foundation.
19 1.2.8.2 tls
20 1.2.8.2 tls You should have received a copy of the GNU General Public License and
21 1.2.8.2 tls a copy of the GCC Runtime Library Exception along with this program;
22 1.2.8.2 tls see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 1.2.8.2 tls <http://www.gnu.org/licenses/>. */
24 1.2.8.2 tls
25 1.2.8.2 tls #include "tconfig.h"
26 1.2.8.2 tls #include "tsystem.h"
27 1.2.8.2 tls #include "coretypes.h"
28 1.2.8.2 tls #include "tm.h"
29 1.2.8.2 tls #include "libgcc_tm.h"
30 1.2.8.2 tls #include "dwarf2.h"
31 1.2.8.2 tls #include "unwind.h"
32 1.2.8.2 tls #ifdef __USING_SJLJ_EXCEPTIONS__
33 1.2.8.2 tls # define NO_SIZE_OF_ENCODED_VALUE
34 1.2.8.2 tls #endif
35 1.2.8.2 tls #include "unwind-pe.h"
36 1.2.8.2 tls #include "unwind-dw2-fde.h"
37 1.2.8.2 tls #include "unwind-dw2-xtensa.h"
38 1.2.8.2 tls
39 1.2.8.2 tls #ifndef __USING_SJLJ_EXCEPTIONS__
40 1.2.8.2 tls
41 1.2.8.2 tls /* The standard CIE and FDE structures work fine for Xtensa but the
42 1.2.8.2 tls variable-size register window save areas are not a good fit for the rest
43 1.2.8.2 tls of the standard DWARF unwinding mechanism. Nor is that mechanism
44 1.2.8.2 tls necessary, since the register save areas are always in fixed locations
45 1.2.8.2 tls in each stack frame. This file is a stripped down and customized version
46 1.2.8.2 tls of the standard DWARF unwinding code. It needs to be customized to have
47 1.2.8.2 tls builtin logic for finding the save areas and also to track the stack
48 1.2.8.2 tls pointer value (besides the CFA) while unwinding since the primary save
49 1.2.8.2 tls area is located below the stack pointer. It is stripped down to reduce
50 1.2.8.2 tls code size and ease the maintenance burden of tracking changes in the
51 1.2.8.2 tls standard version of the code. */
52 1.2.8.2 tls
53 1.2.8.2 tls #ifndef DWARF_REG_TO_UNWIND_COLUMN
54 1.2.8.2 tls #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
55 1.2.8.2 tls #endif
56 1.2.8.2 tls
57 1.2.8.2 tls #define XTENSA_RA_FIELD_MASK 0x3FFFFFFF
58 1.2.8.2 tls
59 1.2.8.2 tls /* This is the register and unwind state for a particular frame. This
60 1.2.8.2 tls provides the information necessary to unwind up past a frame and return
61 1.2.8.2 tls to its caller. */
62 1.2.8.2 tls struct _Unwind_Context
63 1.2.8.2 tls {
64 1.2.8.2 tls /* Track register window save areas of 4 registers each, instead of
65 1.2.8.2 tls keeping separate addresses for the individual registers. */
66 1.2.8.2 tls _Unwind_Word *reg[4];
67 1.2.8.2 tls
68 1.2.8.2 tls void *cfa;
69 1.2.8.2 tls void *sp;
70 1.2.8.2 tls void *ra;
71 1.2.8.2 tls
72 1.2.8.2 tls /* Cache the 2 high bits to replace the window size in return addresses. */
73 1.2.8.2 tls _Unwind_Word ra_high_bits;
74 1.2.8.2 tls
75 1.2.8.2 tls void *lsda;
76 1.2.8.2 tls struct dwarf_eh_bases bases;
77 1.2.8.2 tls /* Signal frame context. */
78 1.2.8.2 tls #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
79 1.2.8.2 tls _Unwind_Word flags;
80 1.2.8.2 tls /* 0 for now, can be increased when further fields are added to
81 1.2.8.2 tls struct _Unwind_Context. */
82 1.2.8.2 tls _Unwind_Word version;
83 1.2.8.2 tls };
84 1.2.8.2 tls
85 1.2.8.2 tls
86 1.2.8.2 tls /* Read unaligned data from the instruction buffer. */
88 1.2.8.2 tls
89 1.2.8.2 tls union unaligned
90 1.2.8.2 tls {
91 1.2.8.2 tls void *p;
92 1.2.8.2 tls } __attribute__ ((packed));
93 1.2.8.2 tls
94 1.2.8.2 tls static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
95 1.2.8.2 tls static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
96 1.2.8.2 tls _Unwind_FrameState *);
97 1.2.8.2 tls
98 1.2.8.2 tls static inline void *
99 1.2.8.2 tls read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
100 1.2.8.2 tls
101 1.2.8.2 tls static inline _Unwind_Word
103 1.2.8.2 tls _Unwind_IsSignalFrame (struct _Unwind_Context *context)
104 1.2.8.2 tls {
105 1.2.8.2 tls return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
106 1.2.8.2 tls }
107 1.2.8.2 tls
108 1.2.8.2 tls static inline void
109 1.2.8.2 tls _Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
110 1.2.8.2 tls {
111 1.2.8.2 tls if (val)
112 1.2.8.2 tls context->flags |= SIGNAL_FRAME_BIT;
113 1.2.8.2 tls else
114 1.2.8.2 tls context->flags &= ~SIGNAL_FRAME_BIT;
115 1.2.8.2 tls }
116 1.2.8.2 tls
117 1.2.8.2 tls /* Get the value of register INDEX as saved in CONTEXT. */
119 1.2.8.2 tls
120 1.2.8.2 tls inline _Unwind_Word
121 1.2.8.2 tls _Unwind_GetGR (struct _Unwind_Context *context, int index)
122 1.2.8.2 tls {
123 1.2.8.2 tls _Unwind_Word *ptr;
124 1.2.8.2 tls
125 1.2.8.2 tls index = DWARF_REG_TO_UNWIND_COLUMN (index);
126 1.2.8.2 tls ptr = context->reg[index >> 2] + (index & 3);
127 1.2.8.2 tls
128 1.2.8.2 tls return *ptr;
129 1.2.8.2 tls }
130 1.2.8.2 tls
131 1.2.8.2 tls /* Get the value of the CFA as saved in CONTEXT. */
132 1.2.8.2 tls
133 1.2.8.2 tls _Unwind_Word
134 1.2.8.2 tls _Unwind_GetCFA (struct _Unwind_Context *context)
135 1.2.8.2 tls {
136 1.2.8.2 tls return (_Unwind_Ptr) context->cfa;
137 1.2.8.2 tls }
138 1.2.8.2 tls
139 1.2.8.2 tls /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */
140 1.2.8.2 tls
141 1.2.8.2 tls inline void
142 1.2.8.2 tls _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
143 1.2.8.2 tls {
144 1.2.8.2 tls _Unwind_Word *ptr;
145 1.2.8.2 tls
146 1.2.8.2 tls index = DWARF_REG_TO_UNWIND_COLUMN (index);
147 1.2.8.2 tls ptr = context->reg[index >> 2] + (index & 3);
148 1.2.8.2 tls
149 1.2.8.2 tls *ptr = val;
150 1.2.8.2 tls }
151 1.2.8.2 tls
152 1.2.8.2 tls /* Retrieve the return address for CONTEXT. */
153 1.2.8.2 tls
154 1.2.8.2 tls inline _Unwind_Ptr
155 1.2.8.2 tls _Unwind_GetIP (struct _Unwind_Context *context)
156 1.2.8.2 tls {
157 1.2.8.2 tls return (_Unwind_Ptr) context->ra;
158 1.2.8.2 tls }
159 1.2.8.2 tls
160 1.2.8.2 tls /* Retrieve the return address and flag whether that IP is before
161 1.2.8.2 tls or after first not yet fully executed instruction. */
162 1.2.8.2 tls
163 1.2.8.2 tls inline _Unwind_Ptr
164 1.2.8.2 tls _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
165 1.2.8.2 tls {
166 1.2.8.2 tls *ip_before_insn = _Unwind_IsSignalFrame (context);
167 1.2.8.2 tls return (_Unwind_Ptr) context->ra;
168 1.2.8.2 tls }
169 1.2.8.2 tls
170 1.2.8.2 tls /* Overwrite the return address for CONTEXT with VAL. */
171 1.2.8.2 tls
172 1.2.8.2 tls inline void
173 1.2.8.2 tls _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
174 1.2.8.2 tls {
175 1.2.8.2 tls context->ra = (void *) val;
176 1.2.8.2 tls }
177 1.2.8.2 tls
178 1.2.8.2 tls _Unwind_Ptr
179 1.2.8.2 tls _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
180 1.2.8.2 tls {
181 1.2.8.2 tls return context->lsda;
182 1.2.8.2 tls }
183 1.2.8.2 tls
184 1.2.8.2 tls _Unwind_Ptr
185 1.2.8.2 tls _Unwind_GetRegionStart (struct _Unwind_Context *context)
186 1.2.8.2 tls {
187 1.2.8.2 tls return (_Unwind_Ptr) context->bases.func;
188 1.2.8.2 tls }
189 1.2.8.2 tls
190 1.2.8.2 tls void *
191 1.2.8.2 tls _Unwind_FindEnclosingFunction (void *pc)
192 1.2.8.2 tls {
193 1.2.8.2 tls struct dwarf_eh_bases bases;
194 1.2.8.2 tls const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
195 1.2.8.2 tls if (fde)
196 1.2.8.2 tls return bases.func;
197 1.2.8.2 tls else
198 1.2.8.2 tls return NULL;
199 1.2.8.2 tls }
200 1.2.8.2 tls
201 1.2.8.2 tls _Unwind_Ptr
202 1.2.8.2 tls _Unwind_GetDataRelBase (struct _Unwind_Context *context)
203 1.2.8.2 tls {
204 1.2.8.2 tls return (_Unwind_Ptr) context->bases.dbase;
205 1.2.8.2 tls }
206 1.2.8.2 tls
207 1.2.8.2 tls _Unwind_Ptr
208 1.2.8.2 tls _Unwind_GetTextRelBase (struct _Unwind_Context *context)
209 1.2.8.2 tls {
210 1.2.8.2 tls return (_Unwind_Ptr) context->bases.tbase;
211 1.2.8.2 tls }
212 1.2.8.2 tls
213 1.2.8.2 tls #include "md-unwind-support.h"
214 1.2.8.2 tls
215 1.2.8.2 tls /* Extract any interesting information from the CIE for the translation
217 1.2.8.2 tls unit F belongs to. Return a pointer to the byte after the augmentation,
218 1.2.8.2 tls or NULL if we encountered an undecipherable augmentation. */
219 1.2.8.2 tls
220 1.2.8.2 tls static const unsigned char *
221 1.2.8.2 tls extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
222 1.2.8.2 tls _Unwind_FrameState *fs)
223 1.2.8.2 tls {
224 1.2.8.2 tls const unsigned char *aug = cie->augmentation;
225 1.2.8.2 tls const unsigned char *p = aug + strlen ((const char *)aug) + 1;
226 1.2.8.2 tls const unsigned char *ret = NULL;
227 1.2.8.2 tls _uleb128_t utmp;
228 1.2.8.2 tls _sleb128_t stmp;
229 1.2.8.2 tls
230 1.2.8.2 tls /* g++ v2 "eh" has pointer immediately following augmentation string,
231 1.2.8.2 tls so it must be handled first. */
232 1.2.8.2 tls if (aug[0] == 'e' && aug[1] == 'h')
233 1.2.8.2 tls {
234 1.2.8.2 tls fs->eh_ptr = read_pointer (p);
235 1.2.8.2 tls p += sizeof (void *);
236 1.2.8.2 tls aug += 2;
237 1.2.8.2 tls }
238 1.2.8.2 tls
239 1.2.8.2 tls /* Immediately following the augmentation are the code and
240 1.2.8.2 tls data alignment and return address column. */
241 1.2.8.2 tls p = read_uleb128 (p, &utmp);
242 1.2.8.2 tls p = read_sleb128 (p, &stmp);
243 1.2.8.2 tls if (cie->version == 1)
244 1.2.8.2 tls fs->retaddr_column = *p++;
245 1.2.8.2 tls else
246 1.2.8.2 tls {
247 1.2.8.2 tls p = read_uleb128 (p, &utmp);
248 1.2.8.2 tls fs->retaddr_column = (_Unwind_Word)utmp;
249 1.2.8.2 tls }
250 1.2.8.2 tls fs->lsda_encoding = DW_EH_PE_omit;
251 1.2.8.2 tls
252 1.2.8.2 tls /* If the augmentation starts with 'z', then a uleb128 immediately
253 1.2.8.2 tls follows containing the length of the augmentation field following
254 1.2.8.2 tls the size. */
255 1.2.8.2 tls if (*aug == 'z')
256 1.2.8.2 tls {
257 1.2.8.2 tls p = read_uleb128 (p, &utmp);
258 1.2.8.2 tls ret = p + utmp;
259 1.2.8.2 tls
260 1.2.8.2 tls fs->saw_z = 1;
261 1.2.8.2 tls ++aug;
262 1.2.8.2 tls }
263 1.2.8.2 tls
264 1.2.8.2 tls /* Iterate over recognized augmentation subsequences. */
265 1.2.8.2 tls while (*aug != '\0')
266 1.2.8.2 tls {
267 1.2.8.2 tls /* "L" indicates a byte showing how the LSDA pointer is encoded. */
268 1.2.8.2 tls if (aug[0] == 'L')
269 1.2.8.2 tls {
270 1.2.8.2 tls fs->lsda_encoding = *p++;
271 1.2.8.2 tls aug += 1;
272 1.2.8.2 tls }
273 1.2.8.2 tls
274 1.2.8.2 tls /* "R" indicates a byte indicating how FDE addresses are encoded. */
275 1.2.8.2 tls else if (aug[0] == 'R')
276 1.2.8.2 tls {
277 1.2.8.2 tls fs->fde_encoding = *p++;
278 1.2.8.2 tls aug += 1;
279 1.2.8.2 tls }
280 1.2.8.2 tls
281 1.2.8.2 tls /* "P" indicates a personality routine in the CIE augmentation. */
282 1.2.8.2 tls else if (aug[0] == 'P')
283 1.2.8.2 tls {
284 1.2.8.2 tls _Unwind_Ptr personality;
285 1.2.8.2 tls
286 1.2.8.2 tls p = read_encoded_value (context, *p, p + 1, &personality);
287 1.2.8.2 tls fs->personality = (_Unwind_Personality_Fn) personality;
288 1.2.8.2 tls aug += 1;
289 1.2.8.2 tls }
290 1.2.8.2 tls
291 1.2.8.2 tls /* "S" indicates a signal frame. */
292 1.2.8.2 tls else if (aug[0] == 'S')
293 1.2.8.2 tls {
294 1.2.8.2 tls fs->signal_frame = 1;
295 1.2.8.2 tls aug += 1;
296 1.2.8.2 tls }
297 1.2.8.2 tls
298 1.2.8.2 tls /* Otherwise we have an unknown augmentation string.
299 1.2.8.2 tls Bail unless we saw a 'z' prefix. */
300 1.2.8.2 tls else
301 1.2.8.2 tls return ret;
302 1.2.8.2 tls }
303 1.2.8.2 tls
304 1.2.8.2 tls return ret ? ret : p;
305 1.2.8.2 tls }
306 1.2.8.2 tls
307 1.2.8.2 tls /* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
309 1.2.8.2 tls its caller and decode it into FS. This function also sets the
310 1.2.8.2 tls lsda member of CONTEXT, as it is really information
311 1.2.8.2 tls about the caller's frame. */
312 1.2.8.2 tls
313 1.2.8.2 tls static _Unwind_Reason_Code
314 1.2.8.2 tls uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
315 1.2.8.2 tls {
316 1.2.8.2 tls const struct dwarf_fde *fde;
317 1.2.8.2 tls const struct dwarf_cie *cie;
318 1.2.8.2 tls const unsigned char *aug;
319 1.2.8.2 tls int window_size;
320 1.2.8.2 tls _Unwind_Word *ra_ptr;
321 1.2.8.2 tls
322 1.2.8.2 tls memset (fs, 0, sizeof (*fs));
323 1.2.8.2 tls context->lsda = 0;
324 1.2.8.2 tls
325 1.2.8.2 tls fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
326 1.2.8.2 tls &context->bases);
327 1.2.8.2 tls if (fde == NULL)
328 1.2.8.2 tls {
329 1.2.8.2 tls #ifdef MD_FALLBACK_FRAME_STATE_FOR
330 1.2.8.2 tls _Unwind_Reason_Code reason;
331 1.2.8.2 tls /* Couldn't find frame unwind info for this function. Try a
332 1.2.8.2 tls target-specific fallback mechanism. This will necessarily
333 1.2.8.2 tls not provide a personality routine or LSDA. */
334 1.2.8.2 tls reason = MD_FALLBACK_FRAME_STATE_FOR (context, fs);
335 1.2.8.2 tls if (reason != _URC_END_OF_STACK)
336 1.2.8.2 tls return reason;
337 1.2.8.2 tls #endif
338 1.2.8.2 tls /* The frame was not recognized and handled by the fallback function,
339 1.2.8.2 tls but it is not really the end of the stack. Fall through here and
340 1.2.8.2 tls unwind it anyway. */
341 1.2.8.2 tls }
342 1.2.8.2 tls else
343 1.2.8.2 tls {
344 1.2.8.2 tls cie = get_cie (fde);
345 1.2.8.2 tls if (extract_cie_info (cie, context, fs) == NULL)
346 1.2.8.2 tls /* CIE contained unknown augmentation. */
347 1.2.8.2 tls return _URC_FATAL_PHASE1_ERROR;
348 1.2.8.2 tls
349 1.2.8.2 tls /* Locate augmentation for the fde. */
350 1.2.8.2 tls aug = (const unsigned char *) fde + sizeof (*fde);
351 1.2.8.2 tls aug += 2 * size_of_encoded_value (fs->fde_encoding);
352 1.2.8.2 tls if (fs->saw_z)
353 1.2.8.2 tls {
354 1.2.8.2 tls _uleb128_t i;
355 1.2.8.2 tls aug = read_uleb128 (aug, &i);
356 1.2.8.2 tls }
357 1.2.8.2 tls if (fs->lsda_encoding != DW_EH_PE_omit)
358 1.2.8.2 tls {
359 1.2.8.2 tls _Unwind_Ptr lsda;
360 1.2.8.2 tls
361 1.2.8.2 tls aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
362 1.2.8.2 tls context->lsda = (void *) lsda;
363 1.2.8.2 tls }
364 1.2.8.2 tls }
365 1.2.8.2 tls
366 1.2.8.2 tls /* Check for the end of the stack. This needs to be checked after
367 1.2.8.2 tls the MD_FALLBACK_FRAME_STATE_FOR check for signal frames because
368 1.2.8.2 tls the contents of context->reg[0] are undefined at a signal frame,
369 1.2.8.2 tls and register a0 may appear to be zero. (The return address in
370 1.2.8.2 tls context->ra comes from register a4 or a8). */
371 1.2.8.2 tls ra_ptr = context->reg[0];
372 1.2.8.2 tls if (ra_ptr && *ra_ptr == 0)
373 1.2.8.2 tls return _URC_END_OF_STACK;
374 1.2.8.2 tls
375 1.2.8.2 tls /* Find the window size from the high bits of the return address. */
376 1.2.8.2 tls if (ra_ptr)
377 1.2.8.2 tls window_size = (*ra_ptr >> 30) * 4;
378 1.2.8.2 tls else
379 1.2.8.2 tls window_size = 8;
380 1.2.8.2 tls
381 1.2.8.2 tls fs->retaddr_column = window_size;
382 1.2.8.2 tls
383 1.2.8.2 tls return _URC_NO_REASON;
384 1.2.8.2 tls }
385 1.2.8.2 tls
386 1.2.8.2 tls static void
388 1.2.8.2 tls uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
389 1.2.8.2 tls {
390 1.2.8.2 tls struct _Unwind_Context orig_context = *context;
391 1.2.8.2 tls _Unwind_Word *sp, *cfa, *next_cfa;
392 1.2.8.2 tls int i;
393 1.2.8.2 tls
394 1.2.8.2 tls if (fs->signal_regs)
395 1.2.8.2 tls {
396 1.2.8.2 tls cfa = (_Unwind_Word *) fs->signal_regs[1];
397 1.2.8.2 tls next_cfa = (_Unwind_Word *) cfa[-3];
398 1.2.8.2 tls
399 1.2.8.2 tls for (i = 0; i < 4; i++)
400 1.2.8.2 tls context->reg[i] = fs->signal_regs + (i << 2);
401 1.2.8.2 tls }
402 1.2.8.2 tls else
403 1.2.8.2 tls {
404 1.2.8.2 tls int window_size = fs->retaddr_column >> 2;
405 1.2.8.2 tls
406 1.2.8.2 tls sp = (_Unwind_Word *) orig_context.sp;
407 1.2.8.2 tls cfa = (_Unwind_Word *) orig_context.cfa;
408 1.2.8.2 tls next_cfa = (_Unwind_Word *) cfa[-3];
409 1.2.8.2 tls
410 1.2.8.2 tls /* Registers a0-a3 are in the save area below sp. */
411 1.2.8.2 tls context->reg[0] = sp - 4;
412 1.2.8.2 tls
413 1.2.8.2 tls /* Find the extra save area below next_cfa. */
414 1.2.8.2 tls for (i = 1; i < window_size; i++)
415 1.2.8.2 tls context->reg[i] = next_cfa - 4 * (1 + window_size - i);
416 1.2.8.2 tls
417 1.2.8.2 tls /* Remaining registers rotate from previous save areas. */
418 1.2.8.2 tls for (i = window_size; i < 4; i++)
419 1.2.8.2 tls context->reg[i] = orig_context.reg[i - window_size];
420 1.2.8.2 tls }
421 1.2.8.2 tls
422 1.2.8.2 tls context->sp = cfa;
423 1.2.8.2 tls context->cfa = next_cfa;
424 1.2.8.2 tls
425 1.2.8.2 tls _Unwind_SetSignalFrame (context, fs->signal_frame);
426 1.2.8.2 tls }
427 1.2.8.2 tls
428 1.2.8.2 tls /* CONTEXT describes the unwind state for a frame, and FS describes the FDE
429 1.2.8.2 tls of its caller. Update CONTEXT to refer to the caller as well. Note
430 1.2.8.2 tls that the lsda member is not updated here, but later in
431 1.2.8.2 tls uw_frame_state_for. */
432 1.2.8.2 tls
433 1.2.8.2 tls static void
434 1.2.8.2 tls uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
435 1.2.8.2 tls {
436 1.2.8.2 tls uw_update_context_1 (context, fs);
437 1.2.8.2 tls
438 1.2.8.2 tls /* Compute the return address now, since the return address column
439 1.2.8.2 tls can change from frame to frame. */
440 1.2.8.2 tls if (fs->signal_ra != 0)
441 1.2.8.2 tls context->ra = (void *) fs->signal_ra;
442 1.2.8.2 tls else
443 1.2.8.2 tls context->ra = (void *) ((_Unwind_GetGR (context, fs->retaddr_column)
444 1.2.8.2 tls & XTENSA_RA_FIELD_MASK) | context->ra_high_bits);
445 1.2.8.2 tls }
446 1.2.8.2 tls
447 1.2.8.2 tls static void
448 1.2.8.2 tls uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
449 1.2.8.2 tls {
450 1.2.8.2 tls uw_update_context (context, fs);
451 1.2.8.2 tls }
452 1.2.8.2 tls
453 1.2.8.2 tls /* Fill in CONTEXT for top-of-stack. The only valid registers at this
455 1.2.8.2 tls level will be the return address and the CFA. */
456 1.2.8.2 tls
457 1.2.8.2 tls #define uw_init_context(CONTEXT) \
458 1.2.8.2 tls do \
459 1.2.8.2 tls { \
460 1.2.8.2 tls __builtin_unwind_init (); \
461 1.2.8.2 tls uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \
462 1.2.8.2 tls __builtin_return_address (0)); \
463 1.2.8.2 tls } \
464 1.2.8.2 tls while (0)
465 1.2.8.2 tls
466 1.2.8.2 tls static void __attribute__((noinline))
467 1.2.8.2 tls uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa,
468 1.2.8.2 tls void *outer_ra)
469 1.2.8.2 tls {
470 1.2.8.2 tls void *ra = __builtin_return_address (0);
471 1.2.8.2 tls void *cfa = __builtin_dwarf_cfa ();
472 1.2.8.2 tls _Unwind_FrameState fs;
473 1.2.8.2 tls
474 1.2.8.2 tls memset (context, 0, sizeof (struct _Unwind_Context));
475 1.2.8.2 tls context->ra = ra;
476 1.2.8.2 tls
477 1.2.8.2 tls memset (&fs, 0, sizeof (fs));
478 1.2.8.2 tls fs.retaddr_column = 8;
479 1.2.8.2 tls context->sp = cfa;
480 1.2.8.2 tls context->cfa = outer_cfa;
481 1.2.8.2 tls context->ra_high_bits =
482 1.2.8.2 tls ((_Unwind_Word) uw_init_context_1) & ~XTENSA_RA_FIELD_MASK;
483 1.2.8.2 tls uw_update_context_1 (context, &fs);
484 1.2.8.2 tls
485 1.2.8.2 tls context->ra = outer_ra;
486 1.2.8.2 tls }
487 1.2.8.2 tls
488 1.2.8.2 tls
489 1.2.8.2 tls /* Install TARGET into CURRENT so that we can return to it. This is a
490 1.2.8.2 tls macro because __builtin_eh_return must be invoked in the context of
491 1.2.8.2 tls our caller. */
492 1.2.8.2 tls
493 1.2.8.2 tls #define uw_install_context(CURRENT, TARGET) \
494 1.2.8.2 tls do \
495 1.2.8.2 tls { \
496 1.2.8.2 tls long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
497 1.2.8.2 tls void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
498 1.2.8.2 tls __builtin_eh_return (offset, handler); \
499 1.2.8.2 tls } \
500 1.2.8.2 tls while (0)
501 1.2.8.2 tls
502 1.2.8.2 tls static long
503 1.2.8.2 tls uw_install_context_1 (struct _Unwind_Context *current,
504 1.2.8.2 tls struct _Unwind_Context *target)
505 1.2.8.2 tls {
506 1.2.8.2 tls long i;
507 1.2.8.2 tls
508 1.2.8.2 tls /* The eh_return insn assumes a window size of 8, so don't bother copying
509 1.2.8.2 tls the save areas for registers a8-a15 since they won't be reloaded. */
510 1.2.8.2 tls for (i = 0; i < 2; ++i)
511 1.2.8.2 tls {
512 1.2.8.2 tls void *c = current->reg[i];
513 1.2.8.2 tls void *t = target->reg[i];
514 1.2.8.2 tls
515 1.2.8.2 tls if (t && c && t != c)
516 1.2.8.2 tls memcpy (c, t, 4 * sizeof (_Unwind_Word));
517 1.2.8.2 tls }
518 1.2.8.2 tls
519 1.2.8.2 tls return 0;
520 1.2.8.2 tls }
521 1.2.8.2 tls
522 1.2.8.2 tls static inline _Unwind_Ptr
523 1.2.8.2 tls uw_identify_context (struct _Unwind_Context *context)
524 1.2.8.2 tls {
525 1.2.8.2 tls return _Unwind_GetCFA (context);
526 1.2.8.2 tls }
527 1.2.8.2 tls
528 1.2.8.2 tls
529 1.2.8.2 tls #include "unwind.inc"
530 1.2.8.2 tls
531 1.2.8.2 tls #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
532 1.2.8.2 tls alias (_Unwind_Backtrace);
533 1.2.8.2 tls alias (_Unwind_DeleteException);
534 1.2.8.2 tls alias (_Unwind_FindEnclosingFunction);
535 1.2.8.2 tls alias (_Unwind_ForcedUnwind);
536 1.2.8.2 tls alias (_Unwind_GetDataRelBase);
537 1.2.8.2 tls alias (_Unwind_GetTextRelBase);
538 1.2.8.2 tls alias (_Unwind_GetCFA);
539 1.2.8.2 tls alias (_Unwind_GetGR);
540 1.2.8.2 tls alias (_Unwind_GetIP);
541 1.2.8.2 tls alias (_Unwind_GetLanguageSpecificData);
542 1.2.8.2 tls alias (_Unwind_GetRegionStart);
543 1.2.8.2 tls alias (_Unwind_RaiseException);
544 alias (_Unwind_Resume);
545 alias (_Unwind_Resume_or_Rethrow);
546 alias (_Unwind_SetGR);
547 alias (_Unwind_SetIP);
548 #endif
549
550 #endif /* !USING_SJLJ_EXCEPTIONS */
551