aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJose Ruiz <ruiz@adacore.com>2009-10-11 20:48:46 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2009-10-11 20:48:46 +0000
commitcb7d60a67762a3e07c7e934feb0e923f8e6a92a7 (patch)
treec8c665a3c52976156261d64fa054e91b88a92903 /gcc
parent8d232178a93d0895482b4cb606f89830352e47db (diff)
downloadgcc-cb7d60a67762a3e07c7e934feb0e923f8e6a92a7.zip
gcc-cb7d60a67762a3e07c7e934feb0e923f8e6a92a7.tar.gz
gcc-cb7d60a67762a3e07c7e934feb0e923f8e6a92a7.tar.bz2
re PR target/33743 (unwinding through signal frames)
PR target/33743 * config/sparc/sol2.h (MD_UNWIND_SUPPORT): Define. * config/sparc/sol2-unwind.h: New file. Co-Authored-By: Eric Botcazou <ebotcazou@adacore.com> From-SVN: r152649
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/sparc/sol2-unwind.h458
-rw-r--r--gcc/config/sparc/sol2.h2
3 files changed, 467 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ef2b9a5..4ef144e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2009-10-11 Jose Ruiz <ruiz@adacore.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/33743
+ * config/sparc/sol2.h (MD_UNWIND_SUPPORT): Define.
+ * config/sparc/sol2-unwind.h: New file.
+
2009-10-11 Olivier Hainque <hainque@adacore.com>
Eric Botcazou <ebotcazou@adacore.com>
diff --git a/gcc/config/sparc/sol2-unwind.h b/gcc/config/sparc/sol2-unwind.h
new file mode 100644
index 0000000..c98dc4d
--- /dev/null
+++ b/gcc/config/sparc/sol2-unwind.h
@@ -0,0 +1,458 @@
+/* DWARF2 EH unwinding support for SPARC Solaris.
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#include <ucontext.h>
+
+#if defined(__arch64__)
+
+#define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state
+
+static _Unwind_Reason_Code
+sparc64_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ void *pc = context->ra;
+ void *this_cfa = context->cfa;
+ void *new_cfa, *ra_location, *shifted_ra_location;
+ int regs_off;
+ int fpu_save_off;
+ unsigned char fpu_save;
+ int i;
+
+ /* This is the observed pattern for the sigacthandler in Solaris 8. */
+ unsigned int sigacthandler_sol8_pattern []
+ = {0x9401400f, 0xca5aafa0, 0x913e2000, 0x892a3003,
+ 0xe0590005, 0x9fc40000, 0x9410001a, 0x80a6e008};
+
+ /* This is the observed pattern for the sigacthandler in Solaris 9. */
+ unsigned int sigacthandler_sol9_pattern []
+ = {0xa33e2000, 0x00000000, 0x892c7003, 0x90100011,
+ 0xe0590005, 0x9fc40000, 0x9410001a, 0x80a46008};
+
+ /* This is the observed pattern for the __sighndlr. */
+ unsigned int sighndlr_pattern []
+ = {0x9de3bf50, 0x90100018, 0x92100019, 0x9fc6c000,
+ 0x9410001a, 0x81c7e008, 0x81e80000};
+
+ /* Deal with frame-less function from which a signal was raised. */
+ if (_Unwind_IsSignalFrame (context))
+ {
+ /* The CFA is by definition unmodified in this case. */
+ fs->regs.cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_reg = __builtin_dwarf_sp_column ();
+ fs->regs.cfa_offset = 0;
+
+ /* This is the canonical RA column. */
+ fs->retaddr_column = 15;
+
+ return _URC_NO_REASON;
+ }
+
+ /* Look for the sigacthandler pattern. The pattern changes slightly
+ in different versions of the operating system, so we skip the
+ comparison against pc-(4*6) for Solaris 9. */
+ if (( *(unsigned int *)(pc-(4*7)) == sigacthandler_sol8_pattern[0]
+ && *(unsigned int *)(pc-(4*6)) == sigacthandler_sol8_pattern[1]
+ && *(unsigned int *)(pc-(4*5)) == sigacthandler_sol8_pattern[2]
+ && *(unsigned int *)(pc-(4*4)) == sigacthandler_sol8_pattern[3]
+ && *(unsigned int *)(pc-(4*3)) == sigacthandler_sol8_pattern[4]
+ && *(unsigned int *)(pc-(4*2)) == sigacthandler_sol8_pattern[5]
+ && *(unsigned int *)(pc-(4*1)) == sigacthandler_sol8_pattern[6]
+ && *(unsigned int *)(pc-(4*0)) == sigacthandler_sol8_pattern[7] ) ||
+ ( *(unsigned int *)(pc-(4*7)) == sigacthandler_sol9_pattern[0]
+ /* skip pc-(4*6) */
+ && *(unsigned int *)(pc-(4*5)) == sigacthandler_sol9_pattern[2]
+ && *(unsigned int *)(pc-(4*4)) == sigacthandler_sol9_pattern[3]
+ && *(unsigned int *)(pc-(4*3)) == sigacthandler_sol9_pattern[4]
+ && *(unsigned int *)(pc-(4*2)) == sigacthandler_sol9_pattern[5]
+ && *(unsigned int *)(pc-(4*1)) == sigacthandler_sol9_pattern[6]
+ && *(unsigned int *)(pc-(4*0)) == sigacthandler_sol9_pattern[7] ) )
+ /* We need to move up two frames (the kernel frame and the handler
+ frame). Minimum stack frame size is 176 bytes (128 + 48): 128
+ bytes for spilling register window (16 extended words for in
+ and local registers), and 6 extended words to store at least
+ 6 arguments to callees, The kernel frame and the sigacthandler
+ both have this minimal stack. The ucontext_t structure is after
+ this offset. */
+ regs_off = 176 + 176;
+
+ /* Look for the __sighndlr pattern. */
+ else if ( *(unsigned int *)(pc-(4*5)) == sighndlr_pattern[0]
+ && *(unsigned int *)(pc-(4*4)) == sighndlr_pattern[1]
+ && *(unsigned int *)(pc-(4*3)) == sighndlr_pattern[2]
+ && *(unsigned int *)(pc-(4*2)) == sighndlr_pattern[3]
+ && *(unsigned int *)(pc-(4*1)) == sighndlr_pattern[4]
+ && *(unsigned int *)(pc-(4*0)) == sighndlr_pattern[5]
+ && *(unsigned int *)(pc+(4*1)) == sighndlr_pattern[6] )
+ {
+ /* We have observed different calling frames among different
+ versions of the operating system, so that we need to
+ discriminate using the upper frame. We look for the return
+ address of the caller frame (there is an offset of 15 double
+ words between the frame address and the place where this return
+ address is stored) in order to do some more pattern matching. */
+ unsigned int cuh_pattern
+ = *(unsigned int *)(*(unsigned long *)(this_cfa + 15*8) - 4);
+
+ if (cuh_pattern == 0x9410001a || cuh_pattern == 0x94100013)
+ /* This matches the call_user_handler pattern for Solaris 9 and
+ for Solaris 8 running inside Solaris Containers respectively.
+ We need to move up four frames (the kernel frame, the signal
+ frame, the call_user_handler frame, the __sighndlr frame).
+ Three of them have the minimum stack frame size (kernel,
+ signal, and __sighndlr frames) of 176 bytes, and there is
+ another with a stack frame of 304 bytes (the call_user_handler
+ frame). The ucontext_t structure is after this offset. */
+ regs_off = 176 + 176 + 176 + 304;
+ else
+ /* We need to move up three frames (the kernel frame, the
+ sigacthandler frame, and the __sighndlr frame). The kernel
+ frame has a stack frame size of 176, the __sighndlr frames of
+ 304 bytes, and there is a stack frame of 176 bytes for the
+ sigacthandler frame. The ucontext_t structure is after this
+ offset. */
+ regs_off = 176 + 304 + 176;
+ }
+
+ /* Exit if the pattern at the return address does not match the
+ previous three patterns. */
+ else
+ return _URC_END_OF_STACK;
+
+ /* FPU information can be extracted from the ucontext_t structure
+ that is the third argument for the signal handler, that is saved
+ in the stack. There are 64 bytes between the beginning of the
+ ucontext_t argument of the signal handler and the uc_mcontext
+ field. There are 176 bytes between the beginning of uc_mcontext
+ and the beginning of the fpregs field. */
+ fpu_save_off = regs_off + (8*10) + 176;
+
+ /* The fpregs field contains 32 extended words at the beginning that
+ contain the fpu state. Then there are 2 extended words and two
+ bytes. */
+ fpu_save = *(unsigned char *)(this_cfa + fpu_save_off + (8*32) + (2*8) + 2);
+
+ /* We need to get the frame pointer for the kernel frame that
+ executes when the signal is raised. This frame is just the
+ following to the application code that generated the signal, so
+ that the later's stack pointer is the former's frame pointer.
+ The stack pointer for the interrupted application code can be
+ calculated from the ucontext_t structure (third argument for the
+ signal handler) that is saved in the stack. There are 10 words
+ between the beginning of the ucontext_t argument of the signal
+ handler and the uc_mcontext.gregs field that contains the
+ registers saved by the signal handler. */
+ new_cfa = *(void **)(this_cfa + regs_off + (8*10) + (REG_SP*8));
+ /* The frame address is %sp + STACK_BIAS in 64-bit mode. */
+ new_cfa += 2047;
+ fs->regs.cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_reg = __builtin_dwarf_sp_column ();
+ fs->regs.cfa_offset = new_cfa - this_cfa;
+
+ /* Restore global and out registers (in this order) from the
+ ucontext_t structure, uc_mcontext.gregs field. */
+ for (i = 1; i < 16; i++)
+ {
+ /* We never restore %sp as everything is purely CFA-based. */
+ if ((unsigned int) i == __builtin_dwarf_sp_column ())
+ continue;
+
+ /* First the global registers and then the out registers. */
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i].loc.offset
+ = this_cfa + regs_off + (8*10) + ((REG_Y+i)*8) - new_cfa;
+ }
+
+ /* Just above the stack pointer there are 16 extended words in which
+ the register window (in and local registers) was saved. */
+ for (i = 0; i < 16; i++)
+ {
+ fs->regs.reg[i + 16].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + 16].loc.offset = i*8;
+ }
+
+ /* Check whether we need to restore fpu registers. */
+ if (fpu_save)
+ {
+ for (i = 0; i < 64; i++)
+ {
+ if (i > 32 && (i & 1))
+ continue;
+
+ fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + 32].loc.offset
+ = this_cfa + fpu_save_off + (i*4) - new_cfa;
+ }
+ }
+
+ /* State the rules to find the kernel's code "return address", which is
+ the address of the active instruction when the signal was caught.
+ On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we
+ need to preventively subtract it from the purported return address. */
+ ra_location = this_cfa + regs_off + (8*10) + (REG_PC*8);
+ shifted_ra_location = this_cfa + regs_off + (8*10) + (REG_Y*8);
+ *(void **)shifted_ra_location = *(void **)ra_location - 8;
+ fs->retaddr_column = 0;
+ fs->regs.reg[0].how = REG_SAVED_OFFSET;
+ fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa;
+ fs->signal_frame = 1;
+
+ return _URC_NO_REASON;
+}
+
+#define MD_FROB_UPDATE_CONTEXT sparc64_frob_update_context
+
+static void
+sparc64_frob_update_context (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ /* The column of %sp contains the old CFA, not the old value of %sp.
+ The CFA offset already comprises the stack bias so, when %sp is the
+ CFA register, we must avoid counting the stack bias twice. Do not
+ do that for signal frames as the offset is artificial for them. */
+ if (fs->regs.cfa_reg == __builtin_dwarf_sp_column ()
+ && fs->regs.cfa_how == CFA_REG_OFFSET
+ && fs->regs.cfa_offset != 0
+ && !fs->signal_frame)
+ context->cfa -= 2047;
+}
+
+#else
+
+#define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state
+
+static _Unwind_Reason_Code
+sparc_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ void *pc = context->ra;
+ void *this_cfa = context->cfa;
+ void *new_cfa, *ra_location, *shifted_ra_location;
+ int regs_off;
+ int fpu_save_off;
+ unsigned char fpu_save;
+ int i;
+
+ /* This is the observed pattern for the sigacthandler. */
+ unsigned int sigacthandler_pattern []
+ = {0x9602400f, 0x92100019, 0x00000000, 0x912e2002,
+ 0xe002000a, 0x90100018, 0x9fc40000, 0x9410001a,
+ 0x80a62008};
+
+ /* This is the observed pattern for the __libthread_segvhdlr. */
+ unsigned int segvhdlr_pattern []
+ = {0x94102000, 0xe007bfe4, 0x9010001c, 0x92100019,
+ 0x9fc40000, 0x9410001a, 0x81c7e008, 0x81e80000,
+ 0x80a26000};
+
+ /* This is the observed pattern for the __sighndlr. */
+ unsigned int sighndlr_pattern []
+ = {0x9de3bfa0, 0x90100018, 0x92100019, 0x9fc6c000,
+ 0x9410001a, 0x81c7e008, 0x81e80000};
+
+ /* Deal with frame-less function from which a signal was raised. */
+ if (_Unwind_IsSignalFrame (context))
+ {
+ /* The CFA is by definition unmodified in this case. */
+ fs->regs.cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_reg = __builtin_dwarf_sp_column ();
+ fs->regs.cfa_offset = 0;
+
+ /* This is the canonical RA column. */
+ fs->retaddr_column = 15;
+
+ return _URC_NO_REASON;
+ }
+
+ /* Look for the sigacthandler pattern. The pattern changes slightly
+ in different versions of the operating system, so we skip the
+ comparison against pc-(4*6). */
+ if ( *(unsigned int *)(pc-(4*8)) == sigacthandler_pattern[0]
+ && *(unsigned int *)(pc-(4*7)) == sigacthandler_pattern[1]
+ /* skip pc-(4*6) */
+ && *(unsigned int *)(pc-(4*5)) == sigacthandler_pattern[3]
+ && *(unsigned int *)(pc-(4*4)) == sigacthandler_pattern[4]
+ && *(unsigned int *)(pc-(4*3)) == sigacthandler_pattern[5]
+ && *(unsigned int *)(pc-(4*2)) == sigacthandler_pattern[6]
+ && *(unsigned int *)(pc-(4*1)) == sigacthandler_pattern[7]
+ && *(unsigned int *)(pc-(4*0)) == sigacthandler_pattern[8] )
+ /* We need to move up two frames (the kernel frame and the handler
+ frame). Minimum stack frame size is 96 bytes (64 + 4 + 24): 64
+ bytes for spilling register window (16 words for in and local
+ registers), 4 bytes for a pointer to space for callees
+ returning structs, and 24 bytes to store at least six argument
+ to callees. The ucontext_t structure is after this offset. */
+ regs_off = 96 + 96;
+
+ /* Look for the __libthread_segvhdlr pattern. */
+ else if ( *(unsigned int *)(pc-(4*6)) == segvhdlr_pattern[0]
+ && *(unsigned int *)(pc-(4*5)) == segvhdlr_pattern[1]
+ && *(unsigned int *)(pc-(4*4)) == segvhdlr_pattern[2]
+ && *(unsigned int *)(pc-(4*3)) == segvhdlr_pattern[3]
+ && *(unsigned int *)(pc-(4*2)) == segvhdlr_pattern[4]
+ && *(unsigned int *)(pc-(4*1)) == segvhdlr_pattern[5]
+ && *(unsigned int *)(pc-(4*0)) == segvhdlr_pattern[6]
+ && *(unsigned int *)(pc+(4*1)) == segvhdlr_pattern[7]
+ && *(unsigned int *)(pc+(4*2)) == segvhdlr_pattern[8] )
+ /* We need to move up four frames (the kernel frame, the
+ sigacthandler frame, the __sighndlr frame, and the
+ __libthread_segvhdlr). Two of them have the minimum
+ stack frame size (kernel and __sighndlr frames) of 96 bytes,
+ other has a stack frame of 216 bytes (the sigacthandler frame),
+ and there is another with a stack frame of 128 bytes (the
+ __libthread_segvhdlr). The ucontext_t structure is after this
+ offset. */
+ regs_off = 96 + 96 + 128 + 216;
+
+ /* Look for the __sighndlr pattern. */
+ else if ( *(unsigned int *)(pc-(4*5)) == sighndlr_pattern[0]
+ && *(unsigned int *)(pc-(4*4)) == sighndlr_pattern[1]
+ && *(unsigned int *)(pc-(4*3)) == sighndlr_pattern[2]
+ && *(unsigned int *)(pc-(4*2)) == sighndlr_pattern[3]
+ && *(unsigned int *)(pc-(4*1)) == sighndlr_pattern[4]
+ && *(unsigned int *)(pc-(4*0)) == sighndlr_pattern[5]
+ && *(unsigned int *)(pc+(4*1)) == sighndlr_pattern[6] )
+ {
+ /* We have observed different calling frames among different
+ versions of the operating system, so that we need to
+ discriminate using the upper frame. We look for the return
+ address of the caller frame (there is an offset of 15 words
+ between the frame address and the place where this return
+ address is stored) in order to do some more pattern matching. */
+ unsigned int cuh_pattern
+ = *(unsigned int *)(*(unsigned int *)(this_cfa + 15*4) - 4);
+
+ if (cuh_pattern == 0xd407a04c)
+ /* This matches the call_user_handler pattern for Solaris 10.
+ We need to move up three frames (the kernel frame, the
+ call_user_handler frame, the __sighndlr frame). Two of them
+ have the minimum stack frame size (kernel and __sighndlr
+ frames) of 96 bytes, and there is another with a stack frame
+ of 160 bytes (the call_user_handler frame). The ucontext_t
+ structure is after this offset. */
+ regs_off = 96 + 96 + 160;
+ else if (cuh_pattern == 0x9410001a || cuh_pattern == 0x9410001b)
+ /* This matches the call_user_handler pattern for Solaris 9 and
+ for Solaris 8 running inside Solaris Containers respectively.
+ We need to move up four frames (the kernel frame, the signal
+ frame, the call_user_handler frame, the __sighndlr frame).
+ Three of them have the minimum stack frame size (kernel,
+ signal, and __sighndlr frames) of 96 bytes, and there is
+ another with a stack frame of 160 bytes (the call_user_handler
+ frame). The ucontext_t structure is after this offset. */
+ regs_off = 96 + 96 + 96 + 160;
+ else
+ /* We need to move up three frames (the kernel frame, the
+ sigacthandler frame, and the __sighndlr frame). Two of them
+ have the minimum stack frame size (kernel and __sighndlr
+ frames) of 96 bytes, and there is another with a stack frame
+ of 216 bytes (the sigacthandler frame). The ucontext_t
+ structure is after this offset. */
+ regs_off = 96 + 96 + 216;
+ }
+
+ /* Exit if the pattern at the return address does not match the
+ previous three patterns. */
+ else
+ return _URC_END_OF_STACK;
+
+ /* FPU information can be extracted from the ucontext_t structure
+ that is the third argument for the signal handler, that is saved
+ in the stack. There are 10 words between the beginning of the
+ ucontext_t argument of the signal handler and the uc_mcontext
+ field. There are 80 bytes between the beginning of uc_mcontext
+ and the beginning of the fpregs field. */
+ fpu_save_off = regs_off + (4*10) + (4*20);
+
+ /* The fpregs field contains 32 words at the beginning that contain
+ the fpu state. Then there are 2 words and two bytes. */
+ fpu_save = *(unsigned char *)(this_cfa + fpu_save_off + (4*32) + (2*4) + 2);
+
+ /* We need to get the frame pointer for the kernel frame that
+ executes when the signal is raised. This frame is just the
+ following to the application code that generated the signal, so
+ that the later's stack pointer is the former's frame pointer.
+ The stack pointer for the interrupted application code can be
+ calculated from the ucontext_t structure (third argument for the
+ signal handler) that is saved in the stack. There are 10 words
+ between the beginning of the ucontext_t argument of the signal
+ handler and the uc_mcontext.gregs field that contains the
+ registers saved by the signal handler. */
+ new_cfa = *(void **)(this_cfa + regs_off + (4*10) + (REG_SP*4));
+ fs->regs.cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_reg = __builtin_dwarf_sp_column ();
+ fs->regs.cfa_offset = new_cfa - this_cfa;
+
+ /* Restore global and out registers (in this order) from the
+ ucontext_t structure, uc_mcontext.gregs field. */
+ for (i = 1; i < 16; i++)
+ {
+ /* We never restore %sp as everything is purely CFA-based. */
+ if ((unsigned int) i == __builtin_dwarf_sp_column ())
+ continue;
+
+ /* First the global registers and then the out registers */
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i].loc.offset
+ = this_cfa + regs_off + (4*10) + ((REG_Y+i)*4) - new_cfa;
+ }
+
+ /* Just above the stack pointer there are 16 words in which the
+ register window (in and local registers) was saved. */
+ for (i = 0; i < 16; i++)
+ {
+ fs->regs.reg[i + 16].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + 16].loc.offset = i*4;
+ }
+
+ /* Check whether we need to restore fpu registers. */
+ if (fpu_save)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + 32].loc.offset
+ = this_cfa + fpu_save_off + (i*4) - new_cfa;
+ }
+ }
+
+ /* State the rules to find the kernel's code "return address", which is
+ the address of the active instruction when the signal was caught.
+ On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we
+ need to preventively subtract it from the purported return address. */
+ ra_location = this_cfa + regs_off + (4*10) + (REG_PC*4);
+ shifted_ra_location = this_cfa + regs_off + (4*10) + (REG_Y*4);
+ *(void **)shifted_ra_location = *(void **)ra_location - 8;
+ fs->retaddr_column = 0;
+ fs->regs.reg[0].how = REG_SAVED_OFFSET;
+ fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa;
+ fs->signal_frame = 1;
+
+ return _URC_NO_REASON;
+};
+
+#endif
diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h
index 139f5b3..a3f7647 100644
--- a/gcc/config/sparc/sol2.h
+++ b/gcc/config/sparc/sol2.h
@@ -194,3 +194,5 @@ along with GCC; see the file COPYING3. If not see
(SIZE), (ALIGN) / BITS_PER_UNIT); \
} \
while (0)
+
+#define MD_UNWIND_SUPPORT "config/sparc/sol2-unwind.h"