Merge -r 127928:132243 from trunk
[official-gcc.git] / gcc / config / xtensa / unwind-dw2-xtensa.c
blob22b492f9eadfb849c9a2333eb88503a314d4c56b
1 /* DWARF2 exception handling and frame unwinding for Xtensa.
2 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 2007, 2008
4 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 In addition to the permissions in the GNU General Public License, the
14 Free Software Foundation gives you unlimited permission to link the
15 compiled version of this file into combinations with other programs,
16 and to distribute those combinations without any restriction coming
17 from the use of this file. (The General Public License restrictions
18 do apply in other respects; for example, they cover modification of
19 the file, and distribution when not linked into a combined
20 executable.)
22 GCC is distributed in the hope that it will be useful, but WITHOUT
23 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
25 License for more details.
27 You should have received a copy of the GNU General Public License
28 along with GCC; see the file COPYING. If not, write to the Free
29 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
30 02110-1301, USA. */
32 #include "tconfig.h"
33 #include "tsystem.h"
34 #include "coretypes.h"
35 #include "tm.h"
36 #include "dwarf2.h"
37 #include "unwind.h"
38 #ifdef __USING_SJLJ_EXCEPTIONS__
39 # define NO_SIZE_OF_ENCODED_VALUE
40 #endif
41 #include "unwind-pe.h"
42 #include "unwind-dw2-fde.h"
43 #include "unwind-dw2-xtensa.h"
45 #ifndef __USING_SJLJ_EXCEPTIONS__
47 /* The standard CIE and FDE structures work fine for Xtensa but the
48 variable-size register window save areas are not a good fit for the rest
49 of the standard DWARF unwinding mechanism. Nor is that mechanism
50 necessary, since the register save areas are always in fixed locations
51 in each stack frame. This file is a stripped down and customized version
52 of the standard DWARF unwinding code. It needs to be customized to have
53 builtin logic for finding the save areas and also to track the stack
54 pointer value (besides the CFA) while unwinding since the primary save
55 area is located below the stack pointer. It is stripped down to reduce
56 code size and ease the maintenance burden of tracking changes in the
57 standard version of the code. */
59 #ifndef DWARF_REG_TO_UNWIND_COLUMN
60 #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
61 #endif
63 #define XTENSA_RA_FIELD_MASK 0x3FFFFFFF
65 /* This is the register and unwind state for a particular frame. This
66 provides the information necessary to unwind up past a frame and return
67 to its caller. */
68 struct _Unwind_Context
70 /* Track register window save areas of 4 registers each, instead of
71 keeping separate addresses for the individual registers. */
72 _Unwind_Word *reg[4];
74 void *cfa;
75 void *sp;
76 void *ra;
78 /* Cache the 2 high bits to replace the window size in return addresses. */
79 _Unwind_Word ra_high_bits;
81 void *lsda;
82 struct dwarf_eh_bases bases;
83 /* Signal frame context. */
84 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
85 _Unwind_Word flags;
86 /* 0 for now, can be increased when further fields are added to
87 struct _Unwind_Context. */
88 _Unwind_Word version;
92 /* Read unaligned data from the instruction buffer. */
94 union unaligned
96 void *p;
97 } __attribute__ ((packed));
99 static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
100 static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
101 _Unwind_FrameState *);
103 static inline void *
104 read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
106 static inline _Unwind_Word
107 _Unwind_IsSignalFrame (struct _Unwind_Context *context)
109 return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
112 static inline void
113 _Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
115 if (val)
116 context->flags |= SIGNAL_FRAME_BIT;
117 else
118 context->flags &= ~SIGNAL_FRAME_BIT;
121 /* Get the value of register INDEX as saved in CONTEXT. */
123 inline _Unwind_Word
124 _Unwind_GetGR (struct _Unwind_Context *context, int index)
126 _Unwind_Word *ptr;
128 index = DWARF_REG_TO_UNWIND_COLUMN (index);
129 ptr = context->reg[index >> 2] + (index & 3);
131 return *ptr;
134 /* Get the value of the CFA as saved in CONTEXT. */
136 _Unwind_Word
137 _Unwind_GetCFA (struct _Unwind_Context *context)
139 return (_Unwind_Ptr) context->cfa;
142 /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */
144 inline void
145 _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
147 _Unwind_Word *ptr;
149 index = DWARF_REG_TO_UNWIND_COLUMN (index);
150 ptr = context->reg[index >> 2] + (index & 3);
152 *ptr = val;
155 /* Retrieve the return address for CONTEXT. */
157 inline _Unwind_Ptr
158 _Unwind_GetIP (struct _Unwind_Context *context)
160 return (_Unwind_Ptr) context->ra;
163 /* Retrieve the return address and flag whether that IP is before
164 or after first not yet fully executed instruction. */
166 inline _Unwind_Ptr
167 _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
169 *ip_before_insn = _Unwind_IsSignalFrame (context);
170 return (_Unwind_Ptr) context->ra;
173 /* Overwrite the return address for CONTEXT with VAL. */
175 inline void
176 _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
178 context->ra = (void *) val;
181 void *
182 _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
184 return context->lsda;
187 _Unwind_Ptr
188 _Unwind_GetRegionStart (struct _Unwind_Context *context)
190 return (_Unwind_Ptr) context->bases.func;
193 void *
194 _Unwind_FindEnclosingFunction (void *pc)
196 struct dwarf_eh_bases bases;
197 const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
198 if (fde)
199 return bases.func;
200 else
201 return NULL;
204 _Unwind_Ptr
205 _Unwind_GetDataRelBase (struct _Unwind_Context *context)
207 return (_Unwind_Ptr) context->bases.dbase;
210 _Unwind_Ptr
211 _Unwind_GetTextRelBase (struct _Unwind_Context *context)
213 return (_Unwind_Ptr) context->bases.tbase;
216 #ifdef MD_UNWIND_SUPPORT
217 #include MD_UNWIND_SUPPORT
218 #endif
220 /* Extract any interesting information from the CIE for the translation
221 unit F belongs to. Return a pointer to the byte after the augmentation,
222 or NULL if we encountered an undecipherable augmentation. */
224 static const unsigned char *
225 extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
226 _Unwind_FrameState *fs)
228 const unsigned char *aug = cie->augmentation;
229 const unsigned char *p = aug + strlen ((const char *)aug) + 1;
230 const unsigned char *ret = NULL;
231 _uleb128_t utmp;
232 _sleb128_t stmp;
234 /* g++ v2 "eh" has pointer immediately following augmentation string,
235 so it must be handled first. */
236 if (aug[0] == 'e' && aug[1] == 'h')
238 fs->eh_ptr = read_pointer (p);
239 p += sizeof (void *);
240 aug += 2;
243 /* Immediately following the augmentation are the code and
244 data alignment and return address column. */
245 p = read_uleb128 (p, &utmp);
246 p = read_sleb128 (p, &stmp);
247 if (cie->version == 1)
248 fs->retaddr_column = *p++;
249 else
251 p = read_uleb128 (p, &utmp);
252 fs->retaddr_column = (_Unwind_Word)utmp;
254 fs->lsda_encoding = DW_EH_PE_omit;
256 /* If the augmentation starts with 'z', then a uleb128 immediately
257 follows containing the length of the augmentation field following
258 the size. */
259 if (*aug == 'z')
261 p = read_uleb128 (p, &utmp);
262 ret = p + utmp;
264 fs->saw_z = 1;
265 ++aug;
268 /* Iterate over recognized augmentation subsequences. */
269 while (*aug != '\0')
271 /* "L" indicates a byte showing how the LSDA pointer is encoded. */
272 if (aug[0] == 'L')
274 fs->lsda_encoding = *p++;
275 aug += 1;
278 /* "R" indicates a byte indicating how FDE addresses are encoded. */
279 else if (aug[0] == 'R')
281 fs->fde_encoding = *p++;
282 aug += 1;
285 /* "P" indicates a personality routine in the CIE augmentation. */
286 else if (aug[0] == 'P')
288 _Unwind_Ptr personality;
290 p = read_encoded_value (context, *p, p + 1, &personality);
291 fs->personality = (_Unwind_Personality_Fn) personality;
292 aug += 1;
295 /* "S" indicates a signal frame. */
296 else if (aug[0] == 'S')
298 fs->signal_frame = 1;
299 aug += 1;
302 /* Otherwise we have an unknown augmentation string.
303 Bail unless we saw a 'z' prefix. */
304 else
305 return ret;
308 return ret ? ret : p;
311 /* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
312 its caller and decode it into FS. This function also sets the
313 lsda member of CONTEXT, as it is really information
314 about the caller's frame. */
316 static _Unwind_Reason_Code
317 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
319 const struct dwarf_fde *fde;
320 const struct dwarf_cie *cie;
321 const unsigned char *aug;
322 int window_size;
323 _Unwind_Word *ra_ptr;
325 memset (fs, 0, sizeof (*fs));
326 context->lsda = 0;
328 fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
329 &context->bases);
330 if (fde == NULL)
332 #ifdef MD_FALLBACK_FRAME_STATE_FOR
333 _Unwind_Reason_Code reason;
334 /* Couldn't find frame unwind info for this function. Try a
335 target-specific fallback mechanism. This will necessarily
336 not provide a personality routine or LSDA. */
337 reason = MD_FALLBACK_FRAME_STATE_FOR (context, fs);
338 if (reason != _URC_END_OF_STACK)
339 return reason;
340 #endif
341 /* The frame was not recognized and handled by the fallback function,
342 but it is not really the end of the stack. Fall through here and
343 unwind it anyway. */
345 else
347 cie = get_cie (fde);
348 if (extract_cie_info (cie, context, fs) == NULL)
349 /* CIE contained unknown augmentation. */
350 return _URC_FATAL_PHASE1_ERROR;
352 /* Locate augmentation for the fde. */
353 aug = (const unsigned char *) fde + sizeof (*fde);
354 aug += 2 * size_of_encoded_value (fs->fde_encoding);
355 if (fs->saw_z)
357 _uleb128_t i;
358 aug = read_uleb128 (aug, &i);
360 if (fs->lsda_encoding != DW_EH_PE_omit)
362 _Unwind_Ptr lsda;
364 aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
365 context->lsda = (void *) lsda;
369 /* Check for the end of the stack. This needs to be checked after
370 the MD_FALLBACK_FRAME_STATE_FOR check for signal frames because
371 the contents of context->reg[0] are undefined at a signal frame,
372 and register a0 may appear to be zero. (The return address in
373 context->ra comes from register a4 or a8). */
374 ra_ptr = context->reg[0];
375 if (ra_ptr && *ra_ptr == 0)
376 return _URC_END_OF_STACK;
378 /* Find the window size from the high bits of the return address. */
379 if (ra_ptr)
380 window_size = (*ra_ptr >> 30) * 4;
381 else
382 window_size = 8;
384 fs->retaddr_column = window_size;
386 return _URC_NO_REASON;
389 static void
390 uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
392 struct _Unwind_Context orig_context = *context;
393 _Unwind_Word *sp, *cfa, *next_cfa;
394 int i;
396 if (fs->signal_regs)
398 cfa = (_Unwind_Word *) fs->signal_regs[1];
399 next_cfa = (_Unwind_Word *) cfa[-3];
401 for (i = 0; i < 4; i++)
402 context->reg[i] = fs->signal_regs + (i << 2);
404 else
406 int window_size = fs->retaddr_column >> 2;
408 sp = (_Unwind_Word *) orig_context.sp;
409 cfa = (_Unwind_Word *) orig_context.cfa;
410 next_cfa = (_Unwind_Word *) cfa[-3];
412 /* Registers a0-a3 are in the save area below sp. */
413 context->reg[0] = sp - 4;
415 /* Find the extra save area below next_cfa. */
416 for (i = 1; i < window_size; i++)
417 context->reg[i] = next_cfa - 4 * (1 + window_size - i);
419 /* Remaining registers rotate from previous save areas. */
420 for (i = window_size; i < 4; i++)
421 context->reg[i] = orig_context.reg[i - window_size];
424 context->sp = cfa;
425 context->cfa = next_cfa;
427 _Unwind_SetSignalFrame (context, fs->signal_frame);
430 /* CONTEXT describes the unwind state for a frame, and FS describes the FDE
431 of its caller. Update CONTEXT to refer to the caller as well. Note
432 that the lsda member is not updated here, but later in
433 uw_frame_state_for. */
435 static void
436 uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
438 uw_update_context_1 (context, fs);
440 /* Compute the return address now, since the return address column
441 can change from frame to frame. */
442 if (fs->signal_ra != 0)
443 context->ra = (void *) fs->signal_ra;
444 else
445 context->ra = (void *) ((_Unwind_GetGR (context, fs->retaddr_column)
446 & XTENSA_RA_FIELD_MASK) | context->ra_high_bits);
449 static void
450 uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
452 uw_update_context (context, fs);
455 /* Fill in CONTEXT for top-of-stack. The only valid registers at this
456 level will be the return address and the CFA. */
458 #define uw_init_context(CONTEXT) \
459 do \
461 __builtin_unwind_init (); \
462 uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \
463 __builtin_return_address (0)); \
465 while (0)
467 static void
468 uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa,
469 void *outer_ra)
471 void *ra = __builtin_return_address (0);
472 void *cfa = __builtin_dwarf_cfa ();
473 _Unwind_FrameState fs;
475 memset (context, 0, sizeof (struct _Unwind_Context));
476 context->ra = ra;
478 memset (&fs, 0, sizeof (fs));
479 fs.retaddr_column = 8;
480 context->sp = cfa;
481 context->cfa = outer_cfa;
482 context->ra_high_bits =
483 ((_Unwind_Word) uw_init_context_1) & ~XTENSA_RA_FIELD_MASK;
484 uw_update_context_1 (context, &fs);
486 context->ra = outer_ra;
490 /* Install TARGET into CURRENT so that we can return to it. This is a
491 macro because __builtin_eh_return must be invoked in the context of
492 our caller. */
494 #define uw_install_context(CURRENT, TARGET) \
495 do \
497 long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
498 void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
499 __builtin_eh_return (offset, handler); \
501 while (0)
503 static long
504 uw_install_context_1 (struct _Unwind_Context *current,
505 struct _Unwind_Context *target)
507 long i;
509 /* The eh_return insn assumes a window size of 8, so don't bother copying
510 the save areas for registers a8-a15 since they won't be reloaded. */
511 for (i = 0; i < 2; ++i)
513 void *c = current->reg[i];
514 void *t = target->reg[i];
516 if (t && c && t != c)
517 memcpy (c, t, 4 * sizeof (_Unwind_Word));
520 return 0;
523 static inline _Unwind_Ptr
524 uw_identify_context (struct _Unwind_Context *context)
526 return _Unwind_GetCFA (context);
530 #include "unwind.inc"
532 #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
533 alias (_Unwind_Backtrace);
534 alias (_Unwind_DeleteException);
535 alias (_Unwind_FindEnclosingFunction);
536 alias (_Unwind_ForcedUnwind);
537 alias (_Unwind_GetDataRelBase);
538 alias (_Unwind_GetTextRelBase);
539 alias (_Unwind_GetCFA);
540 alias (_Unwind_GetGR);
541 alias (_Unwind_GetIP);
542 alias (_Unwind_GetLanguageSpecificData);
543 alias (_Unwind_GetRegionStart);
544 alias (_Unwind_RaiseException);
545 alias (_Unwind_Resume);
546 alias (_Unwind_Resume_or_Rethrow);
547 alias (_Unwind_SetGR);
548 alias (_Unwind_SetIP);
549 #endif
551 #endif /* !USING_SJLJ_EXCEPTIONS */