daily update
[deliverable/binutils-gdb.git] / gdb / arm-linux-nat.c
CommitLineData
ed9a39eb 1/* GNU/Linux on ARM native support.
4c38e0a4
JB
2 Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009,
3 2010 Free Software Foundation, Inc.
ed9a39eb
JM
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
ed9a39eb
JM
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/>. */
ed9a39eb
JM
19
20#include "defs.h"
21#include "inferior.h"
22#include "gdbcore.h"
23#include "gdb_string.h"
4e052eda 24#include "regcache.h"
10d6c8cd
DJ
25#include "target.h"
26#include "linux-nat.h"
05a4558a 27#include "target-descriptions.h"
3b273a55 28#include "auxv.h"
ed9a39eb 29
aeb98c60 30#include "arm-tdep.h"
cb587d83 31#include "arm-linux-tdep.h"
aeb98c60 32
3b273a55 33#include <elf/common.h>
ed9a39eb
JM
34#include <sys/user.h>
35#include <sys/ptrace.h>
36#include <sys/utsname.h>
41c49b06 37#include <sys/procfs.h>
ed9a39eb 38
c60c0f5f
MS
39/* Prototypes for supply_gregset etc. */
40#include "gregset.h"
41
9308fc88
DJ
42/* Defines ps_err_e, struct ps_prochandle. */
43#include "gdb_proc_service.h"
44
81adfced 45#include "features/arm-with-iwmmxt.c"
3b273a55
RE
46#include "features/arm-with-vfpv2.c"
47#include "features/arm-with-vfpv3.c"
48#include "features/arm-with-neon.c"
81adfced 49
9308fc88
DJ
50#ifndef PTRACE_GET_THREAD_AREA
51#define PTRACE_GET_THREAD_AREA 22
52#endif
53
05a4558a
DJ
54#ifndef PTRACE_GETWMMXREGS
55#define PTRACE_GETWMMXREGS 18
56#define PTRACE_SETWMMXREGS 19
57#endif
58
3b273a55
RE
59#ifndef PTRACE_GETVFPREGS
60#define PTRACE_GETVFPREGS 27
61#define PTRACE_SETVFPREGS 28
62#endif
63
64/* These are in <asm/elf.h> in current kernels. */
65#define HWCAP_VFP 64
66#define HWCAP_IWMMXT 512
67#define HWCAP_NEON 4096
68#define HWCAP_VFPv3 8192
69#define HWCAP_VFPv3D16 16384
70
05a4558a
DJ
71/* A flag for whether the WMMX registers are available. */
72static int arm_linux_has_wmmx_registers;
73
3b273a55
RE
74/* The number of 64-bit VFP registers we have (expect this to be 0,
75 16, or 32). */
76static int arm_linux_vfp_register_count;
77
ed9a39eb
JM
78extern int arm_apcs_32;
79
ed9a39eb 80/* The following variables are used to determine the version of the
fdf39c9a 81 underlying GNU/Linux operating system. Examples:
ed9a39eb 82
fdf39c9a 83 GNU/Linux 2.0.35 GNU/Linux 2.2.12
ed9a39eb
JM
84 os_version = 0x00020023 os_version = 0x0002020c
85 os_major = 2 os_major = 2
86 os_minor = 0 os_minor = 2
87 os_release = 35 os_release = 12
88
89 Note: os_version = (os_major << 16) | (os_minor << 8) | os_release
90
91 These are initialized using get_linux_version() from
92 _initialize_arm_linux_nat(). */
93
94static unsigned int os_version, os_major, os_minor, os_release;
95
fdf39c9a 96/* On GNU/Linux, threads are implemented as pseudo-processes, in which
41c49b06 97 case we may be tracing more than one process at a time. In that
39f77062 98 case, inferior_ptid will contain the main process ID and the
fdf39c9a
RE
99 individual thread (process) ID. get_thread_id () is used to get
100 the thread id if it's available, and the process id otherwise. */
41c49b06
SB
101
102int
39f77062 103get_thread_id (ptid_t ptid)
41c49b06 104{
39f77062
KB
105 int tid = TIDGET (ptid);
106 if (0 == tid)
107 tid = PIDGET (ptid);
41c49b06
SB
108 return tid;
109}
3b273a55 110
05a4558a 111#define GET_THREAD_ID(PTID) get_thread_id (PTID)
41c49b06 112
41c49b06 113/* Get the value of a particular register from the floating point
c6b92abd 114 state of the process and store it into regcache. */
41c49b06
SB
115
116static void
56be3814 117fetch_fpregister (struct regcache *regcache, int regno)
41c49b06
SB
118{
119 int ret, tid;
cb587d83 120 gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
41c49b06
SB
121
122 /* Get the thread id for the ptrace call. */
39f77062 123 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
124
125 /* Read the floating point state. */
cb587d83 126 ret = ptrace (PT_GETFPREGS, tid, 0, fp);
41c49b06
SB
127 if (ret < 0)
128 {
edefbb7c 129 warning (_("Unable to fetch floating point register."));
41c49b06
SB
130 return;
131 }
132
133 /* Fetch fpsr. */
34e8f22d 134 if (ARM_FPS_REGNUM == regno)
56be3814 135 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
cb587d83 136 fp + NWFPE_FPSR_OFFSET);
41c49b06
SB
137
138 /* Fetch the floating point register. */
34e8f22d 139 if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
56be3814 140 supply_nwfpe_register (regcache, regno, fp);
41c49b06
SB
141}
142
143/* Get the whole floating point state of the process and store it
c6b92abd 144 into regcache. */
ed9a39eb
JM
145
146static void
56be3814 147fetch_fpregs (struct regcache *regcache)
ed9a39eb 148{
41c49b06 149 int ret, regno, tid;
cb587d83 150 gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
ed9a39eb 151
41c49b06 152 /* Get the thread id for the ptrace call. */
39f77062 153 tid = GET_THREAD_ID (inferior_ptid);
41c49b06 154
ed9a39eb 155 /* Read the floating point state. */
cb587d83 156 ret = ptrace (PT_GETFPREGS, tid, 0, fp);
ed9a39eb
JM
157 if (ret < 0)
158 {
edefbb7c 159 warning (_("Unable to fetch the floating point registers."));
ed9a39eb
JM
160 return;
161 }
162
163 /* Fetch fpsr. */
56be3814 164 regcache_raw_supply (regcache, ARM_FPS_REGNUM,
cb587d83 165 fp + NWFPE_FPSR_OFFSET);
ed9a39eb
JM
166
167 /* Fetch the floating point registers. */
34e8f22d 168 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
56be3814 169 supply_nwfpe_register (regcache, regno, fp);
ed9a39eb
JM
170}
171
41c49b06 172/* Save a particular register into the floating point state of the
c6b92abd 173 process using the contents from regcache. */
41c49b06
SB
174
175static void
56be3814 176store_fpregister (const struct regcache *regcache, int regno)
41c49b06
SB
177{
178 int ret, tid;
cb587d83 179 gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
41c49b06
SB
180
181 /* Get the thread id for the ptrace call. */
39f77062 182 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
183
184 /* Read the floating point state. */
cb587d83 185 ret = ptrace (PT_GETFPREGS, tid, 0, fp);
41c49b06
SB
186 if (ret < 0)
187 {
edefbb7c 188 warning (_("Unable to fetch the floating point registers."));
41c49b06
SB
189 return;
190 }
191
192 /* Store fpsr. */
56be3814
UW
193 if (ARM_FPS_REGNUM == regno && regcache_valid_p (regcache, ARM_FPS_REGNUM))
194 regcache_raw_collect (regcache, ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
41c49b06
SB
195
196 /* Store the floating point register. */
34e8f22d 197 if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
56be3814 198 collect_nwfpe_register (regcache, regno, fp);
41c49b06 199
cb587d83 200 ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
41c49b06
SB
201 if (ret < 0)
202 {
edefbb7c 203 warning (_("Unable to store floating point register."));
41c49b06
SB
204 return;
205 }
206}
207
ed9a39eb 208/* Save the whole floating point state of the process using
c6b92abd 209 the contents from regcache. */
ed9a39eb
JM
210
211static void
56be3814 212store_fpregs (const struct regcache *regcache)
ed9a39eb 213{
41c49b06 214 int ret, regno, tid;
cb587d83 215 gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
ed9a39eb 216
41c49b06 217 /* Get the thread id for the ptrace call. */
39f77062 218 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
219
220 /* Read the floating point state. */
cb587d83 221 ret = ptrace (PT_GETFPREGS, tid, 0, fp);
41c49b06
SB
222 if (ret < 0)
223 {
edefbb7c 224 warning (_("Unable to fetch the floating point registers."));
41c49b06
SB
225 return;
226 }
227
ed9a39eb 228 /* Store fpsr. */
56be3814
UW
229 if (regcache_valid_p (regcache, ARM_FPS_REGNUM))
230 regcache_raw_collect (regcache, ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
ed9a39eb
JM
231
232 /* Store the floating point registers. */
34e8f22d 233 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
56be3814
UW
234 if (regcache_valid_p (regcache, regno))
235 collect_nwfpe_register (regcache, regno, fp);
ed9a39eb 236
cb587d83 237 ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
ed9a39eb
JM
238 if (ret < 0)
239 {
edefbb7c 240 warning (_("Unable to store floating point registers."));
ed9a39eb
JM
241 return;
242 }
243}
244
41c49b06 245/* Fetch a general register of the process and store into
c6b92abd 246 regcache. */
41c49b06
SB
247
248static void
56be3814 249fetch_register (struct regcache *regcache, int regno)
41c49b06
SB
250{
251 int ret, tid;
c2152441 252 elf_gregset_t regs;
41c49b06
SB
253
254 /* Get the thread id for the ptrace call. */
39f77062 255 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
256
257 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
258 if (ret < 0)
259 {
edefbb7c 260 warning (_("Unable to fetch general register."));
41c49b06
SB
261 return;
262 }
263
34e8f22d 264 if (regno >= ARM_A1_REGNUM && regno < ARM_PC_REGNUM)
56be3814 265 regcache_raw_supply (regcache, regno, (char *) &regs[regno]);
41c49b06 266
34e8f22d 267 if (ARM_PS_REGNUM == regno)
41c49b06
SB
268 {
269 if (arm_apcs_32)
56be3814 270 regcache_raw_supply (regcache, ARM_PS_REGNUM,
17c12639 271 (char *) &regs[ARM_CPSR_GREGNUM]);
41c49b06 272 else
56be3814 273 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 274 (char *) &regs[ARM_PC_REGNUM]);
41c49b06
SB
275 }
276
34e8f22d 277 if (ARM_PC_REGNUM == regno)
41c49b06 278 {
bf6ae464 279 regs[ARM_PC_REGNUM] = gdbarch_addr_bits_remove
08790784
UW
280 (get_regcache_arch (regcache),
281 regs[ARM_PC_REGNUM]);
56be3814 282 regcache_raw_supply (regcache, ARM_PC_REGNUM,
23a6d369 283 (char *) &regs[ARM_PC_REGNUM]);
41c49b06
SB
284 }
285}
286
ed9a39eb 287/* Fetch all general registers of the process and store into
c6b92abd 288 regcache. */
ed9a39eb
JM
289
290static void
56be3814 291fetch_regs (struct regcache *regcache)
ed9a39eb 292{
41c49b06 293 int ret, regno, tid;
c2152441 294 elf_gregset_t regs;
ed9a39eb 295
41c49b06 296 /* Get the thread id for the ptrace call. */
39f77062 297 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
298
299 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
ed9a39eb
JM
300 if (ret < 0)
301 {
edefbb7c 302 warning (_("Unable to fetch general registers."));
ed9a39eb
JM
303 return;
304 }
305
34e8f22d 306 for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
56be3814 307 regcache_raw_supply (regcache, regno, (char *) &regs[regno]);
ed9a39eb
JM
308
309 if (arm_apcs_32)
56be3814 310 regcache_raw_supply (regcache, ARM_PS_REGNUM,
17c12639 311 (char *) &regs[ARM_CPSR_GREGNUM]);
ed9a39eb 312 else
56be3814 313 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 314 (char *) &regs[ARM_PC_REGNUM]);
ed9a39eb 315
bf6ae464 316 regs[ARM_PC_REGNUM] = gdbarch_addr_bits_remove
08790784 317 (get_regcache_arch (regcache), regs[ARM_PC_REGNUM]);
56be3814 318 regcache_raw_supply (regcache, ARM_PC_REGNUM,
23a6d369 319 (char *) &regs[ARM_PC_REGNUM]);
ed9a39eb
JM
320}
321
322/* Store all general registers of the process from the values in
c6b92abd 323 regcache. */
ed9a39eb 324
41c49b06 325static void
56be3814 326store_register (const struct regcache *regcache, int regno)
41c49b06
SB
327{
328 int ret, tid;
c2152441 329 elf_gregset_t regs;
41c49b06 330
56be3814 331 if (!regcache_valid_p (regcache, regno))
41c49b06
SB
332 return;
333
334 /* Get the thread id for the ptrace call. */
39f77062 335 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
336
337 /* Get the general registers from the process. */
338 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
339 if (ret < 0)
340 {
edefbb7c 341 warning (_("Unable to fetch general registers."));
41c49b06
SB
342 return;
343 }
344
34e8f22d 345 if (regno >= ARM_A1_REGNUM && regno <= ARM_PC_REGNUM)
56be3814 346 regcache_raw_collect (regcache, regno, (char *) &regs[regno]);
adb8a87c 347 else if (arm_apcs_32 && regno == ARM_PS_REGNUM)
56be3814 348 regcache_raw_collect (regcache, regno,
17c12639 349 (char *) &regs[ARM_CPSR_GREGNUM]);
adb8a87c 350 else if (!arm_apcs_32 && regno == ARM_PS_REGNUM)
56be3814 351 regcache_raw_collect (regcache, ARM_PC_REGNUM,
adb8a87c 352 (char *) &regs[ARM_PC_REGNUM]);
41c49b06
SB
353
354 ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
355 if (ret < 0)
356 {
edefbb7c 357 warning (_("Unable to store general register."));
41c49b06
SB
358 return;
359 }
360}
361
ed9a39eb 362static void
56be3814 363store_regs (const struct regcache *regcache)
ed9a39eb 364{
41c49b06 365 int ret, regno, tid;
c2152441 366 elf_gregset_t regs;
ed9a39eb 367
41c49b06 368 /* Get the thread id for the ptrace call. */
39f77062 369 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
370
371 /* Fetch the general registers. */
372 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
ed9a39eb
JM
373 if (ret < 0)
374 {
edefbb7c 375 warning (_("Unable to fetch general registers."));
ed9a39eb
JM
376 return;
377 }
378
34e8f22d 379 for (regno = ARM_A1_REGNUM; regno <= ARM_PC_REGNUM; regno++)
ed9a39eb 380 {
56be3814
UW
381 if (regcache_valid_p (regcache, regno))
382 regcache_raw_collect (regcache, regno, (char *) &regs[regno]);
ed9a39eb
JM
383 }
384
56be3814
UW
385 if (arm_apcs_32 && regcache_valid_p (regcache, ARM_PS_REGNUM))
386 regcache_raw_collect (regcache, ARM_PS_REGNUM,
17c12639 387 (char *) &regs[ARM_CPSR_GREGNUM]);
adb8a87c 388
41c49b06 389 ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
ed9a39eb
JM
390
391 if (ret < 0)
392 {
edefbb7c 393 warning (_("Unable to store general registers."));
ed9a39eb
JM
394 return;
395 }
396}
397
05a4558a
DJ
398/* Fetch all WMMX registers of the process and store into
399 regcache. */
400
401#define IWMMXT_REGS_SIZE (16 * 8 + 6 * 4)
402
403static void
56be3814 404fetch_wmmx_regs (struct regcache *regcache)
05a4558a
DJ
405{
406 char regbuf[IWMMXT_REGS_SIZE];
407 int ret, regno, tid;
408
409 /* Get the thread id for the ptrace call. */
410 tid = GET_THREAD_ID (inferior_ptid);
411
412 ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf);
413 if (ret < 0)
414 {
415 warning (_("Unable to fetch WMMX registers."));
416 return;
417 }
418
419 for (regno = 0; regno < 16; regno++)
56be3814 420 regcache_raw_supply (regcache, regno + ARM_WR0_REGNUM,
05a4558a
DJ
421 &regbuf[regno * 8]);
422
423 for (regno = 0; regno < 2; regno++)
56be3814 424 regcache_raw_supply (regcache, regno + ARM_WCSSF_REGNUM,
05a4558a
DJ
425 &regbuf[16 * 8 + regno * 4]);
426
427 for (regno = 0; regno < 4; regno++)
56be3814 428 regcache_raw_supply (regcache, regno + ARM_WCGR0_REGNUM,
05a4558a
DJ
429 &regbuf[16 * 8 + 2 * 4 + regno * 4]);
430}
431
432static void
56be3814 433store_wmmx_regs (const struct regcache *regcache)
05a4558a
DJ
434{
435 char regbuf[IWMMXT_REGS_SIZE];
436 int ret, regno, tid;
437
438 /* Get the thread id for the ptrace call. */
439 tid = GET_THREAD_ID (inferior_ptid);
440
441 ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf);
442 if (ret < 0)
443 {
444 warning (_("Unable to fetch WMMX registers."));
445 return;
446 }
447
448 for (regno = 0; regno < 16; regno++)
56be3814
UW
449 if (regcache_valid_p (regcache, regno + ARM_WR0_REGNUM))
450 regcache_raw_collect (regcache, regno + ARM_WR0_REGNUM,
05a4558a
DJ
451 &regbuf[regno * 8]);
452
453 for (regno = 0; regno < 2; regno++)
56be3814
UW
454 if (regcache_valid_p (regcache, regno + ARM_WCSSF_REGNUM))
455 regcache_raw_collect (regcache, regno + ARM_WCSSF_REGNUM,
05a4558a
DJ
456 &regbuf[16 * 8 + regno * 4]);
457
458 for (regno = 0; regno < 4; regno++)
56be3814
UW
459 if (regcache_valid_p (regcache, regno + ARM_WCGR0_REGNUM))
460 regcache_raw_collect (regcache, regno + ARM_WCGR0_REGNUM,
05a4558a
DJ
461 &regbuf[16 * 8 + 2 * 4 + regno * 4]);
462
463 ret = ptrace (PTRACE_SETWMMXREGS, tid, 0, regbuf);
464
465 if (ret < 0)
466 {
467 warning (_("Unable to store WMMX registers."));
468 return;
469 }
470}
471
3b273a55
RE
472/* Fetch and store VFP Registers. The kernel object has space for 32
473 64-bit registers, and the FPSCR. This is even when on a VFPv2 or
474 VFPv3D16 target. */
475#define VFP_REGS_SIZE (32 * 8 + 4)
476
477static void
478fetch_vfp_regs (struct regcache *regcache)
479{
480 char regbuf[VFP_REGS_SIZE];
481 int ret, regno, tid;
482
483 /* Get the thread id for the ptrace call. */
484 tid = GET_THREAD_ID (inferior_ptid);
485
486 ret = ptrace (PTRACE_GETVFPREGS, tid, 0, regbuf);
487 if (ret < 0)
488 {
489 warning (_("Unable to fetch VFP registers."));
490 return;
491 }
492
493 for (regno = 0; regno < arm_linux_vfp_register_count; regno++)
494 regcache_raw_supply (regcache, regno + ARM_D0_REGNUM,
495 (char *) regbuf + regno * 8);
496
497 regcache_raw_supply (regcache, ARM_FPSCR_REGNUM,
498 (char *) regbuf + 32 * 8);
499}
500
501static void
502store_vfp_regs (const struct regcache *regcache)
503{
504 char regbuf[VFP_REGS_SIZE];
505 int ret, regno, tid;
506
507 /* Get the thread id for the ptrace call. */
508 tid = GET_THREAD_ID (inferior_ptid);
509
510 ret = ptrace (PTRACE_GETVFPREGS, tid, 0, regbuf);
511 if (ret < 0)
512 {
513 warning (_("Unable to fetch VFP registers (for update)."));
514 return;
515 }
516
517 for (regno = 0; regno < arm_linux_vfp_register_count; regno++)
518 regcache_raw_collect (regcache, regno + ARM_D0_REGNUM,
519 (char *) regbuf + regno * 8);
520
521 regcache_raw_collect (regcache, ARM_FPSCR_REGNUM,
522 (char *) regbuf + 32 * 8);
523
524 ret = ptrace (PTRACE_SETVFPREGS, tid, 0, regbuf);
525
526 if (ret < 0)
527 {
528 warning (_("Unable to store VFP registers."));
529 return;
530 }
531}
532
ed9a39eb
JM
533/* Fetch registers from the child process. Fetch all registers if
534 regno == -1, otherwise fetch all general registers or all floating
535 point registers depending upon the value of regno. */
536
10d6c8cd 537static void
28439f5e
PA
538arm_linux_fetch_inferior_registers (struct target_ops *ops,
539 struct regcache *regcache, int regno)
ed9a39eb 540{
41c49b06
SB
541 if (-1 == regno)
542 {
56be3814
UW
543 fetch_regs (regcache);
544 fetch_fpregs (regcache);
05a4558a 545 if (arm_linux_has_wmmx_registers)
56be3814 546 fetch_wmmx_regs (regcache);
3b273a55
RE
547 if (arm_linux_vfp_register_count > 0)
548 fetch_vfp_regs (regcache);
41c49b06
SB
549 }
550 else
551 {
05a4558a 552 if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
56be3814 553 fetch_register (regcache, regno);
05a4558a 554 else if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
56be3814 555 fetch_fpregister (regcache, regno);
05a4558a
DJ
556 else if (arm_linux_has_wmmx_registers
557 && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
56be3814 558 fetch_wmmx_regs (regcache);
3b273a55
RE
559 else if (arm_linux_vfp_register_count > 0
560 && regno >= ARM_D0_REGNUM
561 && regno <= ARM_D0_REGNUM + arm_linux_vfp_register_count)
562 fetch_vfp_regs (regcache);
41c49b06 563 }
ed9a39eb
JM
564}
565
566/* Store registers back into the inferior. Store all registers if
567 regno == -1, otherwise store all general registers or all floating
568 point registers depending upon the value of regno. */
569
10d6c8cd 570static void
28439f5e
PA
571arm_linux_store_inferior_registers (struct target_ops *ops,
572 struct regcache *regcache, int regno)
ed9a39eb 573{
41c49b06
SB
574 if (-1 == regno)
575 {
56be3814
UW
576 store_regs (regcache);
577 store_fpregs (regcache);
05a4558a 578 if (arm_linux_has_wmmx_registers)
56be3814 579 store_wmmx_regs (regcache);
3b273a55
RE
580 if (arm_linux_vfp_register_count > 0)
581 store_vfp_regs (regcache);
41c49b06
SB
582 }
583 else
584 {
05a4558a 585 if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
56be3814 586 store_register (regcache, regno);
05a4558a 587 else if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM))
56be3814 588 store_fpregister (regcache, regno);
05a4558a
DJ
589 else if (arm_linux_has_wmmx_registers
590 && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
56be3814 591 store_wmmx_regs (regcache);
3b273a55
RE
592 else if (arm_linux_vfp_register_count > 0
593 && regno >= ARM_D0_REGNUM
594 && regno <= ARM_D0_REGNUM + arm_linux_vfp_register_count)
595 store_vfp_regs (regcache);
41c49b06 596 }
ed9a39eb
JM
597}
598
cb587d83
DJ
599/* Wrapper functions for the standard regset handling, used by
600 thread debugging. */
41c49b06
SB
601
602void
7f7fe91e
UW
603fill_gregset (const struct regcache *regcache,
604 gdb_gregset_t *gregsetp, int regno)
41c49b06 605{
7f7fe91e 606 arm_linux_collect_gregset (NULL, regcache, regno, gregsetp, 0);
41c49b06
SB
607}
608
41c49b06 609void
7f7fe91e 610supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
41c49b06 611{
7f7fe91e 612 arm_linux_supply_gregset (NULL, regcache, -1, gregsetp, 0);
41c49b06
SB
613}
614
41c49b06 615void
7f7fe91e
UW
616fill_fpregset (const struct regcache *regcache,
617 gdb_fpregset_t *fpregsetp, int regno)
41c49b06 618{
7f7fe91e 619 arm_linux_collect_nwfpe (NULL, regcache, regno, fpregsetp, 0);
41c49b06
SB
620}
621
622/* Fill GDB's register array with the floating-point register values
623 in *fpregsetp. */
624
625void
7f7fe91e 626supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
ed9a39eb 627{
7f7fe91e 628 arm_linux_supply_nwfpe (NULL, regcache, -1, fpregsetp, 0);
ed9a39eb
JM
629}
630
9308fc88
DJ
631/* Fetch the thread-local storage pointer for libthread_db. */
632
633ps_err_e
634ps_get_thread_area (const struct ps_prochandle *ph,
635 lwpid_t lwpid, int idx, void **base)
636{
637 if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
638 return PS_ERR;
639
640 /* IDX is the bias from the thread pointer to the beginning of the
641 thread descriptor. It has to be subtracted due to implementation
642 quirks in libthread_db. */
643 *base = (void *) ((char *)*base - idx);
644
645 return PS_OK;
646}
647
ed9a39eb
JM
648static unsigned int
649get_linux_version (unsigned int *vmajor,
650 unsigned int *vminor,
651 unsigned int *vrelease)
652{
653 struct utsname info;
654 char *pmajor, *pminor, *prelease, *tail;
655
656 if (-1 == uname (&info))
657 {
edefbb7c 658 warning (_("Unable to determine GNU/Linux version."));
ed9a39eb
JM
659 return -1;
660 }
661
662 pmajor = strtok (info.release, ".");
663 pminor = strtok (NULL, ".");
664 prelease = strtok (NULL, ".");
665
666 *vmajor = (unsigned int) strtoul (pmajor, &tail, 0);
667 *vminor = (unsigned int) strtoul (pminor, &tail, 0);
668 *vrelease = (unsigned int) strtoul (prelease, &tail, 0);
669
670 return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
671}
672
81adfced
DJ
673static const struct target_desc *
674arm_linux_read_description (struct target_ops *ops)
05a4558a 675{
3b273a55
RE
676 CORE_ADDR arm_hwcap = 0;
677 arm_linux_has_wmmx_registers = 0;
678 arm_linux_vfp_register_count = 0;
05a4558a 679
3b273a55
RE
680 if (target_auxv_search (ops, AT_HWCAP, &arm_hwcap) != 1)
681 {
682 return NULL;
683 }
81adfced 684
3b273a55
RE
685 if (arm_hwcap & HWCAP_IWMMXT)
686 {
687 arm_linux_has_wmmx_registers = 1;
688 if (tdesc_arm_with_iwmmxt == NULL)
689 initialize_tdesc_arm_with_iwmmxt ();
690 return tdesc_arm_with_iwmmxt;
691 }
692
693 if (arm_hwcap & HWCAP_VFP)
694 {
695 int pid;
696 char *buf;
697 const struct target_desc * result = NULL;
698
699 /* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support
700 Neon with VFPv3-D32. */
701 if (arm_hwcap & HWCAP_NEON)
702 {
703 arm_linux_vfp_register_count = 32;
704 if (tdesc_arm_with_neon == NULL)
705 initialize_tdesc_arm_with_neon ();
706 result = tdesc_arm_with_neon;
707 }
708 else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
709 {
710 arm_linux_vfp_register_count = 32;
711 if (tdesc_arm_with_vfpv3 == NULL)
712 initialize_tdesc_arm_with_vfpv3 ();
713 result = tdesc_arm_with_vfpv3;
714 }
715 else
716 {
717 arm_linux_vfp_register_count = 16;
718 if (tdesc_arm_with_vfpv2 == NULL)
719 initialize_tdesc_arm_with_vfpv2 ();
720 result = tdesc_arm_with_vfpv2;
721 }
722
723 /* Now make sure that the kernel supports reading these
724 registers. Support was added in 2.6.30. */
725 pid = GET_LWP (inferior_ptid);
726 errno = 0;
727 buf = alloca (VFP_REGS_SIZE);
728 if (ptrace (PTRACE_GETVFPREGS, pid, 0, buf) < 0
729 && errno == EIO)
730 result = NULL;
731
732 return result;
733 }
734
735 return NULL;
05a4558a
DJ
736}
737
10d6c8cd
DJ
738void _initialize_arm_linux_nat (void);
739
ed9a39eb
JM
740void
741_initialize_arm_linux_nat (void)
742{
10d6c8cd
DJ
743 struct target_ops *t;
744
ed9a39eb 745 os_version = get_linux_version (&os_major, &os_minor, &os_release);
10d6c8cd
DJ
746
747 /* Fill in the generic GNU/Linux methods. */
748 t = linux_target ();
749
750 /* Add our register access methods. */
751 t->to_fetch_registers = arm_linux_fetch_inferior_registers;
752 t->to_store_registers = arm_linux_store_inferior_registers;
753
81adfced 754 t->to_read_description = arm_linux_read_description;
05a4558a 755
10d6c8cd 756 /* Register the target. */
f973ed9c 757 linux_nat_add_target (t);
ed9a39eb 758}
This page took 0.662495 seconds and 4 git commands to generate.