0
|
1 /* DWARF2 EH unwinding support for SPARC Linux.
|
|
2 Copyright 2004, 2005, 2009 Free Software Foundation, Inc.
|
|
3
|
|
4 This file is part of GCC.
|
|
5
|
|
6 GCC is free software; you can redistribute it and/or modify
|
|
7 it under the terms of the GNU General Public License as published by
|
|
8 the Free Software Foundation; either version 3, or (at your option)
|
|
9 any later version.
|
|
10
|
|
11 GCC is distributed in the hope that it will be useful,
|
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 GNU General Public License for more details.
|
|
15
|
|
16 Under Section 7 of GPL version 3, you are granted additional
|
|
17 permissions described in the GCC Runtime Library Exception, version
|
|
18 3.1, as published by the Free Software Foundation.
|
|
19
|
|
20 You should have received a copy of the GNU General Public License and
|
|
21 a copy of the GCC Runtime Library Exception along with this program;
|
|
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
23 <http://www.gnu.org/licenses/>. */
|
|
24
|
|
25
|
|
26 /* Do code reading to identify a signal frame, and set the frame
|
|
27 state data appropriately. See unwind-dw2.c for the structs. */
|
|
28
|
|
29 /* Handle multilib correctly. */
|
|
30 #if defined(__arch64__)
|
|
31
|
|
32 /* 64-bit SPARC version */
|
|
33 #define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state
|
|
34
|
|
35 static _Unwind_Reason_Code
|
|
36 sparc64_fallback_frame_state (struct _Unwind_Context *context,
|
|
37 _Unwind_FrameState *fs)
|
|
38 {
|
|
39 unsigned int *pc = context->ra;
|
|
40 long new_cfa, i;
|
|
41 long regs_off, fpu_save_off;
|
|
42 long this_cfa, fpu_save;
|
|
43
|
|
44 if (pc[0] != 0x82102065 /* mov NR_rt_sigreturn, %g1 */
|
|
45 || pc[1] != 0x91d0206d) /* ta 0x6d */
|
|
46 return _URC_END_OF_STACK;
|
|
47 regs_off = 192 + 128;
|
|
48 fpu_save_off = regs_off + (16 * 8) + (3 * 8) + (2 * 4);
|
|
49 this_cfa = (long) context->cfa;
|
|
50 new_cfa = *(long *)((context->cfa) + (regs_off + (14 * 8)));
|
|
51 new_cfa += 2047; /* Stack bias */
|
|
52 fpu_save = *(long *)((this_cfa) + (fpu_save_off));
|
|
53 fs->regs.cfa_how = CFA_REG_OFFSET;
|
|
54 fs->regs.cfa_reg = 14;
|
|
55 fs->regs.cfa_offset = new_cfa - (long) context->cfa;
|
|
56 for (i = 1; i < 16; ++i)
|
|
57 {
|
|
58 fs->regs.reg[i].how = REG_SAVED_OFFSET;
|
|
59 fs->regs.reg[i].loc.offset =
|
|
60 this_cfa + (regs_off + (i * 8)) - new_cfa;
|
|
61 }
|
|
62 for (i = 0; i < 16; ++i)
|
|
63 {
|
|
64 fs->regs.reg[i + 16].how = REG_SAVED_OFFSET;
|
|
65 fs->regs.reg[i + 16].loc.offset =
|
|
66 this_cfa + (i * 8) - new_cfa;
|
|
67 }
|
|
68 if (fpu_save)
|
|
69 {
|
|
70 for (i = 0; i < 64; ++i)
|
|
71 {
|
|
72 if (i > 32 && (i & 0x1))
|
|
73 continue;
|
|
74 fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
|
|
75 fs->regs.reg[i + 32].loc.offset =
|
|
76 (fpu_save + (i * 4)) - new_cfa;
|
|
77 }
|
|
78 }
|
|
79 /* Stick return address into %g0, same trick Alpha uses. */
|
|
80 fs->regs.reg[0].how = REG_SAVED_OFFSET;
|
|
81 fs->regs.reg[0].loc.offset =
|
|
82 this_cfa + (regs_off + (16 * 8) + 8) - new_cfa;
|
|
83 fs->retaddr_column = 0;
|
|
84 return _URC_NO_REASON;
|
|
85 }
|
|
86
|
|
87 #else
|
|
88
|
|
89 /* 32-bit SPARC version */
|
|
90 #define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state
|
|
91
|
|
92 static _Unwind_Reason_Code
|
|
93 sparc_fallback_frame_state (struct _Unwind_Context *context,
|
|
94 _Unwind_FrameState *fs)
|
|
95 {
|
|
96 unsigned int *pc = context->ra;
|
|
97 int new_cfa, i, oldstyle;
|
|
98 int regs_off, fpu_save_off;
|
|
99 int fpu_save, this_cfa;
|
|
100
|
|
101 if (pc[1] != 0x91d02010) /* ta 0x10 */
|
|
102 return _URC_END_OF_STACK;
|
|
103 if (pc[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */
|
|
104 oldstyle = 1;
|
|
105 else if (pc[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */
|
|
106 oldstyle = 0;
|
|
107 else
|
|
108 return _URC_END_OF_STACK;
|
|
109 if (oldstyle)
|
|
110 {
|
|
111 regs_off = 96;
|
|
112 fpu_save_off = regs_off + (4 * 4) + (16 * 4);
|
|
113 }
|
|
114 else
|
|
115 {
|
|
116 regs_off = 96 + 128;
|
|
117 fpu_save_off = regs_off + (4 * 4) + (16 * 4) + (2 * 4);
|
|
118 }
|
|
119 this_cfa = (int) context->cfa;
|
|
120 new_cfa = *(int *)((context->cfa) + (regs_off+(4*4)+(14 * 4)));
|
|
121 fpu_save = *(int *)((this_cfa) + (fpu_save_off));
|
|
122 fs->regs.cfa_how = CFA_REG_OFFSET;
|
|
123 fs->regs.cfa_reg = 14;
|
|
124 fs->regs.cfa_offset = new_cfa - (int) context->cfa;
|
|
125 for (i = 1; i < 16; ++i)
|
|
126 {
|
|
127 if (i == 14)
|
|
128 continue;
|
|
129 fs->regs.reg[i].how = REG_SAVED_OFFSET;
|
|
130 fs->regs.reg[i].loc.offset =
|
|
131 this_cfa + (regs_off+(4 * 4)+(i * 4)) - new_cfa;
|
|
132 }
|
|
133 for (i = 0; i < 16; ++i)
|
|
134 {
|
|
135 fs->regs.reg[i + 16].how = REG_SAVED_OFFSET;
|
|
136 fs->regs.reg[i + 16].loc.offset =
|
|
137 this_cfa + (i * 4) - new_cfa;
|
|
138 }
|
|
139 if (fpu_save)
|
|
140 {
|
|
141 for (i = 0; i < 32; ++i)
|
|
142 {
|
|
143 fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
|
|
144 fs->regs.reg[i + 32].loc.offset =
|
|
145 (fpu_save + (i * 4)) - new_cfa;
|
|
146 }
|
|
147 }
|
|
148 /* Stick return address into %g0, same trick Alpha uses. */
|
|
149 fs->regs.reg[0].how = REG_SAVED_OFFSET;
|
|
150 fs->regs.reg[0].loc.offset = this_cfa+(regs_off+4)-new_cfa;
|
|
151 fs->retaddr_column = 0;
|
|
152 return _URC_NO_REASON;
|
|
153 }
|
|
154
|
|
155 #endif
|