* NEWS: Mention ARM VFP support.
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-arm-low.c
CommitLineData
0a30fbc4 1/* GNU/Linux/ARM specific low level interface, for the remote server for GDB.
9308fc88 2 Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
0fb0cc75 3 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
0a30fbc4
DJ
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
0a30fbc4
DJ
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
0a30fbc4
DJ
19
20#include "server.h"
58caa3dc 21#include "linux-low.h"
0a30fbc4 22
58d6951d 23#include <elf.h>
9308fc88
DJ
24#include <sys/ptrace.h>
25
26#include "gdb_proc_service.h"
27
58d6951d 28/* Defined in auto-generated files. */
d05b4ac3 29void init_registers_arm (void);
d05b4ac3 30void init_registers_arm_with_iwmmxt (void);
58d6951d
DJ
31void init_registers_arm_with_vfpv2 (void);
32void init_registers_arm_with_vfpv3 (void);
33void init_registers_arm_with_neon (void);
d05b4ac3 34
9308fc88
DJ
35#ifndef PTRACE_GET_THREAD_AREA
36#define PTRACE_GET_THREAD_AREA 22
37#endif
38
fb1e4ffc
DJ
39#ifndef PTRACE_GETWMMXREGS
40# define PTRACE_GETWMMXREGS 18
41# define PTRACE_SETWMMXREGS 19
42#endif
43
58d6951d
DJ
44#ifndef PTRACE_GETVFPREGS
45# define PTRACE_GETVFPREGS 27
46# define PTRACE_SETVFPREGS 28
47#endif
48
49static unsigned long arm_hwcap;
50
51/* These are in <asm/elf.h> in current kernels. */
52#define HWCAP_VFP 64
53#define HWCAP_IWMMXT 512
54#define HWCAP_NEON 4096
55#define HWCAP_VFPv3 8192
56#define HWCAP_VFPv3D16 16384
57
0a30fbc4
DJ
58#ifdef HAVE_SYS_REG_H
59#include <sys/reg.h>
60#endif
61
23ce3b1c 62#define arm_num_regs 26
0a30fbc4 63
2ec06d2e 64static int arm_regmap[] = {
0a30fbc4
DJ
65 0, 4, 8, 12, 16, 20, 24, 28,
66 32, 36, 40, 44, 48, 52, 56, 60,
23ce3b1c
DJ
67 -1, -1, -1, -1, -1, -1, -1, -1, -1,
68 64
0a30fbc4
DJ
69};
70
2ec06d2e
DJ
71static int
72arm_cannot_store_register (int regno)
0a30fbc4 73{
2ec06d2e 74 return (regno >= arm_num_regs);
0a30fbc4
DJ
75}
76
2ec06d2e
DJ
77static int
78arm_cannot_fetch_register (int regno)
0a30fbc4 79{
2ec06d2e 80 return (regno >= arm_num_regs);
0a30fbc4
DJ
81}
82
fb1e4ffc
DJ
83static void
84arm_fill_gregset (void *buf)
85{
86 int i;
87
88 for (i = 0; i < arm_num_regs; i++)
89 if (arm_regmap[i] != -1)
90 collect_register (i, ((char *) buf) + arm_regmap[i]);
91}
92
93static void
94arm_store_gregset (const void *buf)
95{
96 int i;
97 char zerobuf[8];
98
99 memset (zerobuf, 0, 8);
100 for (i = 0; i < arm_num_regs; i++)
101 if (arm_regmap[i] != -1)
102 supply_register (i, ((char *) buf) + arm_regmap[i]);
103 else
104 supply_register (i, zerobuf);
105}
106
fb1e4ffc
DJ
107static void
108arm_fill_wmmxregset (void *buf)
109{
110 int i;
111
58d6951d
DJ
112 if (!(arm_hwcap & HWCAP_IWMMXT))
113 return;
114
fb1e4ffc
DJ
115 for (i = 0; i < 16; i++)
116 collect_register (arm_num_regs + i, (char *) buf + i * 8);
117
118 /* We only have access to wcssf, wcasf, and wcgr0-wcgr3. */
119 for (i = 0; i < 6; i++)
120 collect_register (arm_num_regs + i + 16, (char *) buf + 16 * 8 + i * 4);
121}
122
123static void
124arm_store_wmmxregset (const void *buf)
125{
126 int i;
127
58d6951d
DJ
128 if (!(arm_hwcap & HWCAP_IWMMXT))
129 return;
130
fb1e4ffc
DJ
131 for (i = 0; i < 16; i++)
132 supply_register (arm_num_regs + i, (char *) buf + i * 8);
133
134 /* We only have access to wcssf, wcasf, and wcgr0-wcgr3. */
135 for (i = 0; i < 6; i++)
136 supply_register (arm_num_regs + i + 16, (char *) buf + 16 * 8 + i * 4);
137}
138
58d6951d
DJ
139static void
140arm_fill_vfpregset (void *buf)
141{
142 int i, num, base;
143
144 if (!(arm_hwcap & HWCAP_VFP))
145 return;
146
147 if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
148 num = 32;
149 else
150 num = 16;
151
152 base = find_regno ("d0");
153 for (i = 0; i < num; i++)
154 collect_register (base + i, (char *) buf + i * 8);
155
156 collect_register_by_name ("fpscr", (char *) buf + 32 * 8);
157}
158
159static void
160arm_store_vfpregset (const void *buf)
161{
162 int i, num, base;
163
164 if (!(arm_hwcap & HWCAP_VFP))
165 return;
166
167 if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
168 num = 32;
169 else
170 num = 16;
171
172 base = find_regno ("d0");
173 for (i = 0; i < num; i++)
174 supply_register (base + i, (char *) buf + i * 8);
175
176 supply_register_by_name ("fpscr", (char *) buf + 32 * 8);
177}
fb1e4ffc 178
d677d77d
DJ
179extern int debug_threads;
180
0d62e5e8
DJ
181static CORE_ADDR
182arm_get_pc ()
183{
184 unsigned long pc;
185 collect_register_by_name ("pc", &pc);
d677d77d
DJ
186 if (debug_threads)
187 fprintf (stderr, "stop pc is %08lx\n", pc);
0d62e5e8
DJ
188 return pc;
189}
190
191static void
192arm_set_pc (CORE_ADDR pc)
193{
194 unsigned long newpc = pc;
195 supply_register_by_name ("pc", &newpc);
196}
197
aeb75bf5 198/* Correct in either endianness. */
0d62e5e8
DJ
199static const unsigned long arm_breakpoint = 0xef9f0001;
200#define arm_breakpoint_len 4
aeb75bf5
DJ
201static const unsigned short thumb_breakpoint = 0xde01;
202#define thumb_breakpoint_len 2
0d62e5e8 203
9d1fb177
DJ
204/* For new EABI binaries. We recognize it regardless of which ABI
205 is used for gdbserver, so single threaded debugging should work
206 OK, but for multi-threaded debugging we only insert the current
207 ABI's breakpoint instruction. For now at least. */
208static const unsigned long arm_eabi_breakpoint = 0xe7f001f0;
209
0d62e5e8
DJ
210static int
211arm_breakpoint_at (CORE_ADDR where)
212{
aeb75bf5 213 unsigned long cpsr;
0d62e5e8 214
aeb75bf5 215 collect_register_by_name ("cpsr", &cpsr);
0d62e5e8 216
aeb75bf5
DJ
217 if (cpsr & 0x20)
218 {
219 /* Thumb mode. */
220 unsigned short insn;
9d1fb177 221
aeb75bf5
DJ
222 (*the_target->read_memory) (where, (unsigned char *) &insn, 2);
223 if (insn == thumb_breakpoint)
224 return 1;
225 }
226 else
227 {
228 /* ARM mode. */
229 unsigned long insn;
230
231 (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
232 if (insn == arm_breakpoint)
233 return 1;
234
235 if (insn == arm_eabi_breakpoint)
236 return 1;
237 }
9d1fb177 238
0d62e5e8
DJ
239 return 0;
240}
241
3b2fc2ea
DJ
242/* We only place breakpoints in empty marker functions, and thread locking
243 is outside of the function. So rather than importing software single-step,
244 we can just run until exit. */
245static CORE_ADDR
246arm_reinsert_addr ()
247{
248 unsigned long pc;
249 collect_register_by_name ("lr", &pc);
250 return pc;
251}
252
9308fc88
DJ
253/* Fetch the thread-local storage pointer for libthread_db. */
254
255ps_err_e
256ps_get_thread_area (const struct ps_prochandle *ph,
1b3f6016 257 lwpid_t lwpid, int idx, void **base)
9308fc88
DJ
258{
259 if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
260 return PS_ERR;
261
262 /* IDX is the bias from the thread pointer to the beginning of the
263 thread descriptor. It has to be subtracted due to implementation
264 quirks in libthread_db. */
265 *base = (void *) ((char *)*base - idx);
266
267 return PS_OK;
268}
269
58d6951d
DJ
270static int
271arm_get_hwcap (unsigned long *valp)
272{
273 unsigned char *data = alloca (8);
274 int offset = 0;
275
276 while ((*the_target->read_auxv) (offset, data, 8) == 8)
277 {
278 unsigned int *data_p = (unsigned int *)data;
279 if (data_p[0] == AT_HWCAP)
280 {
281 *valp = data_p[1];
282 return 1;
283 }
284
285 offset += 8;
286 }
287
288 *valp = 0;
289 return 0;
290}
291
292static void
293arm_arch_setup (void)
294{
295 arm_hwcap = 0;
296 if (arm_get_hwcap (&arm_hwcap) == 0)
297 {
298 init_registers_arm ();
299 return;
300 }
301
302 if (arm_hwcap & HWCAP_IWMMXT)
303 {
304 init_registers_arm_with_iwmmxt ();
305 return;
306 }
307
308 if (arm_hwcap & HWCAP_VFP)
309 {
310 int pid;
311 char *buf;
312
313 /* NEON implies either no VFP, or VFPv3-D32. We only support
314 it with VFP. */
315 if (arm_hwcap & HWCAP_NEON)
316 init_registers_arm_with_neon ();
317 else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
318 init_registers_arm_with_vfpv3 ();
319 else
320 init_registers_arm_with_vfpv2 ();
321
322 /* Now make sure that the kernel supports reading these
323 registers. Support was added in 2.6.30. */
324 pid = lwpid_of (get_thread_lwp (current_inferior));
325 errno = 0;
326 buf = malloc (32 * 8 + 4);
327 if (ptrace (PTRACE_GETVFPREGS, pid, 0, buf) < 0
328 && errno == EIO)
329 {
330 arm_hwcap = 0;
331 init_registers_arm ();
332 }
333 free (buf);
334
335 return;
336 }
337
338 /* The default configuration uses legacy FPA registers, probably
339 simulated. */
340 init_registers_arm ();
341}
342
fb1e4ffc
DJ
343struct regset_info target_regsets[] = {
344 { PTRACE_GETREGS, PTRACE_SETREGS, 18 * 4,
345 GENERAL_REGS,
346 arm_fill_gregset, arm_store_gregset },
fb1e4ffc
DJ
347 { PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 16 * 8 + 6 * 4,
348 EXTENDED_REGS,
349 arm_fill_wmmxregset, arm_store_wmmxregset },
58d6951d
DJ
350 { PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 32 * 8 + 4,
351 EXTENDED_REGS,
352 arm_fill_vfpregset, arm_store_vfpregset },
fb1e4ffc
DJ
353 { 0, 0, -1, -1, NULL, NULL }
354};
355
2ec06d2e 356struct linux_target_ops the_low_target = {
58d6951d 357 arm_arch_setup,
2ec06d2e
DJ
358 arm_num_regs,
359 arm_regmap,
360 arm_cannot_fetch_register,
361 arm_cannot_store_register,
0d62e5e8
DJ
362 arm_get_pc,
363 arm_set_pc,
aeb75bf5
DJ
364
365 /* Define an ARM-mode breakpoint; we only set breakpoints in the C
366 library, which is most likely to be ARM. If the kernel supports
367 clone events, we will never insert a breakpoint, so even a Thumb
368 C library will work; so will mixing EABI/non-EABI gdbserver and
369 application. */
9d1fb177 370#ifndef __ARM_EABI__
f450004a 371 (const unsigned char *) &arm_breakpoint,
9d1fb177
DJ
372#else
373 (const unsigned char *) &arm_eabi_breakpoint,
374#endif
0d62e5e8 375 arm_breakpoint_len,
3b2fc2ea 376 arm_reinsert_addr,
0d62e5e8
DJ
377 0,
378 arm_breakpoint_at,
2ec06d2e 379};
This page took 0.532557 seconds and 4 git commands to generate.