Home | History | Annotate | Line # | Download | only in sparc
linux-unwind.h revision 1.1.1.1.8.2
      1  1.1.1.1.8.2  tls /* DWARF2 EH unwinding support for SPARC Linux.
      2  1.1.1.1.8.2  tls    Copyright (C) 2004-2013 Free Software Foundation, Inc.
      3  1.1.1.1.8.2  tls 
      4  1.1.1.1.8.2  tls This file is part of GCC.
      5  1.1.1.1.8.2  tls 
      6  1.1.1.1.8.2  tls GCC is free software; you can redistribute it and/or modify
      7  1.1.1.1.8.2  tls it under the terms of the GNU General Public License as published by
      8  1.1.1.1.8.2  tls the Free Software Foundation; either version 3, or (at your option)
      9  1.1.1.1.8.2  tls any later version.
     10  1.1.1.1.8.2  tls 
     11  1.1.1.1.8.2  tls GCC is distributed in the hope that it will be useful,
     12  1.1.1.1.8.2  tls but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1.1.1.8.2  tls MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  1.1.1.1.8.2  tls GNU General Public License for more details.
     15  1.1.1.1.8.2  tls 
     16  1.1.1.1.8.2  tls Under Section 7 of GPL version 3, you are granted additional
     17  1.1.1.1.8.2  tls permissions described in the GCC Runtime Library Exception, version
     18  1.1.1.1.8.2  tls 3.1, as published by the Free Software Foundation.
     19  1.1.1.1.8.2  tls 
     20  1.1.1.1.8.2  tls You should have received a copy of the GNU General Public License and
     21  1.1.1.1.8.2  tls a copy of the GCC Runtime Library Exception along with this program;
     22  1.1.1.1.8.2  tls see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23  1.1.1.1.8.2  tls <http://www.gnu.org/licenses/>.  */
     24  1.1.1.1.8.2  tls 
     25  1.1.1.1.8.2  tls /* Do code reading to identify a signal frame, and set the frame
     26  1.1.1.1.8.2  tls    state data appropriately.  See unwind-dw2.c for the structs.  */
     27  1.1.1.1.8.2  tls 
     28  1.1.1.1.8.2  tls #if defined(__arch64__)
     29  1.1.1.1.8.2  tls 
     30  1.1.1.1.8.2  tls #undef STACK_BIAS
     31  1.1.1.1.8.2  tls #define STACK_BIAS 2047
     32  1.1.1.1.8.2  tls 
     33  1.1.1.1.8.2  tls /* 64-bit SPARC version */
     34  1.1.1.1.8.2  tls #define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state
     35  1.1.1.1.8.2  tls 
     36  1.1.1.1.8.2  tls static _Unwind_Reason_Code
     37  1.1.1.1.8.2  tls sparc64_fallback_frame_state (struct _Unwind_Context *context,
     38  1.1.1.1.8.2  tls 			      _Unwind_FrameState *fs)
     39  1.1.1.1.8.2  tls {
     40  1.1.1.1.8.2  tls   unsigned int *pc = context->ra;
     41  1.1.1.1.8.2  tls   long this_cfa = (long) context->cfa;
     42  1.1.1.1.8.2  tls   long new_cfa, ra_location, shifted_ra_location;
     43  1.1.1.1.8.2  tls   long regs_off, fpu_save_off;
     44  1.1.1.1.8.2  tls   long fpu_save;
     45  1.1.1.1.8.2  tls   int i;
     46  1.1.1.1.8.2  tls 
     47  1.1.1.1.8.2  tls   if (pc[0] != 0x82102065	/* mov NR_rt_sigreturn, %g1 */
     48  1.1.1.1.8.2  tls       || pc[1] != 0x91d0206d)	/* ta 0x6d */
     49  1.1.1.1.8.2  tls     return _URC_END_OF_STACK;
     50  1.1.1.1.8.2  tls 
     51  1.1.1.1.8.2  tls   regs_off = 192 + 128;
     52  1.1.1.1.8.2  tls   fpu_save_off = regs_off + (16 * 8) + (3 * 8) + (2 * 4);
     53  1.1.1.1.8.2  tls 
     54  1.1.1.1.8.2  tls   new_cfa = *(long *)(this_cfa + regs_off + (14 * 8));
     55  1.1.1.1.8.2  tls   /* The frame address is %sp + STACK_BIAS in 64-bit mode.  */
     56  1.1.1.1.8.2  tls   new_cfa += STACK_BIAS;
     57  1.1.1.1.8.2  tls   fpu_save = *(long *)(this_cfa + fpu_save_off);
     58  1.1.1.1.8.2  tls   fs->regs.cfa_how = CFA_REG_OFFSET;
     59  1.1.1.1.8.2  tls   fs->regs.cfa_reg = __builtin_dwarf_sp_column ();
     60  1.1.1.1.8.2  tls   fs->regs.cfa_offset = new_cfa - this_cfa;
     61  1.1.1.1.8.2  tls 
     62  1.1.1.1.8.2  tls   for (i = 1; i < 16; i++)
     63  1.1.1.1.8.2  tls     {
     64  1.1.1.1.8.2  tls       /* We never restore %sp as everything is purely CFA-based.  */
     65  1.1.1.1.8.2  tls       if ((unsigned int) i == __builtin_dwarf_sp_column ())
     66  1.1.1.1.8.2  tls 	continue;
     67  1.1.1.1.8.2  tls 
     68  1.1.1.1.8.2  tls       fs->regs.reg[i].how = REG_SAVED_OFFSET;
     69  1.1.1.1.8.2  tls       fs->regs.reg[i].loc.offset
     70  1.1.1.1.8.2  tls 	= this_cfa + regs_off + (i * 8) - new_cfa;
     71  1.1.1.1.8.2  tls     }
     72  1.1.1.1.8.2  tls   for (i = 0; i < 16; i++)
     73  1.1.1.1.8.2  tls     {
     74  1.1.1.1.8.2  tls       fs->regs.reg[i + 16].how = REG_SAVED_OFFSET;
     75  1.1.1.1.8.2  tls       fs->regs.reg[i + 16].loc.offset
     76  1.1.1.1.8.2  tls 	= this_cfa + (i * 8) - new_cfa;
     77  1.1.1.1.8.2  tls     }
     78  1.1.1.1.8.2  tls   if (fpu_save)
     79  1.1.1.1.8.2  tls     {
     80  1.1.1.1.8.2  tls       for (i = 0; i < 64; i++)
     81  1.1.1.1.8.2  tls 	{
     82  1.1.1.1.8.2  tls 	  if (i > 32 && (i & 0x1))
     83  1.1.1.1.8.2  tls 	    continue;
     84  1.1.1.1.8.2  tls 	  fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
     85  1.1.1.1.8.2  tls 	  fs->regs.reg[i + 32].loc.offset
     86  1.1.1.1.8.2  tls 	    = fpu_save + (i * 4) - new_cfa;
     87  1.1.1.1.8.2  tls 	}
     88  1.1.1.1.8.2  tls     }
     89  1.1.1.1.8.2  tls 
     90  1.1.1.1.8.2  tls   /* State the rules to find the kernel's code "return address", which is
     91  1.1.1.1.8.2  tls      the address of the active instruction when the signal was caught.
     92  1.1.1.1.8.2  tls      On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we
     93  1.1.1.1.8.2  tls      need to preventively subtract it from the purported return address.  */
     94  1.1.1.1.8.2  tls   ra_location = this_cfa + regs_off + 17 * 8;
     95  1.1.1.1.8.2  tls   shifted_ra_location = this_cfa + regs_off + 19 * 8; /* Y register */
     96  1.1.1.1.8.2  tls   *(long *)shifted_ra_location = *(long *)ra_location - 8;
     97  1.1.1.1.8.2  tls   fs->retaddr_column = 0;
     98  1.1.1.1.8.2  tls   fs->regs.reg[0].how = REG_SAVED_OFFSET;
     99  1.1.1.1.8.2  tls   fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa;
    100  1.1.1.1.8.2  tls   fs->signal_frame = 1;
    101  1.1.1.1.8.2  tls 
    102  1.1.1.1.8.2  tls   return _URC_NO_REASON;
    103  1.1.1.1.8.2  tls }
    104  1.1.1.1.8.2  tls 
    105  1.1.1.1.8.2  tls #define MD_FROB_UPDATE_CONTEXT sparc64_frob_update_context
    106  1.1.1.1.8.2  tls 
    107  1.1.1.1.8.2  tls static void
    108  1.1.1.1.8.2  tls sparc64_frob_update_context (struct _Unwind_Context *context,
    109  1.1.1.1.8.2  tls 			     _Unwind_FrameState *fs)
    110  1.1.1.1.8.2  tls {
    111  1.1.1.1.8.2  tls   /* The column of %sp contains the old CFA, not the old value of %sp.
    112  1.1.1.1.8.2  tls      The CFA offset already comprises the stack bias so, when %sp is the
    113  1.1.1.1.8.2  tls      CFA register, we must avoid counting the stack bias twice.  Do not
    114  1.1.1.1.8.2  tls      do that for signal frames as the offset is artificial for them.  */
    115  1.1.1.1.8.2  tls   if (fs->regs.cfa_reg == __builtin_dwarf_sp_column ()
    116  1.1.1.1.8.2  tls       && fs->regs.cfa_how == CFA_REG_OFFSET
    117  1.1.1.1.8.2  tls       && fs->regs.cfa_offset != 0
    118  1.1.1.1.8.2  tls       && !fs->signal_frame)
    119  1.1.1.1.8.2  tls     {
    120  1.1.1.1.8.2  tls       long i;
    121  1.1.1.1.8.2  tls 
    122  1.1.1.1.8.2  tls       context->cfa -= STACK_BIAS;
    123  1.1.1.1.8.2  tls 
    124  1.1.1.1.8.2  tls       for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i)
    125  1.1.1.1.8.2  tls 	if (fs->regs.reg[i].how == REG_SAVED_OFFSET)
    126  1.1.1.1.8.2  tls 	  _Unwind_SetGRPtr (context, i,
    127  1.1.1.1.8.2  tls 			    _Unwind_GetGRPtr (context, i) - STACK_BIAS);
    128  1.1.1.1.8.2  tls     }
    129  1.1.1.1.8.2  tls }
    130  1.1.1.1.8.2  tls 
    131  1.1.1.1.8.2  tls #else
    132  1.1.1.1.8.2  tls 
    133  1.1.1.1.8.2  tls /* 32-bit SPARC version */
    134  1.1.1.1.8.2  tls #define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state
    135  1.1.1.1.8.2  tls 
    136  1.1.1.1.8.2  tls static _Unwind_Reason_Code
    137  1.1.1.1.8.2  tls sparc_fallback_frame_state (struct _Unwind_Context *context,
    138  1.1.1.1.8.2  tls 			    _Unwind_FrameState *fs)
    139  1.1.1.1.8.2  tls {
    140  1.1.1.1.8.2  tls   unsigned int *pc = context->ra;
    141  1.1.1.1.8.2  tls   int this_cfa = (int) context->cfa;
    142  1.1.1.1.8.2  tls   int new_cfa, ra_location, shifted_ra_location;
    143  1.1.1.1.8.2  tls   int regs_off, fpu_save_off;
    144  1.1.1.1.8.2  tls   int fpu_save;
    145  1.1.1.1.8.2  tls   int old_style, i;
    146  1.1.1.1.8.2  tls 
    147  1.1.1.1.8.2  tls   if (pc[1] != 0x91d02010)	/* ta 0x10 */
    148  1.1.1.1.8.2  tls     return _URC_END_OF_STACK;
    149  1.1.1.1.8.2  tls 
    150  1.1.1.1.8.2  tls   if (pc[0] == 0x821020d8)	/* mov NR_sigreturn, %g1 */
    151  1.1.1.1.8.2  tls     old_style = 1;
    152  1.1.1.1.8.2  tls   else if (pc[0] == 0x82102065)	/* mov NR_rt_sigreturn, %g1 */
    153  1.1.1.1.8.2  tls     old_style = 0;
    154  1.1.1.1.8.2  tls   else
    155  1.1.1.1.8.2  tls     return _URC_END_OF_STACK;
    156  1.1.1.1.8.2  tls 
    157  1.1.1.1.8.2  tls   if (old_style)
    158  1.1.1.1.8.2  tls     {
    159  1.1.1.1.8.2  tls       regs_off = 96;
    160  1.1.1.1.8.2  tls       fpu_save_off = regs_off + (4 * 4) + (16 * 4);
    161  1.1.1.1.8.2  tls     }
    162  1.1.1.1.8.2  tls   else
    163  1.1.1.1.8.2  tls     {
    164  1.1.1.1.8.2  tls       regs_off = 96 + 128;
    165  1.1.1.1.8.2  tls       fpu_save_off = regs_off + (4 * 4) + (16 * 4) + (2 * 4);
    166  1.1.1.1.8.2  tls     }
    167  1.1.1.1.8.2  tls 
    168  1.1.1.1.8.2  tls   new_cfa = *(int *)(this_cfa + regs_off + (4 * 4) + (14 * 4));
    169  1.1.1.1.8.2  tls   fpu_save = *(int *)(this_cfa + fpu_save_off);
    170  1.1.1.1.8.2  tls   fs->regs.cfa_how = CFA_REG_OFFSET;
    171  1.1.1.1.8.2  tls   fs->regs.cfa_reg = __builtin_dwarf_sp_column ();
    172  1.1.1.1.8.2  tls   fs->regs.cfa_offset = new_cfa - this_cfa;
    173  1.1.1.1.8.2  tls 
    174  1.1.1.1.8.2  tls   for (i = 1; i < 16; i++)
    175  1.1.1.1.8.2  tls     {
    176  1.1.1.1.8.2  tls       /* We never restore %sp as everything is purely CFA-based.  */
    177  1.1.1.1.8.2  tls       if ((unsigned int) i == __builtin_dwarf_sp_column ())
    178  1.1.1.1.8.2  tls 	continue;
    179  1.1.1.1.8.2  tls 
    180  1.1.1.1.8.2  tls       fs->regs.reg[i].how = REG_SAVED_OFFSET;
    181  1.1.1.1.8.2  tls       fs->regs.reg[i].loc.offset
    182  1.1.1.1.8.2  tls 	= this_cfa + regs_off + (4 * 4) + (i * 4) - new_cfa;
    183  1.1.1.1.8.2  tls     }
    184  1.1.1.1.8.2  tls   for (i = 0; i < 16; i++)
    185  1.1.1.1.8.2  tls     {
    186  1.1.1.1.8.2  tls       fs->regs.reg[i + 16].how = REG_SAVED_OFFSET;
    187  1.1.1.1.8.2  tls       fs->regs.reg[i + 16].loc.offset
    188  1.1.1.1.8.2  tls 	= this_cfa + (i * 4) - new_cfa;
    189  1.1.1.1.8.2  tls     }
    190  1.1.1.1.8.2  tls   if (fpu_save)
    191  1.1.1.1.8.2  tls     {
    192  1.1.1.1.8.2  tls       for (i = 0; i < 32; i++)
    193  1.1.1.1.8.2  tls 	{
    194  1.1.1.1.8.2  tls 	  fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
    195  1.1.1.1.8.2  tls 	  fs->regs.reg[i + 32].loc.offset
    196  1.1.1.1.8.2  tls 	    = fpu_save + (i * 4) - new_cfa;
    197  1.1.1.1.8.2  tls 	}
    198  1.1.1.1.8.2  tls     }
    199  1.1.1.1.8.2  tls 
    200  1.1.1.1.8.2  tls   /* State the rules to find the kernel's code "return address", which is
    201  1.1.1.1.8.2  tls      the address of the active instruction when the signal was caught.
    202  1.1.1.1.8.2  tls      On the SPARC, since RETURN_ADDR_OFFSET (essentially 8) is defined, we
    203  1.1.1.1.8.2  tls      need to preventively subtract it from the purported return address.  */
    204  1.1.1.1.8.2  tls   ra_location = this_cfa + regs_off + 4;
    205  1.1.1.1.8.2  tls   shifted_ra_location = this_cfa + regs_off + 3 * 4; /* Y register */
    206  1.1.1.1.8.2  tls   *(int *)shifted_ra_location = *(int *)ra_location - 8;
    207  1.1.1.1.8.2  tls   fs->retaddr_column = 0;
    208  1.1.1.1.8.2  tls   fs->regs.reg[0].how = REG_SAVED_OFFSET;
    209  1.1.1.1.8.2  tls   fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa;
    210  1.1.1.1.8.2  tls   fs->signal_frame = 1;
    211  1.1.1.1.8.2  tls 
    212  1.1.1.1.8.2  tls   return _URC_NO_REASON;
    213  1.1.1.1.8.2  tls }
    214  1.1.1.1.8.2  tls 
    215  1.1.1.1.8.2  tls #endif
    216