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