1 /* DWARF2 exception handling and frame unwinding for Xtensa.
2 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
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 3, or (at your option)
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.
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.
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/>. */
29 #include "coretypes.h"
31 #include "libgcc_tm.h"
34 #ifdef __USING_SJLJ_EXCEPTIONS__
35 # define NO_SIZE_OF_ENCODED_VALUE
37 #include "unwind-pe.h"
38 #include "unwind-dw2-fde.h"
39 #include "unwind-dw2-xtensa.h"
41 #ifndef __USING_SJLJ_EXCEPTIONS__
43 /* The standard CIE and FDE structures work fine for Xtensa but the
44 variable-size register window save areas are not a good fit for the rest
45 of the standard DWARF unwinding mechanism. Nor is that mechanism
46 necessary, since the register save areas are always in fixed locations
47 in each stack frame. This file is a stripped down and customized version
48 of the standard DWARF unwinding code. It needs to be customized to have
49 builtin logic for finding the save areas and also to track the stack
50 pointer value (besides the CFA) while unwinding since the primary save
51 area is located below the stack pointer. It is stripped down to reduce
52 code size and ease the maintenance burden of tracking changes in the
53 standard version of the code. */
55 #ifndef DWARF_REG_TO_UNWIND_COLUMN
56 #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
59 #define XTENSA_RA_FIELD_MASK 0x3FFFFFFF
61 /* This is the register and unwind state for a particular frame. This
62 provides the information necessary to unwind up past a frame and return
64 struct _Unwind_Context
66 /* Track register window save areas of 4 registers each, instead of
67 keeping separate addresses for the individual registers. */
74 /* Cache the 2 high bits to replace the window size in return addresses. */
75 _Unwind_Word ra_high_bits
;
78 struct dwarf_eh_bases bases
;
79 /* Signal frame context. */
80 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
82 /* 0 for now, can be increased when further fields are added to
83 struct _Unwind_Context. */
88 /* Read unaligned data from the instruction buffer. */
93 } __attribute__ ((packed
));
95 static void uw_update_context (struct _Unwind_Context
*, _Unwind_FrameState
*);
96 static _Unwind_Reason_Code
uw_frame_state_for (struct _Unwind_Context
*,
97 _Unwind_FrameState
*);
100 read_pointer (const void *p
) { const union unaligned
*up
= p
; return up
->p
; }
102 static inline _Unwind_Word
103 _Unwind_IsSignalFrame (struct _Unwind_Context
*context
)
105 return (context
->flags
& SIGNAL_FRAME_BIT
) ? 1 : 0;
109 _Unwind_SetSignalFrame (struct _Unwind_Context
*context
, int val
)
112 context
->flags
|= SIGNAL_FRAME_BIT
;
114 context
->flags
&= ~SIGNAL_FRAME_BIT
;
117 /* Get the value of register INDEX as saved in CONTEXT. */
120 _Unwind_GetGR (struct _Unwind_Context
*context
, int index
)
124 index
= DWARF_REG_TO_UNWIND_COLUMN (index
);
125 ptr
= context
->reg
[index
>> 2] + (index
& 3);
130 /* Get the value of the CFA as saved in CONTEXT. */
133 _Unwind_GetCFA (struct _Unwind_Context
*context
)
135 return (_Unwind_Ptr
) context
->cfa
;
138 /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */
141 _Unwind_SetGR (struct _Unwind_Context
*context
, int index
, _Unwind_Word val
)
145 index
= DWARF_REG_TO_UNWIND_COLUMN (index
);
146 ptr
= context
->reg
[index
>> 2] + (index
& 3);
151 /* Retrieve the return address for CONTEXT. */
154 _Unwind_GetIP (struct _Unwind_Context
*context
)
156 return (_Unwind_Ptr
) context
->ra
;
159 /* Retrieve the return address and flag whether that IP is before
160 or after first not yet fully executed instruction. */
163 _Unwind_GetIPInfo (struct _Unwind_Context
*context
, int *ip_before_insn
)
165 *ip_before_insn
= _Unwind_IsSignalFrame (context
);
166 return (_Unwind_Ptr
) context
->ra
;
169 /* Overwrite the return address for CONTEXT with VAL. */
172 _Unwind_SetIP (struct _Unwind_Context
*context
, _Unwind_Ptr val
)
174 context
->ra
= (void *) val
;
178 _Unwind_GetLanguageSpecificData (struct _Unwind_Context
*context
)
180 return context
->lsda
;
184 _Unwind_GetRegionStart (struct _Unwind_Context
*context
)
186 return (_Unwind_Ptr
) context
->bases
.func
;
190 _Unwind_FindEnclosingFunction (void *pc
)
192 struct dwarf_eh_bases bases
;
193 const struct dwarf_fde
*fde
= _Unwind_Find_FDE (pc
-1, &bases
);
201 _Unwind_GetDataRelBase (struct _Unwind_Context
*context
)
203 return (_Unwind_Ptr
) context
->bases
.dbase
;
207 _Unwind_GetTextRelBase (struct _Unwind_Context
*context
)
209 return (_Unwind_Ptr
) context
->bases
.tbase
;
212 #include "md-unwind-support.h"
214 /* Extract any interesting information from the CIE for the translation
215 unit F belongs to. Return a pointer to the byte after the augmentation,
216 or NULL if we encountered an undecipherable augmentation. */
218 static const unsigned char *
219 extract_cie_info (const struct dwarf_cie
*cie
, struct _Unwind_Context
*context
,
220 _Unwind_FrameState
*fs
)
222 const unsigned char *aug
= cie
->augmentation
;
223 const unsigned char *p
= aug
+ strlen ((const char *)aug
) + 1;
224 const unsigned char *ret
= NULL
;
228 /* g++ v2 "eh" has pointer immediately following augmentation string,
229 so it must be handled first. */
230 if (aug
[0] == 'e' && aug
[1] == 'h')
232 fs
->eh_ptr
= read_pointer (p
);
233 p
+= sizeof (void *);
237 /* Immediately following the augmentation are the code and
238 data alignment and return address column. */
239 p
= read_uleb128 (p
, &utmp
);
240 p
= read_sleb128 (p
, &stmp
);
241 if (cie
->version
== 1)
242 fs
->retaddr_column
= *p
++;
245 p
= read_uleb128 (p
, &utmp
);
246 fs
->retaddr_column
= (_Unwind_Word
)utmp
;
248 fs
->lsda_encoding
= DW_EH_PE_omit
;
250 /* If the augmentation starts with 'z', then a uleb128 immediately
251 follows containing the length of the augmentation field following
255 p
= read_uleb128 (p
, &utmp
);
262 /* Iterate over recognized augmentation subsequences. */
265 /* "L" indicates a byte showing how the LSDA pointer is encoded. */
268 fs
->lsda_encoding
= *p
++;
272 /* "R" indicates a byte indicating how FDE addresses are encoded. */
273 else if (aug
[0] == 'R')
275 fs
->fde_encoding
= *p
++;
279 /* "P" indicates a personality routine in the CIE augmentation. */
280 else if (aug
[0] == 'P')
282 _Unwind_Ptr personality
;
284 p
= read_encoded_value (context
, *p
, p
+ 1, &personality
);
285 fs
->personality
= (_Unwind_Personality_Fn
) personality
;
289 /* "S" indicates a signal frame. */
290 else if (aug
[0] == 'S')
292 fs
->signal_frame
= 1;
296 /* Otherwise we have an unknown augmentation string.
297 Bail unless we saw a 'z' prefix. */
302 return ret
? ret
: p
;
305 /* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
306 its caller and decode it into FS. This function also sets the
307 lsda member of CONTEXT, as it is really information
308 about the caller's frame. */
310 static _Unwind_Reason_Code
311 uw_frame_state_for (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
313 const struct dwarf_fde
*fde
;
314 const struct dwarf_cie
*cie
;
315 const unsigned char *aug
;
317 _Unwind_Word
*ra_ptr
;
319 memset (fs
, 0, sizeof (*fs
));
322 fde
= _Unwind_Find_FDE (context
->ra
+ _Unwind_IsSignalFrame (context
) - 1,
326 #ifdef MD_FALLBACK_FRAME_STATE_FOR
327 _Unwind_Reason_Code reason
;
328 /* Couldn't find frame unwind info for this function. Try a
329 target-specific fallback mechanism. This will necessarily
330 not provide a personality routine or LSDA. */
331 reason
= MD_FALLBACK_FRAME_STATE_FOR (context
, fs
);
332 if (reason
!= _URC_END_OF_STACK
)
335 /* The frame was not recognized and handled by the fallback function,
336 but it is not really the end of the stack. Fall through here and
342 if (extract_cie_info (cie
, context
, fs
) == NULL
)
343 /* CIE contained unknown augmentation. */
344 return _URC_FATAL_PHASE1_ERROR
;
346 /* Locate augmentation for the fde. */
347 aug
= (const unsigned char *) fde
+ sizeof (*fde
);
348 aug
+= 2 * size_of_encoded_value (fs
->fde_encoding
);
352 aug
= read_uleb128 (aug
, &i
);
354 if (fs
->lsda_encoding
!= DW_EH_PE_omit
)
358 aug
= read_encoded_value (context
, fs
->lsda_encoding
, aug
, &lsda
);
359 context
->lsda
= (void *) lsda
;
363 /* Check for the end of the stack. This needs to be checked after
364 the MD_FALLBACK_FRAME_STATE_FOR check for signal frames because
365 the contents of context->reg[0] are undefined at a signal frame,
366 and register a0 may appear to be zero. (The return address in
367 context->ra comes from register a4 or a8). */
368 ra_ptr
= context
->reg
[0];
369 if (ra_ptr
&& *ra_ptr
== 0)
370 return _URC_END_OF_STACK
;
372 /* Find the window size from the high bits of the return address. */
374 window_size
= (*ra_ptr
>> 30) * 4;
378 fs
->retaddr_column
= window_size
;
380 return _URC_NO_REASON
;
384 uw_update_context_1 (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
386 struct _Unwind_Context orig_context
= *context
;
387 _Unwind_Word
*sp
, *cfa
, *next_cfa
;
392 cfa
= (_Unwind_Word
*) fs
->signal_regs
[1];
393 next_cfa
= (_Unwind_Word
*) cfa
[-3];
395 for (i
= 0; i
< 4; i
++)
396 context
->reg
[i
] = fs
->signal_regs
+ (i
<< 2);
400 int window_size
= fs
->retaddr_column
>> 2;
402 sp
= (_Unwind_Word
*) orig_context
.sp
;
403 cfa
= (_Unwind_Word
*) orig_context
.cfa
;
404 next_cfa
= (_Unwind_Word
*) cfa
[-3];
406 /* Registers a0-a3 are in the save area below sp. */
407 context
->reg
[0] = sp
- 4;
409 /* Find the extra save area below next_cfa. */
410 for (i
= 1; i
< window_size
; i
++)
411 context
->reg
[i
] = next_cfa
- 4 * (1 + window_size
- i
);
413 /* Remaining registers rotate from previous save areas. */
414 for (i
= window_size
; i
< 4; i
++)
415 context
->reg
[i
] = orig_context
.reg
[i
- window_size
];
419 context
->cfa
= next_cfa
;
421 _Unwind_SetSignalFrame (context
, fs
->signal_frame
);
424 /* CONTEXT describes the unwind state for a frame, and FS describes the FDE
425 of its caller. Update CONTEXT to refer to the caller as well. Note
426 that the lsda member is not updated here, but later in
427 uw_frame_state_for. */
430 uw_update_context (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
432 uw_update_context_1 (context
, fs
);
434 /* Compute the return address now, since the return address column
435 can change from frame to frame. */
436 if (fs
->signal_ra
!= 0)
437 context
->ra
= (void *) fs
->signal_ra
;
439 context
->ra
= (void *) ((_Unwind_GetGR (context
, fs
->retaddr_column
)
440 & XTENSA_RA_FIELD_MASK
) | context
->ra_high_bits
);
444 uw_advance_context (struct _Unwind_Context
*context
, _Unwind_FrameState
*fs
)
446 uw_update_context (context
, fs
);
449 /* Fill in CONTEXT for top-of-stack. The only valid registers at this
450 level will be the return address and the CFA. */
452 #define uw_init_context(CONTEXT) \
455 __builtin_unwind_init (); \
456 uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \
457 __builtin_return_address (0)); \
461 static void __attribute__((noinline
))
462 uw_init_context_1 (struct _Unwind_Context
*context
, void *outer_cfa
,
465 void *ra
= __builtin_return_address (0);
466 void *cfa
= __builtin_dwarf_cfa ();
467 _Unwind_FrameState fs
;
469 memset (context
, 0, sizeof (struct _Unwind_Context
));
472 memset (&fs
, 0, sizeof (fs
));
473 fs
.retaddr_column
= 8;
475 context
->cfa
= outer_cfa
;
476 context
->ra_high_bits
=
477 ((_Unwind_Word
) uw_init_context_1
) & ~XTENSA_RA_FIELD_MASK
;
478 uw_update_context_1 (context
, &fs
);
480 context
->ra
= outer_ra
;
484 /* Install TARGET into CURRENT so that we can return to it. This is a
485 macro because __builtin_eh_return must be invoked in the context of
488 #define uw_install_context(CURRENT, TARGET) \
491 long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
492 void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
493 __builtin_eh_return (offset, handler); \
498 uw_install_context_1 (struct _Unwind_Context
*current
,
499 struct _Unwind_Context
*target
)
503 /* The eh_return insn assumes a window size of 8, so don't bother copying
504 the save areas for registers a8-a15 since they won't be reloaded. */
505 for (i
= 0; i
< 2; ++i
)
507 void *c
= current
->reg
[i
];
508 void *t
= target
->reg
[i
];
510 if (t
&& c
&& t
!= c
)
511 memcpy (c
, t
, 4 * sizeof (_Unwind_Word
));
517 static inline _Unwind_Ptr
518 uw_identify_context (struct _Unwind_Context
*context
)
520 return _Unwind_GetCFA (context
);
524 #include "unwind.inc"
526 #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
527 alias (_Unwind_Backtrace
);
528 alias (_Unwind_DeleteException
);
529 alias (_Unwind_FindEnclosingFunction
);
530 alias (_Unwind_ForcedUnwind
);
531 alias (_Unwind_GetDataRelBase
);
532 alias (_Unwind_GetTextRelBase
);
533 alias (_Unwind_GetCFA
);
534 alias (_Unwind_GetGR
);
535 alias (_Unwind_GetIP
);
536 alias (_Unwind_GetLanguageSpecificData
);
537 alias (_Unwind_GetRegionStart
);
538 alias (_Unwind_RaiseException
);
539 alias (_Unwind_Resume
);
540 alias (_Unwind_Resume_or_Rethrow
);
541 alias (_Unwind_SetGR
);
542 alias (_Unwind_SetIP
);
545 #endif /* !USING_SJLJ_EXCEPTIONS */