Commit | Line | Data |
---|---|---|
386c036b MK |
1 | /* Target-dependent code for GNU/Linux SPARC. |
2 | ||
ee8aef23 | 3 | Copyright 2003, 2004 Free Software Foundation, Inc. |
386c036b MK |
4 | |
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | Boston, MA 02111-1307, USA. */ | |
21 | ||
22 | #include "defs.h" | |
23 | #include "floatformat.h" | |
24 | #include "frame.h" | |
25 | #include "frame-unwind.h" | |
26 | #include "gdbarch.h" | |
27 | #include "gdbcore.h" | |
28 | #include "osabi.h" | |
29 | #include "regcache.h" | |
30 | #include "solib-svr4.h" | |
31 | #include "symtab.h" | |
32 | #include "trad-frame.h" | |
33 | ||
34 | #include "gdb_assert.h" | |
35 | #include "gdb_string.h" | |
36 | ||
37 | #include "sparc-tdep.h" | |
38 | ||
39 | /* Recognizing signal handler frames. */ | |
40 | ||
41 | /* GNU/Linux has two flavors of signals. Normal signal handlers, and | |
42 | "realtime" (RT) signals. The RT signals can provide additional | |
43 | information to the signal handler if the SA_SIGINFO flag is set | |
44 | when establishing a signal handler using `sigaction'. It is not | |
45 | unlikely that future versions of GNU/Linux will support SA_SIGINFO | |
46 | for normal signals too. */ | |
47 | ||
48 | /* When the sparc Linux kernel calls a signal handler and the | |
49 | SA_RESTORER flag isn't set, the return address points to a bit of | |
50 | code on the stack. This function returns whether the PC appears to | |
51 | be within this bit of code. | |
52 | ||
53 | The instruction sequence for normal signals is | |
54 | mov __NR_sigreturn, %g1 ! hex: 0x821020d8 | |
55 | ta 0x10 ! hex: 0x91d02010 | |
56 | ||
57 | Checking for the code sequence should be somewhat reliable, because | |
58 | the effect is to call the system call sigreturn. This is unlikely | |
59 | to occur anywhere other than a signal trampoline. | |
60 | ||
61 | It kind of sucks that we have to read memory from the process in | |
62 | order to identify a signal trampoline, but there doesn't seem to be | |
63 | any other way. However, sparc32_linux_pc_in_sigtramp arranges to | |
64 | only call us if no function name could be identified, which should | |
65 | be the case since the code is on the stack. */ | |
66 | ||
67 | #define LINUX32_SIGTRAMP_INSN0 0x821020d8 /* mov __NR_sigreturn, %g1 */ | |
68 | #define LINUX32_SIGTRAMP_INSN1 0x91d02010 /* ta 0x10 */ | |
69 | ||
70 | /* The instruction sequence for RT signals is | |
71 | mov __NR_rt_sigreturn, %g1 ! hex: 0x82102065 | |
72 | ta {0x10,0x6d} ! hex: 0x91d02010 or 0x91d0206d | |
73 | ||
74 | The effect is to call the system call rt_sigreturn. The trap number | |
75 | is variable based upon whether this is a 32-bit or 64-bit sparc binary. | |
76 | Note that 64-bit binaries only use this RT signal return method. */ | |
77 | ||
78 | #define LINUX32_RT_SIGTRAMP_INSN0 0x82102065 | |
79 | #define LINUX32_RT_SIGTRAMP_INSN1 0x91d02010 | |
80 | ||
81 | /* If PC is in a sigtramp routine consisting of the instructions INSN0 | |
82 | and INSN1, return the address of the start of the routine. | |
83 | Otherwise, return 0. */ | |
84 | ||
85 | CORE_ADDR | |
ee8aef23 MK |
86 | sparc_linux_sigtramp_start (struct frame_info *next_frame, |
87 | ULONGEST insn0, ULONGEST insn1) | |
386c036b | 88 | { |
ee8aef23 | 89 | CORE_ADDR pc = frame_pc_unwind (next_frame); |
386c036b | 90 | ULONGEST word0, word1; |
ee8aef23 | 91 | unsigned char buf[8]; /* Two instructions. */ |
386c036b MK |
92 | |
93 | /* We only recognize a signal trampoline if PC is at the start of | |
94 | one of the instructions. We optimize for finding the PC at the | |
95 | start of the instruction sequence, as will be the case when the | |
96 | trampoline is not the first frame on the stack. We assume that | |
97 | in the case where the PC is not at the start of the instruction | |
98 | sequence, there will be a few trailing readable bytes on the | |
99 | stack. */ | |
100 | ||
ee8aef23 | 101 | if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf)) |
386c036b MK |
102 | return 0; |
103 | ||
104 | word0 = extract_unsigned_integer (buf, 4); | |
105 | if (word0 != insn0) | |
106 | { | |
107 | if (word0 != insn1) | |
108 | return 0; | |
109 | ||
110 | pc -= 4; | |
ee8aef23 | 111 | if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf)) |
386c036b MK |
112 | return 0; |
113 | ||
114 | word0 = extract_unsigned_integer (buf, 4); | |
115 | } | |
116 | ||
117 | word1 = extract_unsigned_integer (buf + 4, 4); | |
118 | if (word0 != insn0 || word1 != insn1) | |
119 | return 0; | |
120 | ||
121 | return pc; | |
122 | } | |
123 | ||
124 | static CORE_ADDR | |
ee8aef23 | 125 | sparc32_linux_sigtramp_start (struct frame_info *next_frame) |
386c036b | 126 | { |
ee8aef23 | 127 | return sparc_linux_sigtramp_start (next_frame, LINUX32_SIGTRAMP_INSN0, |
386c036b MK |
128 | LINUX32_SIGTRAMP_INSN1); |
129 | } | |
130 | ||
131 | static CORE_ADDR | |
ee8aef23 | 132 | sparc32_linux_rt_sigtramp_start (struct frame_info *next_frame) |
386c036b | 133 | { |
ee8aef23 | 134 | return sparc_linux_sigtramp_start (next_frame, LINUX32_RT_SIGTRAMP_INSN0, |
386c036b MK |
135 | LINUX32_RT_SIGTRAMP_INSN1); |
136 | } | |
137 | ||
138 | static int | |
ee8aef23 | 139 | sparc32_linux_sigtramp_p (struct frame_info *next_frame) |
386c036b | 140 | { |
ee8aef23 MK |
141 | CORE_ADDR pc = frame_pc_unwind (next_frame); |
142 | char *name; | |
143 | ||
144 | find_pc_partial_function (pc, &name, NULL, NULL); | |
145 | ||
386c036b MK |
146 | /* If we have NAME, we can optimize the search. The trampolines are |
147 | named __restore and __restore_rt. However, they aren't dynamically | |
148 | exported from the shared C library, so the trampoline may appear to | |
149 | be part of the preceding function. This should always be sigaction, | |
150 | __sigaction, or __libc_sigaction (all aliases to the same function). */ | |
151 | if (name == NULL || strstr (name, "sigaction") != NULL) | |
ee8aef23 MK |
152 | return (sparc32_linux_sigtramp_start (next_frame) != 0 |
153 | || sparc32_linux_rt_sigtramp_start (next_frame) != 0); | |
386c036b MK |
154 | |
155 | return (strcmp ("__restore", name) == 0 | |
156 | || strcmp ("__restore_rt", name) == 0); | |
157 | } | |
158 | ||
159 | static struct sparc_frame_cache * | |
160 | sparc32_linux_sigtramp_frame_cache (struct frame_info *next_frame, | |
161 | void **this_cache) | |
162 | { | |
163 | struct sparc_frame_cache *cache; | |
164 | CORE_ADDR sigcontext_addr, addr; | |
165 | int regnum; | |
166 | ||
167 | if (*this_cache) | |
168 | return *this_cache; | |
169 | ||
170 | cache = sparc32_frame_cache (next_frame, this_cache); | |
171 | gdb_assert (cache == *this_cache); | |
172 | ||
173 | /* ??? What about signal trampolines that aren't frameless? */ | |
174 | regnum = SPARC_SP_REGNUM; | |
175 | cache->base = frame_unwind_register_unsigned (next_frame, regnum); | |
176 | ||
177 | regnum = SPARC_O1_REGNUM; | |
178 | sigcontext_addr = frame_unwind_register_unsigned (next_frame, regnum); | |
179 | ||
ee8aef23 | 180 | addr = sparc32_linux_sigtramp_start (next_frame); |
386c036b MK |
181 | if (addr == 0) |
182 | { | |
183 | /* If this is a RT signal trampoline, adjust SIGCONTEXT_ADDR | |
184 | accordingly. */ | |
ee8aef23 | 185 | addr = sparc32_linux_rt_sigtramp_start (next_frame); |
386c036b MK |
186 | if (addr) |
187 | sigcontext_addr += 128; | |
188 | else | |
189 | addr = frame_func_unwind (next_frame); | |
190 | } | |
191 | cache->pc = addr; | |
192 | ||
193 | cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); | |
194 | ||
195 | cache->saved_regs[SPARC32_PSR_REGNUM].addr = sigcontext_addr + 0; | |
196 | cache->saved_regs[SPARC32_PC_REGNUM].addr = sigcontext_addr + 4; | |
197 | cache->saved_regs[SPARC32_NPC_REGNUM].addr = sigcontext_addr + 8; | |
198 | cache->saved_regs[SPARC32_Y_REGNUM].addr = sigcontext_addr + 12; | |
199 | ||
200 | /* Since %g0 is always zero, keep the identity encoding. */ | |
201 | for (regnum = SPARC_G1_REGNUM, addr = sigcontext_addr + 20; | |
202 | regnum <= SPARC_O7_REGNUM; regnum++, addr += 4) | |
203 | cache->saved_regs[regnum].addr = addr; | |
204 | ||
205 | for (regnum = SPARC_L0_REGNUM, addr = cache->base; | |
206 | regnum <= SPARC_I7_REGNUM; regnum++, addr += 4) | |
207 | cache->saved_regs[regnum].addr = addr; | |
208 | ||
209 | return cache; | |
210 | } | |
211 | ||
212 | static void | |
213 | sparc32_linux_sigtramp_frame_this_id (struct frame_info *next_frame, | |
214 | void **this_cache, | |
215 | struct frame_id *this_id) | |
216 | { | |
217 | struct sparc_frame_cache *cache = | |
218 | sparc32_linux_sigtramp_frame_cache (next_frame, this_cache); | |
219 | ||
220 | (*this_id) = frame_id_build (cache->base, cache->pc); | |
221 | } | |
222 | ||
223 | static void | |
224 | sparc32_linux_sigtramp_frame_prev_register (struct frame_info *next_frame, | |
225 | void **this_cache, | |
226 | int regnum, int *optimizedp, | |
227 | enum lval_type *lvalp, | |
228 | CORE_ADDR *addrp, | |
229 | int *realnump, void *valuep) | |
230 | { | |
231 | struct sparc_frame_cache *cache = | |
232 | sparc32_linux_sigtramp_frame_cache (next_frame, this_cache); | |
233 | ||
1f67027d AC |
234 | trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, |
235 | optimizedp, lvalp, addrp, realnump, valuep); | |
386c036b MK |
236 | } |
237 | ||
238 | static const struct frame_unwind sparc32_linux_sigtramp_frame_unwind = | |
239 | { | |
240 | SIGTRAMP_FRAME, | |
241 | sparc32_linux_sigtramp_frame_this_id, | |
242 | sparc32_linux_sigtramp_frame_prev_register | |
243 | }; | |
244 | ||
245 | static const struct frame_unwind * | |
246 | sparc32_linux_sigtramp_frame_sniffer (struct frame_info *next_frame) | |
247 | { | |
ee8aef23 | 248 | if (sparc32_linux_sigtramp_p (next_frame)) |
386c036b MK |
249 | return &sparc32_linux_sigtramp_frame_unwind; |
250 | ||
251 | return NULL; | |
252 | } | |
253 | \f | |
254 | ||
386c036b MK |
255 | static void |
256 | sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | |
257 | { | |
258 | /* GNU/Linux is very similar to Solaris ... */ | |
259 | sparc32_sol2_init_abi (info, gdbarch); | |
260 | ||
261 | /* ... but doesn't have kernel-assisted single-stepping support. */ | |
262 | set_gdbarch_software_single_step (gdbarch, sparc_software_single_step); | |
263 | ||
264 | /* GNU/Linux doesn't support the 128-bit `long double' from the psABI. */ | |
265 | set_gdbarch_long_double_bit (gdbarch, 64); | |
266 | set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big); | |
267 | ||
386c036b | 268 | frame_unwind_append_sniffer (gdbarch, sparc32_linux_sigtramp_frame_sniffer); |
386c036b MK |
269 | } |
270 | ||
271 | /* Provide a prototype to silence -Wmissing-prototypes. */ | |
272 | extern void _initialize_sparc_linux_tdep (void); | |
273 | ||
274 | void | |
275 | _initialize_sparc_linux_tdep (void) | |
276 | { | |
277 | gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_LINUX, | |
278 | sparc32_linux_init_abi); | |
279 | } |