138fd1498Szrj /* DWARF2 exception handling and frame unwind runtime interface routines.
238fd1498Szrj Copyright (C) 1997-2018 Free Software Foundation, Inc.
338fd1498Szrj
438fd1498Szrj This file is part of GCC.
538fd1498Szrj
638fd1498Szrj GCC is free software; you can redistribute it and/or modify it
738fd1498Szrj under the terms of the GNU General Public License as published by
838fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj any later version.
1038fd1498Szrj
1138fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT
1238fd1498Szrj ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1338fd1498Szrj or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
1438fd1498Szrj License for more details.
1538fd1498Szrj
1638fd1498Szrj Under Section 7 of GPL version 3, you are granted additional
1738fd1498Szrj permissions described in the GCC Runtime Library Exception, version
1838fd1498Szrj 3.1, as published by the Free Software Foundation.
1938fd1498Szrj
2038fd1498Szrj You should have received a copy of the GNU General Public License and
2138fd1498Szrj a copy of the GCC Runtime Library Exception along with this program;
2238fd1498Szrj see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2338fd1498Szrj <http://www.gnu.org/licenses/>. */
2438fd1498Szrj
2538fd1498Szrj #include "tconfig.h"
2638fd1498Szrj #include "tsystem.h"
2738fd1498Szrj #include "coretypes.h"
2838fd1498Szrj #include "tm.h"
2938fd1498Szrj #include "libgcc_tm.h"
3038fd1498Szrj #include "dwarf2.h"
3138fd1498Szrj #include "unwind.h"
3238fd1498Szrj #ifdef __USING_SJLJ_EXCEPTIONS__
3338fd1498Szrj # define NO_SIZE_OF_ENCODED_VALUE
3438fd1498Szrj #endif
3538fd1498Szrj #include "unwind-pe.h"
3638fd1498Szrj #include "unwind-dw2-fde.h"
3738fd1498Szrj #include "gthr.h"
3838fd1498Szrj #include "unwind-dw2.h"
3938fd1498Szrj
4038fd1498Szrj #ifdef HAVE_SYS_SDT_H
4138fd1498Szrj #include <sys/sdt.h>
4238fd1498Szrj #endif
4338fd1498Szrj
4438fd1498Szrj #ifndef __USING_SJLJ_EXCEPTIONS__
4538fd1498Szrj
4638fd1498Szrj #ifndef __LIBGCC_STACK_GROWS_DOWNWARD__
4738fd1498Szrj #define __LIBGCC_STACK_GROWS_DOWNWARD__ 0
4838fd1498Szrj #else
4938fd1498Szrj #undef __LIBGCC_STACK_GROWS_DOWNWARD__
5038fd1498Szrj #define __LIBGCC_STACK_GROWS_DOWNWARD__ 1
5138fd1498Szrj #endif
5238fd1498Szrj
5338fd1498Szrj /* Dwarf frame registers used for pre gcc 3.0 compiled glibc. */
5438fd1498Szrj #ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
5538fd1498Szrj #define PRE_GCC3_DWARF_FRAME_REGISTERS __LIBGCC_DWARF_FRAME_REGISTERS__
5638fd1498Szrj #endif
5738fd1498Szrj
5838fd1498Szrj /* ??? For the public function interfaces, we tend to gcc_assert that the
5938fd1498Szrj column numbers are in range. For the dwarf2 unwind info this does happen,
6038fd1498Szrj although so far in a case that doesn't actually matter.
6138fd1498Szrj
6238fd1498Szrj See PR49146, in which a call from x86_64 ms abi to x86_64 unix abi stores
6338fd1498Szrj the call-saved xmm registers and annotates them. We havn't bothered
6438fd1498Szrj providing support for the xmm registers for the x86_64 port primarily
6538fd1498Szrj because the 64-bit windows targets don't use dwarf2 unwind, using sjlj or
6638fd1498Szrj SEH instead. Adding the support for unix targets would generally be a
6738fd1498Szrj waste. However, some runtime libraries supplied with ICC do contain such
6838fd1498Szrj an unorthodox transition, as well as the unwind info to match. This loss
6938fd1498Szrj of register restoration doesn't matter in practice, because the exception
7038fd1498Szrj is caught in the native unix abi, where all of the xmm registers are
7138fd1498Szrj call clobbered.
7238fd1498Szrj
7338fd1498Szrj Ideally, we'd record some bit to notice when we're failing to restore some
7438fd1498Szrj register recorded in the unwind info, but to do that we need annotation on
7538fd1498Szrj the unix->ms abi edge, so that we know when the register data may be
7638fd1498Szrj discarded. And since this edge is also within the ICC library, we're
7738fd1498Szrj unlikely to be able to get the new annotation.
7838fd1498Szrj
7938fd1498Szrj Barring a magic solution to restore the ms abi defined 128-bit xmm registers
8038fd1498Szrj (as distictly opposed to the full runtime width) without causing extra
8138fd1498Szrj overhead for normal unix abis, the best solution seems to be to simply
8238fd1498Szrj ignore unwind data for unknown columns. */
8338fd1498Szrj
8438fd1498Szrj #define UNWIND_COLUMN_IN_RANGE(x) \
8538fd1498Szrj __builtin_expect((x) <= __LIBGCC_DWARF_FRAME_REGISTERS__, 1)
8638fd1498Szrj
8738fd1498Szrj #ifdef REG_VALUE_IN_UNWIND_CONTEXT
8838fd1498Szrj typedef _Unwind_Word _Unwind_Context_Reg_Val;
8938fd1498Szrj
9038fd1498Szrj #ifndef ASSUME_EXTENDED_UNWIND_CONTEXT
9138fd1498Szrj #define ASSUME_EXTENDED_UNWIND_CONTEXT 1
9238fd1498Szrj #endif
9338fd1498Szrj
9438fd1498Szrj static inline _Unwind_Word
_Unwind_Get_Unwind_Word(_Unwind_Context_Reg_Val val)9538fd1498Szrj _Unwind_Get_Unwind_Word (_Unwind_Context_Reg_Val val)
9638fd1498Szrj {
9738fd1498Szrj return val;
9838fd1498Szrj }
9938fd1498Szrj
10038fd1498Szrj static inline _Unwind_Context_Reg_Val
_Unwind_Get_Unwind_Context_Reg_Val(_Unwind_Word val)10138fd1498Szrj _Unwind_Get_Unwind_Context_Reg_Val (_Unwind_Word val)
10238fd1498Szrj {
10338fd1498Szrj return val;
10438fd1498Szrj }
10538fd1498Szrj #else
10638fd1498Szrj typedef void *_Unwind_Context_Reg_Val;
10738fd1498Szrj
10838fd1498Szrj static inline _Unwind_Word
_Unwind_Get_Unwind_Word(_Unwind_Context_Reg_Val val)10938fd1498Szrj _Unwind_Get_Unwind_Word (_Unwind_Context_Reg_Val val)
11038fd1498Szrj {
11138fd1498Szrj return (_Unwind_Word) (_Unwind_Internal_Ptr) val;
11238fd1498Szrj }
11338fd1498Szrj
11438fd1498Szrj static inline _Unwind_Context_Reg_Val
_Unwind_Get_Unwind_Context_Reg_Val(_Unwind_Word val)11538fd1498Szrj _Unwind_Get_Unwind_Context_Reg_Val (_Unwind_Word val)
11638fd1498Szrj {
11738fd1498Szrj return (_Unwind_Context_Reg_Val) (_Unwind_Internal_Ptr) val;
11838fd1498Szrj }
11938fd1498Szrj #endif
12038fd1498Szrj
12138fd1498Szrj #ifndef ASSUME_EXTENDED_UNWIND_CONTEXT
12238fd1498Szrj #define ASSUME_EXTENDED_UNWIND_CONTEXT 0
12338fd1498Szrj #endif
12438fd1498Szrj
12538fd1498Szrj /* This is the register and unwind state for a particular frame. This
12638fd1498Szrj provides the information necessary to unwind up past a frame and return
12738fd1498Szrj to its caller. */
12838fd1498Szrj struct _Unwind_Context
12938fd1498Szrj {
13038fd1498Szrj _Unwind_Context_Reg_Val reg[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
13138fd1498Szrj void *cfa;
13238fd1498Szrj void *ra;
13338fd1498Szrj void *lsda;
13438fd1498Szrj struct dwarf_eh_bases bases;
13538fd1498Szrj /* Signal frame context. */
13638fd1498Szrj #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
13738fd1498Szrj /* Context which has version/args_size/by_value fields. */
13838fd1498Szrj #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
13938fd1498Szrj /* Bit reserved on AArch64, return address has been signed with A key. */
14038fd1498Szrj #define RA_A_SIGNED_BIT ((~(_Unwind_Word) 0 >> 3) + 1)
14138fd1498Szrj _Unwind_Word flags;
14238fd1498Szrj /* 0 for now, can be increased when further fields are added to
14338fd1498Szrj struct _Unwind_Context. */
14438fd1498Szrj _Unwind_Word version;
14538fd1498Szrj _Unwind_Word args_size;
14638fd1498Szrj char by_value[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
14738fd1498Szrj };
14838fd1498Szrj
14938fd1498Szrj /* Byte size of every register managed by these routines. */
15038fd1498Szrj static unsigned char dwarf_reg_size_table[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
15138fd1498Szrj
15238fd1498Szrj
15338fd1498Szrj /* Read unaligned data from the instruction buffer. */
15438fd1498Szrj
15538fd1498Szrj union unaligned
15638fd1498Szrj {
15738fd1498Szrj void *p;
15838fd1498Szrj unsigned u2 __attribute__ ((mode (HI)));
15938fd1498Szrj unsigned u4 __attribute__ ((mode (SI)));
16038fd1498Szrj unsigned u8 __attribute__ ((mode (DI)));
16138fd1498Szrj signed s2 __attribute__ ((mode (HI)));
16238fd1498Szrj signed s4 __attribute__ ((mode (SI)));
16338fd1498Szrj signed s8 __attribute__ ((mode (DI)));
16438fd1498Szrj } __attribute__ ((packed));
16538fd1498Szrj
16638fd1498Szrj static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
16738fd1498Szrj static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
16838fd1498Szrj _Unwind_FrameState *);
16938fd1498Szrj
17038fd1498Szrj static inline void *
read_pointer(const void * p)17138fd1498Szrj read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
17238fd1498Szrj
17338fd1498Szrj static inline int
read_1u(const void * p)17438fd1498Szrj read_1u (const void *p) { return *(const unsigned char *) p; }
17538fd1498Szrj
17638fd1498Szrj static inline int
read_1s(const void * p)17738fd1498Szrj read_1s (const void *p) { return *(const signed char *) p; }
17838fd1498Szrj
17938fd1498Szrj static inline int
read_2u(const void * p)18038fd1498Szrj read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
18138fd1498Szrj
18238fd1498Szrj static inline int
read_2s(const void * p)18338fd1498Szrj read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
18438fd1498Szrj
18538fd1498Szrj static inline unsigned int
read_4u(const void * p)18638fd1498Szrj read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
18738fd1498Szrj
18838fd1498Szrj static inline int
read_4s(const void * p)18938fd1498Szrj read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
19038fd1498Szrj
19138fd1498Szrj static inline unsigned long
read_8u(const void * p)19238fd1498Szrj read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
19338fd1498Szrj
19438fd1498Szrj static inline unsigned long
read_8s(const void * p)19538fd1498Szrj read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
19638fd1498Szrj
19738fd1498Szrj static inline _Unwind_Word
_Unwind_IsSignalFrame(struct _Unwind_Context * context)19838fd1498Szrj _Unwind_IsSignalFrame (struct _Unwind_Context *context)
19938fd1498Szrj {
20038fd1498Szrj return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
20138fd1498Szrj }
20238fd1498Szrj
20338fd1498Szrj static inline void
_Unwind_SetSignalFrame(struct _Unwind_Context * context,int val)20438fd1498Szrj _Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
20538fd1498Szrj {
20638fd1498Szrj if (val)
20738fd1498Szrj context->flags |= SIGNAL_FRAME_BIT;
20838fd1498Szrj else
20938fd1498Szrj context->flags &= ~SIGNAL_FRAME_BIT;
21038fd1498Szrj }
21138fd1498Szrj
21238fd1498Szrj static inline _Unwind_Word
_Unwind_IsExtendedContext(struct _Unwind_Context * context)21338fd1498Szrj _Unwind_IsExtendedContext (struct _Unwind_Context *context)
21438fd1498Szrj {
21538fd1498Szrj return (ASSUME_EXTENDED_UNWIND_CONTEXT
21638fd1498Szrj || (context->flags & EXTENDED_CONTEXT_BIT));
21738fd1498Szrj }
21838fd1498Szrj
21938fd1498Szrj /* Get the value of register REGNO as saved in CONTEXT. */
22038fd1498Szrj
22138fd1498Szrj inline _Unwind_Word
_Unwind_GetGR(struct _Unwind_Context * context,int regno)22238fd1498Szrj _Unwind_GetGR (struct _Unwind_Context *context, int regno)
22338fd1498Szrj {
22438fd1498Szrj int size, index;
22538fd1498Szrj _Unwind_Context_Reg_Val val;
22638fd1498Szrj
22738fd1498Szrj #ifdef DWARF_ZERO_REG
228*58e805e6Szrj if (regno == DWARF_ZERO_REG)
22938fd1498Szrj return 0;
23038fd1498Szrj #endif
23138fd1498Szrj
23238fd1498Szrj index = DWARF_REG_TO_UNWIND_COLUMN (regno);
23338fd1498Szrj gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
23438fd1498Szrj size = dwarf_reg_size_table[index];
23538fd1498Szrj val = context->reg[index];
23638fd1498Szrj
23738fd1498Szrj if (_Unwind_IsExtendedContext (context) && context->by_value[index])
23838fd1498Szrj return _Unwind_Get_Unwind_Word (val);
23938fd1498Szrj
24038fd1498Szrj #ifdef DWARF_LAZY_REGISTER_VALUE
24138fd1498Szrj {
24238fd1498Szrj _Unwind_Word value;
24338fd1498Szrj if (DWARF_LAZY_REGISTER_VALUE (regno, &value))
24438fd1498Szrj return value;
24538fd1498Szrj }
24638fd1498Szrj #endif
24738fd1498Szrj
24838fd1498Szrj /* This will segfault if the register hasn't been saved. */
24938fd1498Szrj if (size == sizeof(_Unwind_Ptr))
25038fd1498Szrj return * (_Unwind_Ptr *) (_Unwind_Internal_Ptr) val;
25138fd1498Szrj else
25238fd1498Szrj {
25338fd1498Szrj gcc_assert (size == sizeof(_Unwind_Word));
25438fd1498Szrj return * (_Unwind_Word *) (_Unwind_Internal_Ptr) val;
25538fd1498Szrj }
25638fd1498Szrj }
25738fd1498Szrj
25838fd1498Szrj static inline void *
_Unwind_GetPtr(struct _Unwind_Context * context,int index)25938fd1498Szrj _Unwind_GetPtr (struct _Unwind_Context *context, int index)
26038fd1498Szrj {
26138fd1498Szrj return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index);
26238fd1498Szrj }
26338fd1498Szrj
26438fd1498Szrj /* Get the value of the CFA as saved in CONTEXT. */
26538fd1498Szrj
26638fd1498Szrj _Unwind_Word
_Unwind_GetCFA(struct _Unwind_Context * context)26738fd1498Szrj _Unwind_GetCFA (struct _Unwind_Context *context)
26838fd1498Szrj {
26938fd1498Szrj return (_Unwind_Ptr) context->cfa;
27038fd1498Szrj }
27138fd1498Szrj
27238fd1498Szrj /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */
27338fd1498Szrj
27438fd1498Szrj inline void
_Unwind_SetGR(struct _Unwind_Context * context,int index,_Unwind_Word val)27538fd1498Szrj _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
27638fd1498Szrj {
27738fd1498Szrj int size;
27838fd1498Szrj void *ptr;
27938fd1498Szrj
28038fd1498Szrj index = DWARF_REG_TO_UNWIND_COLUMN (index);
28138fd1498Szrj gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
28238fd1498Szrj size = dwarf_reg_size_table[index];
28338fd1498Szrj
28438fd1498Szrj if (_Unwind_IsExtendedContext (context) && context->by_value[index])
28538fd1498Szrj {
28638fd1498Szrj context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val);
28738fd1498Szrj return;
28838fd1498Szrj }
28938fd1498Szrj
29038fd1498Szrj ptr = (void *) (_Unwind_Internal_Ptr) context->reg[index];
29138fd1498Szrj
29238fd1498Szrj if (size == sizeof(_Unwind_Ptr))
29338fd1498Szrj * (_Unwind_Ptr *) ptr = val;
29438fd1498Szrj else
29538fd1498Szrj {
29638fd1498Szrj gcc_assert (size == sizeof(_Unwind_Word));
29738fd1498Szrj * (_Unwind_Word *) ptr = val;
29838fd1498Szrj }
29938fd1498Szrj }
30038fd1498Szrj
30138fd1498Szrj /* Get the pointer to a register INDEX as saved in CONTEXT. */
30238fd1498Szrj
30338fd1498Szrj static inline void *
_Unwind_GetGRPtr(struct _Unwind_Context * context,int index)30438fd1498Szrj _Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
30538fd1498Szrj {
30638fd1498Szrj index = DWARF_REG_TO_UNWIND_COLUMN (index);
30738fd1498Szrj if (_Unwind_IsExtendedContext (context) && context->by_value[index])
30838fd1498Szrj return &context->reg[index];
30938fd1498Szrj return (void *) (_Unwind_Internal_Ptr) context->reg[index];
31038fd1498Szrj }
31138fd1498Szrj
31238fd1498Szrj /* Set the pointer to a register INDEX as saved in CONTEXT. */
31338fd1498Szrj
31438fd1498Szrj static inline void
_Unwind_SetGRPtr(struct _Unwind_Context * context,int index,void * p)31538fd1498Szrj _Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
31638fd1498Szrj {
31738fd1498Szrj index = DWARF_REG_TO_UNWIND_COLUMN (index);
31838fd1498Szrj if (_Unwind_IsExtendedContext (context))
31938fd1498Szrj context->by_value[index] = 0;
32038fd1498Szrj context->reg[index] = (_Unwind_Context_Reg_Val) (_Unwind_Internal_Ptr) p;
32138fd1498Szrj }
32238fd1498Szrj
32338fd1498Szrj /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */
32438fd1498Szrj
32538fd1498Szrj static inline void
_Unwind_SetGRValue(struct _Unwind_Context * context,int index,_Unwind_Word val)32638fd1498Szrj _Unwind_SetGRValue (struct _Unwind_Context *context, int index,
32738fd1498Szrj _Unwind_Word val)
32838fd1498Szrj {
32938fd1498Szrj index = DWARF_REG_TO_UNWIND_COLUMN (index);
33038fd1498Szrj gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
33138fd1498Szrj /* Return column size may be smaller than _Unwind_Context_Reg_Val. */
33238fd1498Szrj gcc_assert (dwarf_reg_size_table[index] <= sizeof (_Unwind_Context_Reg_Val));
33338fd1498Szrj
33438fd1498Szrj context->by_value[index] = 1;
33538fd1498Szrj context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val);
33638fd1498Szrj }
33738fd1498Szrj
33838fd1498Szrj /* Return nonzero if register INDEX is stored by value rather than
33938fd1498Szrj by reference. */
34038fd1498Szrj
34138fd1498Szrj static inline int
_Unwind_GRByValue(struct _Unwind_Context * context,int index)34238fd1498Szrj _Unwind_GRByValue (struct _Unwind_Context *context, int index)
34338fd1498Szrj {
34438fd1498Szrj index = DWARF_REG_TO_UNWIND_COLUMN (index);
34538fd1498Szrj return context->by_value[index];
34638fd1498Szrj }
34738fd1498Szrj
34838fd1498Szrj /* Retrieve the return address for CONTEXT. */
34938fd1498Szrj
35038fd1498Szrj inline _Unwind_Ptr
_Unwind_GetIP(struct _Unwind_Context * context)35138fd1498Szrj _Unwind_GetIP (struct _Unwind_Context *context)
35238fd1498Szrj {
35338fd1498Szrj return (_Unwind_Ptr) context->ra;
35438fd1498Szrj }
35538fd1498Szrj
35638fd1498Szrj /* Retrieve the return address and flag whether that IP is before
35738fd1498Szrj or after first not yet fully executed instruction. */
35838fd1498Szrj
35938fd1498Szrj inline _Unwind_Ptr
_Unwind_GetIPInfo(struct _Unwind_Context * context,int * ip_before_insn)36038fd1498Szrj _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
36138fd1498Szrj {
36238fd1498Szrj *ip_before_insn = _Unwind_IsSignalFrame (context);
36338fd1498Szrj return (_Unwind_Ptr) context->ra;
36438fd1498Szrj }
36538fd1498Szrj
36638fd1498Szrj /* Overwrite the return address for CONTEXT with VAL. */
36738fd1498Szrj
36838fd1498Szrj inline void
_Unwind_SetIP(struct _Unwind_Context * context,_Unwind_Ptr val)36938fd1498Szrj _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
37038fd1498Szrj {
37138fd1498Szrj context->ra = (void *) val;
37238fd1498Szrj }
37338fd1498Szrj
37438fd1498Szrj void *
_Unwind_GetLanguageSpecificData(struct _Unwind_Context * context)37538fd1498Szrj _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
37638fd1498Szrj {
37738fd1498Szrj return context->lsda;
37838fd1498Szrj }
37938fd1498Szrj
38038fd1498Szrj _Unwind_Ptr
_Unwind_GetRegionStart(struct _Unwind_Context * context)38138fd1498Szrj _Unwind_GetRegionStart (struct _Unwind_Context *context)
38238fd1498Szrj {
38338fd1498Szrj return (_Unwind_Ptr) context->bases.func;
38438fd1498Szrj }
38538fd1498Szrj
38638fd1498Szrj void *
_Unwind_FindEnclosingFunction(void * pc)38738fd1498Szrj _Unwind_FindEnclosingFunction (void *pc)
38838fd1498Szrj {
38938fd1498Szrj struct dwarf_eh_bases bases;
39038fd1498Szrj const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
39138fd1498Szrj if (fde)
39238fd1498Szrj return bases.func;
39338fd1498Szrj else
39438fd1498Szrj return NULL;
39538fd1498Szrj }
39638fd1498Szrj
39738fd1498Szrj #ifndef __ia64__
39838fd1498Szrj _Unwind_Ptr
_Unwind_GetDataRelBase(struct _Unwind_Context * context)39938fd1498Szrj _Unwind_GetDataRelBase (struct _Unwind_Context *context)
40038fd1498Szrj {
40138fd1498Szrj return (_Unwind_Ptr) context->bases.dbase;
40238fd1498Szrj }
40338fd1498Szrj
40438fd1498Szrj _Unwind_Ptr
_Unwind_GetTextRelBase(struct _Unwind_Context * context)40538fd1498Szrj _Unwind_GetTextRelBase (struct _Unwind_Context *context)
40638fd1498Szrj {
40738fd1498Szrj return (_Unwind_Ptr) context->bases.tbase;
40838fd1498Szrj }
40938fd1498Szrj #endif
41038fd1498Szrj
41138fd1498Szrj #include "md-unwind-support.h"
41238fd1498Szrj
41338fd1498Szrj /* Extract any interesting information from the CIE for the translation
41438fd1498Szrj unit F belongs to. Return a pointer to the byte after the augmentation,
41538fd1498Szrj or NULL if we encountered an undecipherable augmentation. */
41638fd1498Szrj
41738fd1498Szrj static const unsigned char *
extract_cie_info(const struct dwarf_cie * cie,struct _Unwind_Context * context,_Unwind_FrameState * fs)41838fd1498Szrj extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
41938fd1498Szrj _Unwind_FrameState *fs)
42038fd1498Szrj {
42138fd1498Szrj const unsigned char *aug = cie->augmentation;
42238fd1498Szrj const unsigned char *p = aug + strlen ((const char *)aug) + 1;
42338fd1498Szrj const unsigned char *ret = NULL;
42438fd1498Szrj _uleb128_t utmp;
42538fd1498Szrj _sleb128_t stmp;
42638fd1498Szrj
42738fd1498Szrj /* g++ v2 "eh" has pointer immediately following augmentation string,
42838fd1498Szrj so it must be handled first. */
42938fd1498Szrj if (aug[0] == 'e' && aug[1] == 'h')
43038fd1498Szrj {
43138fd1498Szrj fs->eh_ptr = read_pointer (p);
43238fd1498Szrj p += sizeof (void *);
43338fd1498Szrj aug += 2;
43438fd1498Szrj }
43538fd1498Szrj
43638fd1498Szrj /* After the augmentation resp. pointer for "eh" augmentation
43738fd1498Szrj follows for CIE version >= 4 address size byte and
43838fd1498Szrj segment size byte. */
43938fd1498Szrj if (__builtin_expect (cie->version >= 4, 0))
44038fd1498Szrj {
44138fd1498Szrj if (p[0] != sizeof (void *) || p[1] != 0)
44238fd1498Szrj return NULL;
44338fd1498Szrj p += 2;
44438fd1498Szrj }
44538fd1498Szrj /* Immediately following this are the code and
44638fd1498Szrj data alignment and return address column. */
44738fd1498Szrj p = read_uleb128 (p, &utmp);
44838fd1498Szrj fs->code_align = (_Unwind_Word)utmp;
44938fd1498Szrj p = read_sleb128 (p, &stmp);
45038fd1498Szrj fs->data_align = (_Unwind_Sword)stmp;
45138fd1498Szrj if (cie->version == 1)
45238fd1498Szrj fs->retaddr_column = *p++;
45338fd1498Szrj else
45438fd1498Szrj {
45538fd1498Szrj p = read_uleb128 (p, &utmp);
45638fd1498Szrj fs->retaddr_column = (_Unwind_Word)utmp;
45738fd1498Szrj }
45838fd1498Szrj fs->lsda_encoding = DW_EH_PE_omit;
45938fd1498Szrj
46038fd1498Szrj /* If the augmentation starts with 'z', then a uleb128 immediately
46138fd1498Szrj follows containing the length of the augmentation field following
46238fd1498Szrj the size. */
46338fd1498Szrj if (*aug == 'z')
46438fd1498Szrj {
46538fd1498Szrj p = read_uleb128 (p, &utmp);
46638fd1498Szrj ret = p + utmp;
46738fd1498Szrj
46838fd1498Szrj fs->saw_z = 1;
46938fd1498Szrj ++aug;
47038fd1498Szrj }
47138fd1498Szrj
47238fd1498Szrj /* Iterate over recognized augmentation subsequences. */
47338fd1498Szrj while (*aug != '\0')
47438fd1498Szrj {
47538fd1498Szrj /* "L" indicates a byte showing how the LSDA pointer is encoded. */
47638fd1498Szrj if (aug[0] == 'L')
47738fd1498Szrj {
47838fd1498Szrj fs->lsda_encoding = *p++;
47938fd1498Szrj aug += 1;
48038fd1498Szrj }
48138fd1498Szrj
48238fd1498Szrj /* "R" indicates a byte indicating how FDE addresses are encoded. */
48338fd1498Szrj else if (aug[0] == 'R')
48438fd1498Szrj {
48538fd1498Szrj fs->fde_encoding = *p++;
48638fd1498Szrj aug += 1;
48738fd1498Szrj }
48838fd1498Szrj
48938fd1498Szrj /* "P" indicates a personality routine in the CIE augmentation. */
49038fd1498Szrj else if (aug[0] == 'P')
49138fd1498Szrj {
49238fd1498Szrj _Unwind_Ptr personality;
49338fd1498Szrj
49438fd1498Szrj p = read_encoded_value (context, *p, p + 1, &personality);
49538fd1498Szrj fs->personality = (_Unwind_Personality_Fn) personality;
49638fd1498Szrj aug += 1;
49738fd1498Szrj }
49838fd1498Szrj
49938fd1498Szrj /* "S" indicates a signal frame. */
50038fd1498Szrj else if (aug[0] == 'S')
50138fd1498Szrj {
50238fd1498Szrj fs->signal_frame = 1;
50338fd1498Szrj aug += 1;
50438fd1498Szrj }
50538fd1498Szrj
50638fd1498Szrj /* Otherwise we have an unknown augmentation string.
50738fd1498Szrj Bail unless we saw a 'z' prefix. */
50838fd1498Szrj else
50938fd1498Szrj return ret;
51038fd1498Szrj }
51138fd1498Szrj
51238fd1498Szrj return ret ? ret : p;
51338fd1498Szrj }
51438fd1498Szrj
51538fd1498Szrj
51638fd1498Szrj /* Decode a DW_OP stack program. Return the top of stack. Push INITIAL
51738fd1498Szrj onto the stack to start. */
51838fd1498Szrj
51938fd1498Szrj static _Unwind_Word
execute_stack_op(const unsigned char * op_ptr,const unsigned char * op_end,struct _Unwind_Context * context,_Unwind_Word initial)52038fd1498Szrj execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
52138fd1498Szrj struct _Unwind_Context *context, _Unwind_Word initial)
52238fd1498Szrj {
52338fd1498Szrj _Unwind_Word stack[64]; /* ??? Assume this is enough. */
52438fd1498Szrj int stack_elt;
52538fd1498Szrj
52638fd1498Szrj stack[0] = initial;
52738fd1498Szrj stack_elt = 1;
52838fd1498Szrj
52938fd1498Szrj while (op_ptr < op_end)
53038fd1498Szrj {
53138fd1498Szrj enum dwarf_location_atom op = *op_ptr++;
53238fd1498Szrj _Unwind_Word result;
53338fd1498Szrj _uleb128_t reg, utmp;
53438fd1498Szrj _sleb128_t offset, stmp;
53538fd1498Szrj
53638fd1498Szrj switch (op)
53738fd1498Szrj {
53838fd1498Szrj case DW_OP_lit0:
53938fd1498Szrj case DW_OP_lit1:
54038fd1498Szrj case DW_OP_lit2:
54138fd1498Szrj case DW_OP_lit3:
54238fd1498Szrj case DW_OP_lit4:
54338fd1498Szrj case DW_OP_lit5:
54438fd1498Szrj case DW_OP_lit6:
54538fd1498Szrj case DW_OP_lit7:
54638fd1498Szrj case DW_OP_lit8:
54738fd1498Szrj case DW_OP_lit9:
54838fd1498Szrj case DW_OP_lit10:
54938fd1498Szrj case DW_OP_lit11:
55038fd1498Szrj case DW_OP_lit12:
55138fd1498Szrj case DW_OP_lit13:
55238fd1498Szrj case DW_OP_lit14:
55338fd1498Szrj case DW_OP_lit15:
55438fd1498Szrj case DW_OP_lit16:
55538fd1498Szrj case DW_OP_lit17:
55638fd1498Szrj case DW_OP_lit18:
55738fd1498Szrj case DW_OP_lit19:
55838fd1498Szrj case DW_OP_lit20:
55938fd1498Szrj case DW_OP_lit21:
56038fd1498Szrj case DW_OP_lit22:
56138fd1498Szrj case DW_OP_lit23:
56238fd1498Szrj case DW_OP_lit24:
56338fd1498Szrj case DW_OP_lit25:
56438fd1498Szrj case DW_OP_lit26:
56538fd1498Szrj case DW_OP_lit27:
56638fd1498Szrj case DW_OP_lit28:
56738fd1498Szrj case DW_OP_lit29:
56838fd1498Szrj case DW_OP_lit30:
56938fd1498Szrj case DW_OP_lit31:
57038fd1498Szrj result = op - DW_OP_lit0;
57138fd1498Szrj break;
57238fd1498Szrj
57338fd1498Szrj case DW_OP_addr:
57438fd1498Szrj result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
57538fd1498Szrj op_ptr += sizeof (void *);
57638fd1498Szrj break;
57738fd1498Szrj
57838fd1498Szrj case DW_OP_GNU_encoded_addr:
57938fd1498Szrj {
58038fd1498Szrj _Unwind_Ptr presult;
58138fd1498Szrj op_ptr = read_encoded_value (context, *op_ptr, op_ptr+1, &presult);
58238fd1498Szrj result = presult;
58338fd1498Szrj }
58438fd1498Szrj break;
58538fd1498Szrj
58638fd1498Szrj case DW_OP_const1u:
58738fd1498Szrj result = read_1u (op_ptr);
58838fd1498Szrj op_ptr += 1;
58938fd1498Szrj break;
59038fd1498Szrj case DW_OP_const1s:
59138fd1498Szrj result = read_1s (op_ptr);
59238fd1498Szrj op_ptr += 1;
59338fd1498Szrj break;
59438fd1498Szrj case DW_OP_const2u:
59538fd1498Szrj result = read_2u (op_ptr);
59638fd1498Szrj op_ptr += 2;
59738fd1498Szrj break;
59838fd1498Szrj case DW_OP_const2s:
59938fd1498Szrj result = read_2s (op_ptr);
60038fd1498Szrj op_ptr += 2;
60138fd1498Szrj break;
60238fd1498Szrj case DW_OP_const4u:
60338fd1498Szrj result = read_4u (op_ptr);
60438fd1498Szrj op_ptr += 4;
60538fd1498Szrj break;
60638fd1498Szrj case DW_OP_const4s:
60738fd1498Szrj result = read_4s (op_ptr);
60838fd1498Szrj op_ptr += 4;
60938fd1498Szrj break;
61038fd1498Szrj case DW_OP_const8u:
61138fd1498Szrj result = read_8u (op_ptr);
61238fd1498Szrj op_ptr += 8;
61338fd1498Szrj break;
61438fd1498Szrj case DW_OP_const8s:
61538fd1498Szrj result = read_8s (op_ptr);
61638fd1498Szrj op_ptr += 8;
61738fd1498Szrj break;
61838fd1498Szrj case DW_OP_constu:
61938fd1498Szrj op_ptr = read_uleb128 (op_ptr, &utmp);
62038fd1498Szrj result = (_Unwind_Word)utmp;
62138fd1498Szrj break;
62238fd1498Szrj case DW_OP_consts:
62338fd1498Szrj op_ptr = read_sleb128 (op_ptr, &stmp);
62438fd1498Szrj result = (_Unwind_Sword)stmp;
62538fd1498Szrj break;
62638fd1498Szrj
62738fd1498Szrj case DW_OP_reg0:
62838fd1498Szrj case DW_OP_reg1:
62938fd1498Szrj case DW_OP_reg2:
63038fd1498Szrj case DW_OP_reg3:
63138fd1498Szrj case DW_OP_reg4:
63238fd1498Szrj case DW_OP_reg5:
63338fd1498Szrj case DW_OP_reg6:
63438fd1498Szrj case DW_OP_reg7:
63538fd1498Szrj case DW_OP_reg8:
63638fd1498Szrj case DW_OP_reg9:
63738fd1498Szrj case DW_OP_reg10:
63838fd1498Szrj case DW_OP_reg11:
63938fd1498Szrj case DW_OP_reg12:
64038fd1498Szrj case DW_OP_reg13:
64138fd1498Szrj case DW_OP_reg14:
64238fd1498Szrj case DW_OP_reg15:
64338fd1498Szrj case DW_OP_reg16:
64438fd1498Szrj case DW_OP_reg17:
64538fd1498Szrj case DW_OP_reg18:
64638fd1498Szrj case DW_OP_reg19:
64738fd1498Szrj case DW_OP_reg20:
64838fd1498Szrj case DW_OP_reg21:
64938fd1498Szrj case DW_OP_reg22:
65038fd1498Szrj case DW_OP_reg23:
65138fd1498Szrj case DW_OP_reg24:
65238fd1498Szrj case DW_OP_reg25:
65338fd1498Szrj case DW_OP_reg26:
65438fd1498Szrj case DW_OP_reg27:
65538fd1498Szrj case DW_OP_reg28:
65638fd1498Szrj case DW_OP_reg29:
65738fd1498Szrj case DW_OP_reg30:
65838fd1498Szrj case DW_OP_reg31:
65938fd1498Szrj result = _Unwind_GetGR (context, op - DW_OP_reg0);
66038fd1498Szrj break;
66138fd1498Szrj case DW_OP_regx:
66238fd1498Szrj op_ptr = read_uleb128 (op_ptr, ®);
66338fd1498Szrj result = _Unwind_GetGR (context, reg);
66438fd1498Szrj break;
66538fd1498Szrj
66638fd1498Szrj case DW_OP_breg0:
66738fd1498Szrj case DW_OP_breg1:
66838fd1498Szrj case DW_OP_breg2:
66938fd1498Szrj case DW_OP_breg3:
67038fd1498Szrj case DW_OP_breg4:
67138fd1498Szrj case DW_OP_breg5:
67238fd1498Szrj case DW_OP_breg6:
67338fd1498Szrj case DW_OP_breg7:
67438fd1498Szrj case DW_OP_breg8:
67538fd1498Szrj case DW_OP_breg9:
67638fd1498Szrj case DW_OP_breg10:
67738fd1498Szrj case DW_OP_breg11:
67838fd1498Szrj case DW_OP_breg12:
67938fd1498Szrj case DW_OP_breg13:
68038fd1498Szrj case DW_OP_breg14:
68138fd1498Szrj case DW_OP_breg15:
68238fd1498Szrj case DW_OP_breg16:
68338fd1498Szrj case DW_OP_breg17:
68438fd1498Szrj case DW_OP_breg18:
68538fd1498Szrj case DW_OP_breg19:
68638fd1498Szrj case DW_OP_breg20:
68738fd1498Szrj case DW_OP_breg21:
68838fd1498Szrj case DW_OP_breg22:
68938fd1498Szrj case DW_OP_breg23:
69038fd1498Szrj case DW_OP_breg24:
69138fd1498Szrj case DW_OP_breg25:
69238fd1498Szrj case DW_OP_breg26:
69338fd1498Szrj case DW_OP_breg27:
69438fd1498Szrj case DW_OP_breg28:
69538fd1498Szrj case DW_OP_breg29:
69638fd1498Szrj case DW_OP_breg30:
69738fd1498Szrj case DW_OP_breg31:
69838fd1498Szrj op_ptr = read_sleb128 (op_ptr, &offset);
69938fd1498Szrj result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
70038fd1498Szrj break;
70138fd1498Szrj case DW_OP_bregx:
70238fd1498Szrj op_ptr = read_uleb128 (op_ptr, ®);
70338fd1498Szrj op_ptr = read_sleb128 (op_ptr, &offset);
70438fd1498Szrj result = _Unwind_GetGR (context, reg) + (_Unwind_Word)offset;
70538fd1498Szrj break;
70638fd1498Szrj
70738fd1498Szrj case DW_OP_dup:
70838fd1498Szrj gcc_assert (stack_elt);
70938fd1498Szrj result = stack[stack_elt - 1];
71038fd1498Szrj break;
71138fd1498Szrj
71238fd1498Szrj case DW_OP_drop:
71338fd1498Szrj gcc_assert (stack_elt);
71438fd1498Szrj stack_elt -= 1;
71538fd1498Szrj goto no_push;
71638fd1498Szrj
71738fd1498Szrj case DW_OP_pick:
71838fd1498Szrj offset = *op_ptr++;
71938fd1498Szrj gcc_assert (offset < stack_elt - 1);
72038fd1498Szrj result = stack[stack_elt - 1 - offset];
72138fd1498Szrj break;
72238fd1498Szrj
72338fd1498Szrj case DW_OP_over:
72438fd1498Szrj gcc_assert (stack_elt >= 2);
72538fd1498Szrj result = stack[stack_elt - 2];
72638fd1498Szrj break;
72738fd1498Szrj
72838fd1498Szrj case DW_OP_swap:
72938fd1498Szrj {
73038fd1498Szrj _Unwind_Word t;
73138fd1498Szrj gcc_assert (stack_elt >= 2);
73238fd1498Szrj t = stack[stack_elt - 1];
73338fd1498Szrj stack[stack_elt - 1] = stack[stack_elt - 2];
73438fd1498Szrj stack[stack_elt - 2] = t;
73538fd1498Szrj goto no_push;
73638fd1498Szrj }
73738fd1498Szrj
73838fd1498Szrj case DW_OP_rot:
73938fd1498Szrj {
74038fd1498Szrj _Unwind_Word t1, t2, t3;
74138fd1498Szrj
74238fd1498Szrj gcc_assert (stack_elt >= 3);
74338fd1498Szrj t1 = stack[stack_elt - 1];
74438fd1498Szrj t2 = stack[stack_elt - 2];
74538fd1498Szrj t3 = stack[stack_elt - 3];
74638fd1498Szrj stack[stack_elt - 1] = t2;
74738fd1498Szrj stack[stack_elt - 2] = t3;
74838fd1498Szrj stack[stack_elt - 3] = t1;
74938fd1498Szrj goto no_push;
75038fd1498Szrj }
75138fd1498Szrj
75238fd1498Szrj case DW_OP_deref:
75338fd1498Szrj case DW_OP_deref_size:
75438fd1498Szrj case DW_OP_abs:
75538fd1498Szrj case DW_OP_neg:
75638fd1498Szrj case DW_OP_not:
75738fd1498Szrj case DW_OP_plus_uconst:
75838fd1498Szrj /* Unary operations. */
75938fd1498Szrj gcc_assert (stack_elt);
76038fd1498Szrj stack_elt -= 1;
76138fd1498Szrj
76238fd1498Szrj result = stack[stack_elt];
76338fd1498Szrj
76438fd1498Szrj switch (op)
76538fd1498Szrj {
76638fd1498Szrj case DW_OP_deref:
76738fd1498Szrj {
76838fd1498Szrj void *ptr = (void *) (_Unwind_Ptr) result;
76938fd1498Szrj result = (_Unwind_Ptr) read_pointer (ptr);
77038fd1498Szrj }
77138fd1498Szrj break;
77238fd1498Szrj
77338fd1498Szrj case DW_OP_deref_size:
77438fd1498Szrj {
77538fd1498Szrj void *ptr = (void *) (_Unwind_Ptr) result;
77638fd1498Szrj switch (*op_ptr++)
77738fd1498Szrj {
77838fd1498Szrj case 1:
77938fd1498Szrj result = read_1u (ptr);
78038fd1498Szrj break;
78138fd1498Szrj case 2:
78238fd1498Szrj result = read_2u (ptr);
78338fd1498Szrj break;
78438fd1498Szrj case 4:
78538fd1498Szrj result = read_4u (ptr);
78638fd1498Szrj break;
78738fd1498Szrj case 8:
78838fd1498Szrj result = read_8u (ptr);
78938fd1498Szrj break;
79038fd1498Szrj default:
79138fd1498Szrj gcc_unreachable ();
79238fd1498Szrj }
79338fd1498Szrj }
79438fd1498Szrj break;
79538fd1498Szrj
79638fd1498Szrj case DW_OP_abs:
79738fd1498Szrj if ((_Unwind_Sword) result < 0)
79838fd1498Szrj result = -result;
79938fd1498Szrj break;
80038fd1498Szrj case DW_OP_neg:
80138fd1498Szrj result = -result;
80238fd1498Szrj break;
80338fd1498Szrj case DW_OP_not:
80438fd1498Szrj result = ~result;
80538fd1498Szrj break;
80638fd1498Szrj case DW_OP_plus_uconst:
80738fd1498Szrj op_ptr = read_uleb128 (op_ptr, &utmp);
80838fd1498Szrj result += (_Unwind_Word)utmp;
80938fd1498Szrj break;
81038fd1498Szrj
81138fd1498Szrj default:
81238fd1498Szrj gcc_unreachable ();
81338fd1498Szrj }
81438fd1498Szrj break;
81538fd1498Szrj
81638fd1498Szrj case DW_OP_and:
81738fd1498Szrj case DW_OP_div:
81838fd1498Szrj case DW_OP_minus:
81938fd1498Szrj case DW_OP_mod:
82038fd1498Szrj case DW_OP_mul:
82138fd1498Szrj case DW_OP_or:
82238fd1498Szrj case DW_OP_plus:
82338fd1498Szrj case DW_OP_shl:
82438fd1498Szrj case DW_OP_shr:
82538fd1498Szrj case DW_OP_shra:
82638fd1498Szrj case DW_OP_xor:
82738fd1498Szrj case DW_OP_le:
82838fd1498Szrj case DW_OP_ge:
82938fd1498Szrj case DW_OP_eq:
83038fd1498Szrj case DW_OP_lt:
83138fd1498Szrj case DW_OP_gt:
83238fd1498Szrj case DW_OP_ne:
83338fd1498Szrj {
83438fd1498Szrj /* Binary operations. */
83538fd1498Szrj _Unwind_Word first, second;
83638fd1498Szrj gcc_assert (stack_elt >= 2);
83738fd1498Szrj stack_elt -= 2;
83838fd1498Szrj
83938fd1498Szrj second = stack[stack_elt];
84038fd1498Szrj first = stack[stack_elt + 1];
84138fd1498Szrj
84238fd1498Szrj switch (op)
84338fd1498Szrj {
84438fd1498Szrj case DW_OP_and:
84538fd1498Szrj result = second & first;
84638fd1498Szrj break;
84738fd1498Szrj case DW_OP_div:
84838fd1498Szrj result = (_Unwind_Sword) second / (_Unwind_Sword) first;
84938fd1498Szrj break;
85038fd1498Szrj case DW_OP_minus:
85138fd1498Szrj result = second - first;
85238fd1498Szrj break;
85338fd1498Szrj case DW_OP_mod:
85438fd1498Szrj result = second % first;
85538fd1498Szrj break;
85638fd1498Szrj case DW_OP_mul:
85738fd1498Szrj result = second * first;
85838fd1498Szrj break;
85938fd1498Szrj case DW_OP_or:
86038fd1498Szrj result = second | first;
86138fd1498Szrj break;
86238fd1498Szrj case DW_OP_plus:
86338fd1498Szrj result = second + first;
86438fd1498Szrj break;
86538fd1498Szrj case DW_OP_shl:
86638fd1498Szrj result = second << first;
86738fd1498Szrj break;
86838fd1498Szrj case DW_OP_shr:
86938fd1498Szrj result = second >> first;
87038fd1498Szrj break;
87138fd1498Szrj case DW_OP_shra:
87238fd1498Szrj result = (_Unwind_Sword) second >> first;
87338fd1498Szrj break;
87438fd1498Szrj case DW_OP_xor:
87538fd1498Szrj result = second ^ first;
87638fd1498Szrj break;
87738fd1498Szrj case DW_OP_le:
87838fd1498Szrj result = (_Unwind_Sword) second <= (_Unwind_Sword) first;
87938fd1498Szrj break;
88038fd1498Szrj case DW_OP_ge:
88138fd1498Szrj result = (_Unwind_Sword) second >= (_Unwind_Sword) first;
88238fd1498Szrj break;
88338fd1498Szrj case DW_OP_eq:
88438fd1498Szrj result = (_Unwind_Sword) second == (_Unwind_Sword) first;
88538fd1498Szrj break;
88638fd1498Szrj case DW_OP_lt:
88738fd1498Szrj result = (_Unwind_Sword) second < (_Unwind_Sword) first;
88838fd1498Szrj break;
88938fd1498Szrj case DW_OP_gt:
89038fd1498Szrj result = (_Unwind_Sword) second > (_Unwind_Sword) first;
89138fd1498Szrj break;
89238fd1498Szrj case DW_OP_ne:
89338fd1498Szrj result = (_Unwind_Sword) second != (_Unwind_Sword) first;
89438fd1498Szrj break;
89538fd1498Szrj
89638fd1498Szrj default:
89738fd1498Szrj gcc_unreachable ();
89838fd1498Szrj }
89938fd1498Szrj }
90038fd1498Szrj break;
90138fd1498Szrj
90238fd1498Szrj case DW_OP_skip:
90338fd1498Szrj offset = read_2s (op_ptr);
90438fd1498Szrj op_ptr += 2;
90538fd1498Szrj op_ptr += offset;
90638fd1498Szrj goto no_push;
90738fd1498Szrj
90838fd1498Szrj case DW_OP_bra:
90938fd1498Szrj gcc_assert (stack_elt);
91038fd1498Szrj stack_elt -= 1;
91138fd1498Szrj
91238fd1498Szrj offset = read_2s (op_ptr);
91338fd1498Szrj op_ptr += 2;
91438fd1498Szrj if (stack[stack_elt] != 0)
91538fd1498Szrj op_ptr += offset;
91638fd1498Szrj goto no_push;
91738fd1498Szrj
91838fd1498Szrj case DW_OP_nop:
91938fd1498Szrj goto no_push;
92038fd1498Szrj
92138fd1498Szrj default:
92238fd1498Szrj gcc_unreachable ();
92338fd1498Szrj }
92438fd1498Szrj
92538fd1498Szrj /* Most things push a result value. */
92638fd1498Szrj gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack));
92738fd1498Szrj stack[stack_elt++] = result;
92838fd1498Szrj no_push:;
92938fd1498Szrj }
93038fd1498Szrj
93138fd1498Szrj /* We were executing this program to get a value. It should be
93238fd1498Szrj at top of stack. */
93338fd1498Szrj gcc_assert (stack_elt);
93438fd1498Szrj stack_elt -= 1;
93538fd1498Szrj return stack[stack_elt];
93638fd1498Szrj }
93738fd1498Szrj
93838fd1498Szrj
93938fd1498Szrj /* Decode DWARF 2 call frame information. Takes pointers the
94038fd1498Szrj instruction sequence to decode, current register information and
94138fd1498Szrj CIE info, and the PC range to evaluate. */
94238fd1498Szrj
94338fd1498Szrj static void
execute_cfa_program(const unsigned char * insn_ptr,const unsigned char * insn_end,struct _Unwind_Context * context,_Unwind_FrameState * fs)94438fd1498Szrj execute_cfa_program (const unsigned char *insn_ptr,
94538fd1498Szrj const unsigned char *insn_end,
94638fd1498Szrj struct _Unwind_Context *context,
94738fd1498Szrj _Unwind_FrameState *fs)
94838fd1498Szrj {
94938fd1498Szrj struct frame_state_reg_info *unused_rs = NULL;
95038fd1498Szrj
95138fd1498Szrj /* Don't allow remember/restore between CIE and FDE programs. */
95238fd1498Szrj fs->regs.prev = NULL;
95338fd1498Szrj
95438fd1498Szrj /* The comparison with the return address uses < rather than <= because
95538fd1498Szrj we are only interested in the effects of code before the call; for a
95638fd1498Szrj noreturn function, the return address may point to unrelated code with
95738fd1498Szrj a different stack configuration that we are not interested in. We
95838fd1498Szrj assume that the call itself is unwind info-neutral; if not, or if
95938fd1498Szrj there are delay instructions that adjust the stack, these must be
96038fd1498Szrj reflected at the point immediately before the call insn.
96138fd1498Szrj In signal frames, return address is after last completed instruction,
96238fd1498Szrj so we add 1 to return address to make the comparison <=. */
96338fd1498Szrj while (insn_ptr < insn_end
96438fd1498Szrj && fs->pc < context->ra + _Unwind_IsSignalFrame (context))
96538fd1498Szrj {
96638fd1498Szrj unsigned char insn = *insn_ptr++;
96738fd1498Szrj _uleb128_t reg, utmp;
96838fd1498Szrj _sleb128_t offset, stmp;
96938fd1498Szrj
97038fd1498Szrj if ((insn & 0xc0) == DW_CFA_advance_loc)
97138fd1498Szrj fs->pc += (insn & 0x3f) * fs->code_align;
97238fd1498Szrj else if ((insn & 0xc0) == DW_CFA_offset)
97338fd1498Szrj {
97438fd1498Szrj reg = insn & 0x3f;
97538fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
97638fd1498Szrj offset = (_Unwind_Sword) utmp * fs->data_align;
97738fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
97838fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
97938fd1498Szrj {
98038fd1498Szrj fs->regs.reg[reg].how = REG_SAVED_OFFSET;
98138fd1498Szrj fs->regs.reg[reg].loc.offset = offset;
98238fd1498Szrj }
98338fd1498Szrj }
98438fd1498Szrj else if ((insn & 0xc0) == DW_CFA_restore)
98538fd1498Szrj {
98638fd1498Szrj reg = insn & 0x3f;
98738fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
98838fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
98938fd1498Szrj fs->regs.reg[reg].how = REG_UNSAVED;
99038fd1498Szrj }
99138fd1498Szrj else switch (insn)
99238fd1498Szrj {
99338fd1498Szrj case DW_CFA_set_loc:
99438fd1498Szrj {
99538fd1498Szrj _Unwind_Ptr pc;
99638fd1498Szrj
99738fd1498Szrj insn_ptr = read_encoded_value (context, fs->fde_encoding,
99838fd1498Szrj insn_ptr, &pc);
99938fd1498Szrj fs->pc = (void *) pc;
100038fd1498Szrj }
100138fd1498Szrj break;
100238fd1498Szrj
100338fd1498Szrj case DW_CFA_advance_loc1:
100438fd1498Szrj fs->pc += read_1u (insn_ptr) * fs->code_align;
100538fd1498Szrj insn_ptr += 1;
100638fd1498Szrj break;
100738fd1498Szrj case DW_CFA_advance_loc2:
100838fd1498Szrj fs->pc += read_2u (insn_ptr) * fs->code_align;
100938fd1498Szrj insn_ptr += 2;
101038fd1498Szrj break;
101138fd1498Szrj case DW_CFA_advance_loc4:
101238fd1498Szrj fs->pc += read_4u (insn_ptr) * fs->code_align;
101338fd1498Szrj insn_ptr += 4;
101438fd1498Szrj break;
101538fd1498Szrj
101638fd1498Szrj case DW_CFA_offset_extended:
101738fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®);
101838fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
101938fd1498Szrj offset = (_Unwind_Sword) utmp * fs->data_align;
102038fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
102138fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
102238fd1498Szrj {
102338fd1498Szrj fs->regs.reg[reg].how = REG_SAVED_OFFSET;
102438fd1498Szrj fs->regs.reg[reg].loc.offset = offset;
102538fd1498Szrj }
102638fd1498Szrj break;
102738fd1498Szrj
102838fd1498Szrj case DW_CFA_restore_extended:
102938fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®);
103038fd1498Szrj /* FIXME, this is wrong; the CIE might have said that the
103138fd1498Szrj register was saved somewhere. */
103238fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
103338fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
103438fd1498Szrj fs->regs.reg[reg].how = REG_UNSAVED;
103538fd1498Szrj break;
103638fd1498Szrj
103738fd1498Szrj case DW_CFA_same_value:
103838fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®);
103938fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
104038fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
104138fd1498Szrj fs->regs.reg[reg].how = REG_UNSAVED;
104238fd1498Szrj break;
104338fd1498Szrj
104438fd1498Szrj case DW_CFA_undefined:
104538fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®);
104638fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
104738fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
104838fd1498Szrj fs->regs.reg[reg].how = REG_UNDEFINED;
104938fd1498Szrj break;
105038fd1498Szrj
105138fd1498Szrj case DW_CFA_nop:
105238fd1498Szrj break;
105338fd1498Szrj
105438fd1498Szrj case DW_CFA_register:
105538fd1498Szrj {
105638fd1498Szrj _uleb128_t reg2;
105738fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®);
105838fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®2);
105938fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
106038fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
106138fd1498Szrj {
106238fd1498Szrj fs->regs.reg[reg].how = REG_SAVED_REG;
106338fd1498Szrj fs->regs.reg[reg].loc.reg = (_Unwind_Word)reg2;
106438fd1498Szrj }
106538fd1498Szrj }
106638fd1498Szrj break;
106738fd1498Szrj
106838fd1498Szrj case DW_CFA_remember_state:
106938fd1498Szrj {
107038fd1498Szrj struct frame_state_reg_info *new_rs;
107138fd1498Szrj if (unused_rs)
107238fd1498Szrj {
107338fd1498Szrj new_rs = unused_rs;
107438fd1498Szrj unused_rs = unused_rs->prev;
107538fd1498Szrj }
107638fd1498Szrj else
107738fd1498Szrj new_rs = alloca (sizeof (struct frame_state_reg_info));
107838fd1498Szrj
107938fd1498Szrj *new_rs = fs->regs;
108038fd1498Szrj fs->regs.prev = new_rs;
108138fd1498Szrj }
108238fd1498Szrj break;
108338fd1498Szrj
108438fd1498Szrj case DW_CFA_restore_state:
108538fd1498Szrj {
108638fd1498Szrj struct frame_state_reg_info *old_rs = fs->regs.prev;
108738fd1498Szrj fs->regs = *old_rs;
108838fd1498Szrj old_rs->prev = unused_rs;
108938fd1498Szrj unused_rs = old_rs;
109038fd1498Szrj }
109138fd1498Szrj break;
109238fd1498Szrj
109338fd1498Szrj case DW_CFA_def_cfa:
109438fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
109538fd1498Szrj fs->regs.cfa_reg = (_Unwind_Word)utmp;
109638fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
109738fd1498Szrj fs->regs.cfa_offset = (_Unwind_Word)utmp;
109838fd1498Szrj fs->regs.cfa_how = CFA_REG_OFFSET;
109938fd1498Szrj break;
110038fd1498Szrj
110138fd1498Szrj case DW_CFA_def_cfa_register:
110238fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
110338fd1498Szrj fs->regs.cfa_reg = (_Unwind_Word)utmp;
110438fd1498Szrj fs->regs.cfa_how = CFA_REG_OFFSET;
110538fd1498Szrj break;
110638fd1498Szrj
110738fd1498Szrj case DW_CFA_def_cfa_offset:
110838fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
110938fd1498Szrj fs->regs.cfa_offset = utmp;
111038fd1498Szrj /* cfa_how deliberately not set. */
111138fd1498Szrj break;
111238fd1498Szrj
111338fd1498Szrj case DW_CFA_def_cfa_expression:
111438fd1498Szrj fs->regs.cfa_exp = insn_ptr;
111538fd1498Szrj fs->regs.cfa_how = CFA_EXP;
111638fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
111738fd1498Szrj insn_ptr += utmp;
111838fd1498Szrj break;
111938fd1498Szrj
112038fd1498Szrj case DW_CFA_expression:
112138fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®);
112238fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
112338fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
112438fd1498Szrj {
112538fd1498Szrj fs->regs.reg[reg].how = REG_SAVED_EXP;
112638fd1498Szrj fs->regs.reg[reg].loc.exp = insn_ptr;
112738fd1498Szrj }
112838fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
112938fd1498Szrj insn_ptr += utmp;
113038fd1498Szrj break;
113138fd1498Szrj
113238fd1498Szrj /* Dwarf3. */
113338fd1498Szrj case DW_CFA_offset_extended_sf:
113438fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®);
113538fd1498Szrj insn_ptr = read_sleb128 (insn_ptr, &stmp);
113638fd1498Szrj offset = stmp * fs->data_align;
113738fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
113838fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
113938fd1498Szrj {
114038fd1498Szrj fs->regs.reg[reg].how = REG_SAVED_OFFSET;
114138fd1498Szrj fs->regs.reg[reg].loc.offset = offset;
114238fd1498Szrj }
114338fd1498Szrj break;
114438fd1498Szrj
114538fd1498Szrj case DW_CFA_def_cfa_sf:
114638fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
114738fd1498Szrj fs->regs.cfa_reg = (_Unwind_Word)utmp;
114838fd1498Szrj insn_ptr = read_sleb128 (insn_ptr, &stmp);
114938fd1498Szrj fs->regs.cfa_offset = (_Unwind_Sword)stmp;
115038fd1498Szrj fs->regs.cfa_how = CFA_REG_OFFSET;
115138fd1498Szrj fs->regs.cfa_offset *= fs->data_align;
115238fd1498Szrj break;
115338fd1498Szrj
115438fd1498Szrj case DW_CFA_def_cfa_offset_sf:
115538fd1498Szrj insn_ptr = read_sleb128 (insn_ptr, &stmp);
115638fd1498Szrj fs->regs.cfa_offset = (_Unwind_Sword)stmp;
115738fd1498Szrj fs->regs.cfa_offset *= fs->data_align;
115838fd1498Szrj /* cfa_how deliberately not set. */
115938fd1498Szrj break;
116038fd1498Szrj
116138fd1498Szrj case DW_CFA_val_offset:
116238fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®);
116338fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
116438fd1498Szrj offset = (_Unwind_Sword) utmp * fs->data_align;
116538fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
116638fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
116738fd1498Szrj {
116838fd1498Szrj fs->regs.reg[reg].how = REG_SAVED_VAL_OFFSET;
116938fd1498Szrj fs->regs.reg[reg].loc.offset = offset;
117038fd1498Szrj }
117138fd1498Szrj break;
117238fd1498Szrj
117338fd1498Szrj case DW_CFA_val_offset_sf:
117438fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®);
117538fd1498Szrj insn_ptr = read_sleb128 (insn_ptr, &stmp);
117638fd1498Szrj offset = stmp * fs->data_align;
117738fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
117838fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
117938fd1498Szrj {
118038fd1498Szrj fs->regs.reg[reg].how = REG_SAVED_VAL_OFFSET;
118138fd1498Szrj fs->regs.reg[reg].loc.offset = offset;
118238fd1498Szrj }
118338fd1498Szrj break;
118438fd1498Szrj
118538fd1498Szrj case DW_CFA_val_expression:
118638fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®);
118738fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
118838fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
118938fd1498Szrj {
119038fd1498Szrj fs->regs.reg[reg].how = REG_SAVED_VAL_EXP;
119138fd1498Szrj fs->regs.reg[reg].loc.exp = insn_ptr;
119238fd1498Szrj }
119338fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
119438fd1498Szrj insn_ptr += utmp;
119538fd1498Szrj break;
119638fd1498Szrj
119738fd1498Szrj case DW_CFA_GNU_window_save:
119838fd1498Szrj #if defined (__aarch64__) && !defined (__ILP32__)
119938fd1498Szrj /* This CFA is multiplexed with Sparc. On AArch64 it's used to toggle
120038fd1498Szrj return address signing status. */
120138fd1498Szrj fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
120238fd1498Szrj #else
120338fd1498Szrj /* ??? Hardcoded for SPARC register window configuration. */
120438fd1498Szrj if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32)
120538fd1498Szrj for (reg = 16; reg < 32; ++reg)
120638fd1498Szrj {
120738fd1498Szrj fs->regs.reg[reg].how = REG_SAVED_OFFSET;
120838fd1498Szrj fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
120938fd1498Szrj }
121038fd1498Szrj #endif
121138fd1498Szrj break;
121238fd1498Szrj
121338fd1498Szrj case DW_CFA_GNU_args_size:
121438fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
121538fd1498Szrj context->args_size = (_Unwind_Word)utmp;
121638fd1498Szrj break;
121738fd1498Szrj
121838fd1498Szrj case DW_CFA_GNU_negative_offset_extended:
121938fd1498Szrj /* Obsoleted by DW_CFA_offset_extended_sf, but used by
122038fd1498Szrj older PowerPC code. */
122138fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, ®);
122238fd1498Szrj insn_ptr = read_uleb128 (insn_ptr, &utmp);
122338fd1498Szrj offset = (_Unwind_Word) utmp * fs->data_align;
122438fd1498Szrj reg = DWARF_REG_TO_UNWIND_COLUMN (reg);
122538fd1498Szrj if (UNWIND_COLUMN_IN_RANGE (reg))
122638fd1498Szrj {
122738fd1498Szrj fs->regs.reg[reg].how = REG_SAVED_OFFSET;
122838fd1498Szrj fs->regs.reg[reg].loc.offset = -offset;
122938fd1498Szrj }
123038fd1498Szrj break;
123138fd1498Szrj
123238fd1498Szrj default:
123338fd1498Szrj gcc_unreachable ();
123438fd1498Szrj }
123538fd1498Szrj }
123638fd1498Szrj }
123738fd1498Szrj
123838fd1498Szrj /* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
123938fd1498Szrj its caller and decode it into FS. This function also sets the
124038fd1498Szrj args_size and lsda members of CONTEXT, as they are really information
124138fd1498Szrj about the caller's frame. */
124238fd1498Szrj
124338fd1498Szrj static _Unwind_Reason_Code
uw_frame_state_for(struct _Unwind_Context * context,_Unwind_FrameState * fs)124438fd1498Szrj uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
124538fd1498Szrj {
124638fd1498Szrj const struct dwarf_fde *fde;
124738fd1498Szrj const struct dwarf_cie *cie;
124838fd1498Szrj const unsigned char *aug, *insn, *end;
124938fd1498Szrj
125038fd1498Szrj memset (fs, 0, sizeof (*fs));
125138fd1498Szrj context->args_size = 0;
125238fd1498Szrj context->lsda = 0;
125338fd1498Szrj
125438fd1498Szrj if (context->ra == 0)
125538fd1498Szrj return _URC_END_OF_STACK;
125638fd1498Szrj
125738fd1498Szrj fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
125838fd1498Szrj &context->bases);
125938fd1498Szrj if (fde == NULL)
126038fd1498Szrj {
126138fd1498Szrj #ifdef MD_FALLBACK_FRAME_STATE_FOR
126238fd1498Szrj /* Couldn't find frame unwind info for this function. Try a
126338fd1498Szrj target-specific fallback mechanism. This will necessarily
126438fd1498Szrj not provide a personality routine or LSDA. */
126538fd1498Szrj return MD_FALLBACK_FRAME_STATE_FOR (context, fs);
126638fd1498Szrj #else
126738fd1498Szrj return _URC_END_OF_STACK;
126838fd1498Szrj #endif
126938fd1498Szrj }
127038fd1498Szrj
127138fd1498Szrj fs->pc = context->bases.func;
127238fd1498Szrj
127338fd1498Szrj cie = get_cie (fde);
127438fd1498Szrj insn = extract_cie_info (cie, context, fs);
127538fd1498Szrj if (insn == NULL)
127638fd1498Szrj /* CIE contained unknown augmentation. */
127738fd1498Szrj return _URC_FATAL_PHASE1_ERROR;
127838fd1498Szrj
127938fd1498Szrj /* First decode all the insns in the CIE. */
128038fd1498Szrj end = (const unsigned char *) next_fde ((const struct dwarf_fde *) cie);
128138fd1498Szrj execute_cfa_program (insn, end, context, fs);
128238fd1498Szrj
128338fd1498Szrj /* Locate augmentation for the fde. */
128438fd1498Szrj aug = (const unsigned char *) fde + sizeof (*fde);
128538fd1498Szrj aug += 2 * size_of_encoded_value (fs->fde_encoding);
128638fd1498Szrj insn = NULL;
128738fd1498Szrj if (fs->saw_z)
128838fd1498Szrj {
128938fd1498Szrj _uleb128_t i;
129038fd1498Szrj aug = read_uleb128 (aug, &i);
129138fd1498Szrj insn = aug + i;
129238fd1498Szrj }
129338fd1498Szrj if (fs->lsda_encoding != DW_EH_PE_omit)
129438fd1498Szrj {
129538fd1498Szrj _Unwind_Ptr lsda;
129638fd1498Szrj
129738fd1498Szrj aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
129838fd1498Szrj context->lsda = (void *) lsda;
129938fd1498Szrj }
130038fd1498Szrj
130138fd1498Szrj /* Then the insns in the FDE up to our target PC. */
130238fd1498Szrj if (insn == NULL)
130338fd1498Szrj insn = aug;
130438fd1498Szrj end = (const unsigned char *) next_fde (fde);
130538fd1498Szrj execute_cfa_program (insn, end, context, fs);
130638fd1498Szrj
130738fd1498Szrj return _URC_NO_REASON;
130838fd1498Szrj }
130938fd1498Szrj
131038fd1498Szrj typedef struct frame_state
131138fd1498Szrj {
131238fd1498Szrj void *cfa;
131338fd1498Szrj void *eh_ptr;
131438fd1498Szrj long cfa_offset;
131538fd1498Szrj long args_size;
131638fd1498Szrj long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
131738fd1498Szrj unsigned short cfa_reg;
131838fd1498Szrj unsigned short retaddr_column;
131938fd1498Szrj char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
132038fd1498Szrj } frame_state;
132138fd1498Szrj
132238fd1498Szrj struct frame_state * __frame_state_for (void *, struct frame_state *);
132338fd1498Szrj
132438fd1498Szrj /* Called from pre-G++ 3.0 __throw to find the registers to restore for
132538fd1498Szrj a given PC_TARGET. The caller should allocate a local variable of
132638fd1498Szrj `struct frame_state' and pass its address to STATE_IN. */
132738fd1498Szrj
132838fd1498Szrj struct frame_state *
__frame_state_for(void * pc_target,struct frame_state * state_in)132938fd1498Szrj __frame_state_for (void *pc_target, struct frame_state *state_in)
133038fd1498Szrj {
133138fd1498Szrj struct _Unwind_Context context;
133238fd1498Szrj _Unwind_FrameState fs;
133338fd1498Szrj int reg;
133438fd1498Szrj
133538fd1498Szrj memset (&context, 0, sizeof (struct _Unwind_Context));
133638fd1498Szrj if (!ASSUME_EXTENDED_UNWIND_CONTEXT)
133738fd1498Szrj context.flags = EXTENDED_CONTEXT_BIT;
133838fd1498Szrj context.ra = pc_target + 1;
133938fd1498Szrj
134038fd1498Szrj if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
134138fd1498Szrj return 0;
134238fd1498Szrj
134338fd1498Szrj /* We have no way to pass a location expression for the CFA to our
134438fd1498Szrj caller. It wouldn't understand it anyway. */
134538fd1498Szrj if (fs.regs.cfa_how == CFA_EXP)
134638fd1498Szrj return 0;
134738fd1498Szrj
134838fd1498Szrj for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++)
134938fd1498Szrj {
135038fd1498Szrj state_in->saved[reg] = fs.regs.reg[reg].how;
135138fd1498Szrj switch (state_in->saved[reg])
135238fd1498Szrj {
135338fd1498Szrj case REG_SAVED_REG:
135438fd1498Szrj state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
135538fd1498Szrj break;
135638fd1498Szrj case REG_SAVED_OFFSET:
135738fd1498Szrj state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
135838fd1498Szrj break;
135938fd1498Szrj default:
136038fd1498Szrj state_in->reg_or_offset[reg] = 0;
136138fd1498Szrj break;
136238fd1498Szrj }
136338fd1498Szrj }
136438fd1498Szrj
136538fd1498Szrj state_in->cfa_offset = fs.regs.cfa_offset;
136638fd1498Szrj state_in->cfa_reg = fs.regs.cfa_reg;
136738fd1498Szrj state_in->retaddr_column = fs.retaddr_column;
136838fd1498Szrj state_in->args_size = context.args_size;
136938fd1498Szrj state_in->eh_ptr = fs.eh_ptr;
137038fd1498Szrj
137138fd1498Szrj return state_in;
137238fd1498Szrj }
137338fd1498Szrj
137438fd1498Szrj typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
137538fd1498Szrj
137638fd1498Szrj static inline void
_Unwind_SetSpColumn(struct _Unwind_Context * context,void * cfa,_Unwind_SpTmp * tmp_sp)137738fd1498Szrj _Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
137838fd1498Szrj _Unwind_SpTmp *tmp_sp)
137938fd1498Szrj {
138038fd1498Szrj int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
138138fd1498Szrj
138238fd1498Szrj if (size == sizeof(_Unwind_Ptr))
138338fd1498Szrj tmp_sp->ptr = (_Unwind_Ptr) cfa;
138438fd1498Szrj else
138538fd1498Szrj {
138638fd1498Szrj gcc_assert (size == sizeof(_Unwind_Word));
138738fd1498Szrj tmp_sp->word = (_Unwind_Ptr) cfa;
138838fd1498Szrj }
138938fd1498Szrj _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp);
139038fd1498Szrj }
139138fd1498Szrj
139238fd1498Szrj static void
uw_update_context_1(struct _Unwind_Context * context,_Unwind_FrameState * fs)139338fd1498Szrj uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
139438fd1498Szrj {
139538fd1498Szrj struct _Unwind_Context orig_context = *context;
139638fd1498Szrj void *cfa;
139738fd1498Szrj long i;
139838fd1498Szrj
139938fd1498Szrj #ifdef __LIBGCC_EH_RETURN_STACKADJ_RTX__
140038fd1498Szrj /* Special handling here: Many machines do not use a frame pointer,
140138fd1498Szrj and track the CFA only through offsets from the stack pointer from
140238fd1498Szrj one frame to the next. In this case, the stack pointer is never
140338fd1498Szrj stored, so it has no saved address in the context. What we do
140438fd1498Szrj have is the CFA from the previous stack frame.
140538fd1498Szrj
140638fd1498Szrj In very special situations (such as unwind info for signal return),
140738fd1498Szrj there may be location expressions that use the stack pointer as well.
140838fd1498Szrj
140938fd1498Szrj Do this conditionally for one frame. This allows the unwind info
141038fd1498Szrj for one frame to save a copy of the stack pointer from the previous
141138fd1498Szrj frame, and be able to use much easier CFA mechanisms to do it.
141238fd1498Szrj Always zap the saved stack pointer value for the next frame; carrying
141338fd1498Szrj the value over from one frame to another doesn't make sense. */
141438fd1498Szrj
141538fd1498Szrj _Unwind_SpTmp tmp_sp;
141638fd1498Szrj
141738fd1498Szrj if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ()))
141838fd1498Szrj _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp);
141938fd1498Szrj _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL);
142038fd1498Szrj #endif
142138fd1498Szrj
142238fd1498Szrj /* Compute this frame's CFA. */
142338fd1498Szrj switch (fs->regs.cfa_how)
142438fd1498Szrj {
142538fd1498Szrj case CFA_REG_OFFSET:
142638fd1498Szrj cfa = _Unwind_GetPtr (&orig_context, fs->regs.cfa_reg);
142738fd1498Szrj cfa += fs->regs.cfa_offset;
142838fd1498Szrj break;
142938fd1498Szrj
143038fd1498Szrj case CFA_EXP:
143138fd1498Szrj {
143238fd1498Szrj const unsigned char *exp = fs->regs.cfa_exp;
143338fd1498Szrj _uleb128_t len;
143438fd1498Szrj
143538fd1498Szrj exp = read_uleb128 (exp, &len);
143638fd1498Szrj cfa = (void *) (_Unwind_Ptr)
143738fd1498Szrj execute_stack_op (exp, exp + len, &orig_context, 0);
143838fd1498Szrj break;
143938fd1498Szrj }
144038fd1498Szrj
144138fd1498Szrj default:
144238fd1498Szrj gcc_unreachable ();
144338fd1498Szrj }
144438fd1498Szrj context->cfa = cfa;
144538fd1498Szrj
144638fd1498Szrj /* Compute the addresses of all registers saved in this frame. */
144738fd1498Szrj for (i = 0; i < __LIBGCC_DWARF_FRAME_REGISTERS__ + 1; ++i)
144838fd1498Szrj switch (fs->regs.reg[i].how)
144938fd1498Szrj {
145038fd1498Szrj case REG_UNSAVED:
145138fd1498Szrj case REG_UNDEFINED:
145238fd1498Szrj break;
145338fd1498Szrj
145438fd1498Szrj case REG_SAVED_OFFSET:
145538fd1498Szrj _Unwind_SetGRPtr (context, i,
145638fd1498Szrj (void *) (cfa + fs->regs.reg[i].loc.offset));
145738fd1498Szrj break;
145838fd1498Szrj
145938fd1498Szrj case REG_SAVED_REG:
146038fd1498Szrj if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
146138fd1498Szrj _Unwind_SetGRValue (context, i,
146238fd1498Szrj _Unwind_GetGR (&orig_context,
146338fd1498Szrj fs->regs.reg[i].loc.reg));
146438fd1498Szrj else
146538fd1498Szrj _Unwind_SetGRPtr (context, i,
146638fd1498Szrj _Unwind_GetGRPtr (&orig_context,
146738fd1498Szrj fs->regs.reg[i].loc.reg));
146838fd1498Szrj break;
146938fd1498Szrj
147038fd1498Szrj case REG_SAVED_EXP:
147138fd1498Szrj {
147238fd1498Szrj const unsigned char *exp = fs->regs.reg[i].loc.exp;
147338fd1498Szrj _uleb128_t len;
147438fd1498Szrj _Unwind_Ptr val;
147538fd1498Szrj
147638fd1498Szrj exp = read_uleb128 (exp, &len);
147738fd1498Szrj val = execute_stack_op (exp, exp + len, &orig_context,
147838fd1498Szrj (_Unwind_Ptr) cfa);
147938fd1498Szrj _Unwind_SetGRPtr (context, i, (void *) val);
148038fd1498Szrj }
148138fd1498Szrj break;
148238fd1498Szrj
148338fd1498Szrj case REG_SAVED_VAL_OFFSET:
148438fd1498Szrj _Unwind_SetGRValue (context, i,
148538fd1498Szrj (_Unwind_Internal_Ptr)
148638fd1498Szrj (cfa + fs->regs.reg[i].loc.offset));
148738fd1498Szrj break;
148838fd1498Szrj
148938fd1498Szrj case REG_SAVED_VAL_EXP:
149038fd1498Szrj {
149138fd1498Szrj const unsigned char *exp = fs->regs.reg[i].loc.exp;
149238fd1498Szrj _uleb128_t len;
149338fd1498Szrj _Unwind_Ptr val;
149438fd1498Szrj
149538fd1498Szrj exp = read_uleb128 (exp, &len);
149638fd1498Szrj val = execute_stack_op (exp, exp + len, &orig_context,
149738fd1498Szrj (_Unwind_Ptr) cfa);
149838fd1498Szrj _Unwind_SetGRValue (context, i, val);
149938fd1498Szrj }
150038fd1498Szrj break;
150138fd1498Szrj }
150238fd1498Szrj
150338fd1498Szrj _Unwind_SetSignalFrame (context, fs->signal_frame);
150438fd1498Szrj
150538fd1498Szrj #ifdef MD_FROB_UPDATE_CONTEXT
150638fd1498Szrj MD_FROB_UPDATE_CONTEXT (context, fs);
150738fd1498Szrj #endif
150838fd1498Szrj }
150938fd1498Szrj
151038fd1498Szrj /* CONTEXT describes the unwind state for a frame, and FS describes the FDE
151138fd1498Szrj of its caller. Update CONTEXT to refer to the caller as well. Note
151238fd1498Szrj that the args_size and lsda members are not updated here, but later in
151338fd1498Szrj uw_frame_state_for. */
151438fd1498Szrj
151538fd1498Szrj static void
uw_update_context(struct _Unwind_Context * context,_Unwind_FrameState * fs)151638fd1498Szrj uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
151738fd1498Szrj {
151838fd1498Szrj uw_update_context_1 (context, fs);
151938fd1498Szrj
152038fd1498Szrj /* In general this unwinder doesn't make any distinction between
152138fd1498Szrj undefined and same_value rule. Call-saved registers are assumed
152238fd1498Szrj to have same_value rule by default and explicit undefined
152338fd1498Szrj rule is handled like same_value. The only exception is
152438fd1498Szrj DW_CFA_undefined on retaddr_column which is supposed to
152538fd1498Szrj mark outermost frame in DWARF 3. */
152638fd1498Szrj if (fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (fs->retaddr_column)].how
152738fd1498Szrj == REG_UNDEFINED)
152838fd1498Szrj /* uw_frame_state_for uses context->ra == 0 check to find outermost
152938fd1498Szrj stack frame. */
153038fd1498Szrj context->ra = 0;
153138fd1498Szrj else
153238fd1498Szrj {
153338fd1498Szrj /* Compute the return address now, since the return address column
153438fd1498Szrj can change from frame to frame. */
153538fd1498Szrj context->ra = __builtin_extract_return_addr
153638fd1498Szrj (_Unwind_GetPtr (context, fs->retaddr_column));
153738fd1498Szrj #ifdef MD_POST_EXTRACT_FRAME_ADDR
153838fd1498Szrj context->ra = MD_POST_EXTRACT_FRAME_ADDR (context, fs, context->ra);
153938fd1498Szrj #endif
154038fd1498Szrj }
154138fd1498Szrj }
154238fd1498Szrj
154338fd1498Szrj static void
uw_advance_context(struct _Unwind_Context * context,_Unwind_FrameState * fs)154438fd1498Szrj uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
154538fd1498Szrj {
154638fd1498Szrj uw_update_context (context, fs);
154738fd1498Szrj }
154838fd1498Szrj
154938fd1498Szrj /* Fill in CONTEXT for top-of-stack. The only valid registers at this
155038fd1498Szrj level will be the return address and the CFA. */
155138fd1498Szrj
155238fd1498Szrj #define uw_init_context(CONTEXT) \
155338fd1498Szrj do \
155438fd1498Szrj { \
155538fd1498Szrj /* Do any necessary initialization to access arbitrary stack frames. \
155638fd1498Szrj On the SPARC, this means flushing the register windows. */ \
155738fd1498Szrj __builtin_unwind_init (); \
155838fd1498Szrj uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \
155938fd1498Szrj __builtin_return_address (0)); \
156038fd1498Szrj } \
156138fd1498Szrj while (0)
156238fd1498Szrj
156338fd1498Szrj static inline void
init_dwarf_reg_size_table(void)156438fd1498Szrj init_dwarf_reg_size_table (void)
156538fd1498Szrj {
156638fd1498Szrj __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
156738fd1498Szrj }
156838fd1498Szrj
156938fd1498Szrj static void __attribute__((noinline))
uw_init_context_1(struct _Unwind_Context * context,void * outer_cfa,void * outer_ra)157038fd1498Szrj uw_init_context_1 (struct _Unwind_Context *context,
157138fd1498Szrj void *outer_cfa, void *outer_ra)
157238fd1498Szrj {
157338fd1498Szrj void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
157438fd1498Szrj #ifdef MD_POST_EXTRACT_ROOT_ADDR
157538fd1498Szrj ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
157638fd1498Szrj #endif
157738fd1498Szrj _Unwind_FrameState fs;
157838fd1498Szrj _Unwind_SpTmp sp_slot;
157938fd1498Szrj _Unwind_Reason_Code code;
158038fd1498Szrj
158138fd1498Szrj memset (context, 0, sizeof (struct _Unwind_Context));
158238fd1498Szrj context->ra = ra;
158338fd1498Szrj if (!ASSUME_EXTENDED_UNWIND_CONTEXT)
158438fd1498Szrj context->flags = EXTENDED_CONTEXT_BIT;
158538fd1498Szrj
158638fd1498Szrj code = uw_frame_state_for (context, &fs);
158738fd1498Szrj gcc_assert (code == _URC_NO_REASON);
158838fd1498Szrj
158938fd1498Szrj #if __GTHREADS
159038fd1498Szrj {
159138fd1498Szrj static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
159238fd1498Szrj if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
159338fd1498Szrj && dwarf_reg_size_table[0] == 0)
159438fd1498Szrj init_dwarf_reg_size_table ();
159538fd1498Szrj }
159638fd1498Szrj #else
159738fd1498Szrj if (dwarf_reg_size_table[0] == 0)
159838fd1498Szrj init_dwarf_reg_size_table ();
159938fd1498Szrj #endif
160038fd1498Szrj
160138fd1498Szrj /* Force the frame state to use the known cfa value. */
160238fd1498Szrj _Unwind_SetSpColumn (context, outer_cfa, &sp_slot);
160338fd1498Szrj fs.regs.cfa_how = CFA_REG_OFFSET;
160438fd1498Szrj fs.regs.cfa_reg = __builtin_dwarf_sp_column ();
160538fd1498Szrj fs.regs.cfa_offset = 0;
160638fd1498Szrj
160738fd1498Szrj uw_update_context_1 (context, &fs);
160838fd1498Szrj
160938fd1498Szrj /* If the return address column was saved in a register in the
161038fd1498Szrj initialization context, then we can't see it in the given
161138fd1498Szrj call frame data. So have the initialization context tell us. */
161238fd1498Szrj context->ra = __builtin_extract_return_addr (outer_ra);
161338fd1498Szrj #ifdef MD_POST_EXTRACT_ROOT_ADDR
161438fd1498Szrj context->ra = MD_POST_EXTRACT_ROOT_ADDR (context->ra);
161538fd1498Szrj #endif
161638fd1498Szrj }
161738fd1498Szrj
161838fd1498Szrj static void _Unwind_DebugHook (void *, void *)
161938fd1498Szrj __attribute__ ((__noinline__, __used__, __noclone__));
162038fd1498Szrj
162138fd1498Szrj /* This function is called during unwinding. It is intended as a hook
162238fd1498Szrj for a debugger to intercept exceptions. CFA is the CFA of the
162338fd1498Szrj target frame. HANDLER is the PC to which control will be
162438fd1498Szrj transferred. */
162538fd1498Szrj static void
_Unwind_DebugHook(void * cfa,void * handler)162638fd1498Szrj _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
162738fd1498Szrj void *handler __attribute__ ((__unused__)))
162838fd1498Szrj {
162938fd1498Szrj /* We only want to use stap probes starting with v3. Earlier
163038fd1498Szrj versions added too much startup cost. */
163138fd1498Szrj #if defined (HAVE_SYS_SDT_H) && defined (STAP_PROBE2) && _SDT_NOTE_TYPE >= 3
163238fd1498Szrj STAP_PROBE2 (libgcc, unwind, cfa, handler);
163338fd1498Szrj #else
163438fd1498Szrj asm ("");
163538fd1498Szrj #endif
163638fd1498Szrj }
163738fd1498Szrj
163838fd1498Szrj /* Frob exception handler's address kept in TARGET before installing into
163938fd1498Szrj CURRENT context. */
164038fd1498Szrj
164138fd1498Szrj static inline void *
uw_frob_return_addr(struct _Unwind_Context * current,struct _Unwind_Context * target)164238fd1498Szrj uw_frob_return_addr (struct _Unwind_Context *current
164338fd1498Szrj __attribute__ ((__unused__)),
164438fd1498Szrj struct _Unwind_Context *target)
164538fd1498Szrj {
164638fd1498Szrj void *ret_addr = __builtin_frob_return_addr (target->ra);
164738fd1498Szrj #ifdef MD_POST_FROB_EH_HANDLER_ADDR
164838fd1498Szrj ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
164938fd1498Szrj #endif
165038fd1498Szrj return ret_addr;
165138fd1498Szrj }
165238fd1498Szrj
165338fd1498Szrj /* Install TARGET into CURRENT so that we can return to it. This is a
165438fd1498Szrj macro because __builtin_eh_return must be invoked in the context of
165538fd1498Szrj our caller. FRAMES is a number of frames to be unwind.
165638fd1498Szrj _Unwind_Frames_Extra is a macro to do additional work during unwinding
165738fd1498Szrj if needed, for example shadow stack pointer adjustment for Intel CET
165838fd1498Szrj technology. */
165938fd1498Szrj
166038fd1498Szrj #define uw_install_context(CURRENT, TARGET, FRAMES) \
166138fd1498Szrj do \
166238fd1498Szrj { \
166338fd1498Szrj long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
166438fd1498Szrj void *handler = uw_frob_return_addr ((CURRENT), (TARGET)); \
166538fd1498Szrj _Unwind_DebugHook ((TARGET)->cfa, handler); \
166638fd1498Szrj _Unwind_Frames_Extra (FRAMES); \
166738fd1498Szrj __builtin_eh_return (offset, handler); \
166838fd1498Szrj } \
166938fd1498Szrj while (0)
167038fd1498Szrj
167138fd1498Szrj static long
uw_install_context_1(struct _Unwind_Context * current,struct _Unwind_Context * target)167238fd1498Szrj uw_install_context_1 (struct _Unwind_Context *current,
167338fd1498Szrj struct _Unwind_Context *target)
167438fd1498Szrj {
167538fd1498Szrj long i;
167638fd1498Szrj _Unwind_SpTmp sp_slot;
167738fd1498Szrj
167838fd1498Szrj /* If the target frame does not have a saved stack pointer,
167938fd1498Szrj then set up the target's CFA. */
168038fd1498Szrj if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
168138fd1498Szrj _Unwind_SetSpColumn (target, target->cfa, &sp_slot);
168238fd1498Szrj
168338fd1498Szrj for (i = 0; i < __LIBGCC_DWARF_FRAME_REGISTERS__; ++i)
168438fd1498Szrj {
168538fd1498Szrj void *c = (void *) (_Unwind_Internal_Ptr) current->reg[i];
168638fd1498Szrj void *t = (void *) (_Unwind_Internal_Ptr)target->reg[i];
168738fd1498Szrj
168838fd1498Szrj gcc_assert (current->by_value[i] == 0);
168938fd1498Szrj if (target->by_value[i] && c)
169038fd1498Szrj {
169138fd1498Szrj _Unwind_Word w;
169238fd1498Szrj _Unwind_Ptr p;
169338fd1498Szrj if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
169438fd1498Szrj {
169538fd1498Szrj w = (_Unwind_Internal_Ptr) t;
169638fd1498Szrj memcpy (c, &w, sizeof (_Unwind_Word));
169738fd1498Szrj }
169838fd1498Szrj else
169938fd1498Szrj {
170038fd1498Szrj gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
170138fd1498Szrj p = (_Unwind_Internal_Ptr) t;
170238fd1498Szrj memcpy (c, &p, sizeof (_Unwind_Ptr));
170338fd1498Szrj }
170438fd1498Szrj }
170538fd1498Szrj else if (t && c && t != c)
170638fd1498Szrj memcpy (c, t, dwarf_reg_size_table[i]);
170738fd1498Szrj }
170838fd1498Szrj
170938fd1498Szrj /* If the current frame doesn't have a saved stack pointer, then we
171038fd1498Szrj need to rely on EH_RETURN_STACKADJ_RTX to get our target stack
171138fd1498Szrj pointer value reloaded. */
171238fd1498Szrj if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ()))
171338fd1498Szrj {
171438fd1498Szrj void *target_cfa;
171538fd1498Szrj
171638fd1498Szrj target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ());
171738fd1498Szrj
171838fd1498Szrj /* We adjust SP by the difference between CURRENT and TARGET's CFA. */
171938fd1498Szrj if (__LIBGCC_STACK_GROWS_DOWNWARD__)
172038fd1498Szrj return target_cfa - current->cfa + target->args_size;
172138fd1498Szrj else
172238fd1498Szrj return current->cfa - target_cfa - target->args_size;
172338fd1498Szrj }
172438fd1498Szrj return 0;
172538fd1498Szrj }
172638fd1498Szrj
172738fd1498Szrj static inline _Unwind_Ptr
uw_identify_context(struct _Unwind_Context * context)172838fd1498Szrj uw_identify_context (struct _Unwind_Context *context)
172938fd1498Szrj {
173038fd1498Szrj /* The CFA is not sufficient to disambiguate the context of a function
173138fd1498Szrj interrupted by a signal before establishing its frame and the context
173238fd1498Szrj of the signal itself. */
173338fd1498Szrj if (__LIBGCC_STACK_GROWS_DOWNWARD__)
173438fd1498Szrj return _Unwind_GetCFA (context) - _Unwind_IsSignalFrame (context);
173538fd1498Szrj else
173638fd1498Szrj return _Unwind_GetCFA (context) + _Unwind_IsSignalFrame (context);
173738fd1498Szrj }
173838fd1498Szrj
173938fd1498Szrj
174038fd1498Szrj #include "unwind.inc"
174138fd1498Szrj
174238fd1498Szrj #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
174338fd1498Szrj alias (_Unwind_Backtrace);
174438fd1498Szrj alias (_Unwind_DeleteException);
174538fd1498Szrj alias (_Unwind_FindEnclosingFunction);
174638fd1498Szrj alias (_Unwind_ForcedUnwind);
174738fd1498Szrj alias (_Unwind_GetDataRelBase);
174838fd1498Szrj alias (_Unwind_GetTextRelBase);
174938fd1498Szrj alias (_Unwind_GetCFA);
175038fd1498Szrj alias (_Unwind_GetGR);
175138fd1498Szrj alias (_Unwind_GetIP);
175238fd1498Szrj alias (_Unwind_GetLanguageSpecificData);
175338fd1498Szrj alias (_Unwind_GetRegionStart);
175438fd1498Szrj alias (_Unwind_RaiseException);
175538fd1498Szrj alias (_Unwind_Resume);
175638fd1498Szrj alias (_Unwind_Resume_or_Rethrow);
175738fd1498Szrj alias (_Unwind_SetGR);
175838fd1498Szrj alias (_Unwind_SetIP);
175938fd1498Szrj #endif
176038fd1498Szrj
176138fd1498Szrj #endif /* !USING_SJLJ_EXCEPTIONS */
1762