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