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