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