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