*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / arm-linux-nat.c
CommitLineData
ed9a39eb 1/* GNU/Linux on ARM native support.
4c38e0a4 2 Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009,
7b6bb8da 3 2010, 2011 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
0963b4bd 39/* Prototypes for supply_gregset etc. */
c60c0f5f
MS
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 74/* The number of 64-bit VFP registers we have (expect this to be 0,
0963b4bd 75 16, or 32). */
3b273a55
RE
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. */
672c9795
YQ
193 if (ARM_FPS_REGNUM == regno
194 && REG_VALID == regcache_register_status (regcache, ARM_FPS_REGNUM))
56be3814 195 regcache_raw_collect (regcache, ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
41c49b06
SB
196
197 /* Store the floating point register. */
34e8f22d 198 if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
56be3814 199 collect_nwfpe_register (regcache, regno, fp);
41c49b06 200
cb587d83 201 ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
41c49b06
SB
202 if (ret < 0)
203 {
edefbb7c 204 warning (_("Unable to store floating point register."));
41c49b06
SB
205 return;
206 }
207}
208
ed9a39eb 209/* Save the whole floating point state of the process using
c6b92abd 210 the contents from regcache. */
ed9a39eb
JM
211
212static void
56be3814 213store_fpregs (const struct regcache *regcache)
ed9a39eb 214{
41c49b06 215 int ret, regno, tid;
cb587d83 216 gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
ed9a39eb 217
41c49b06 218 /* Get the thread id for the ptrace call. */
39f77062 219 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
220
221 /* Read the floating point state. */
cb587d83 222 ret = ptrace (PT_GETFPREGS, tid, 0, fp);
41c49b06
SB
223 if (ret < 0)
224 {
edefbb7c 225 warning (_("Unable to fetch the floating point registers."));
41c49b06
SB
226 return;
227 }
228
ed9a39eb 229 /* Store fpsr. */
672c9795 230 if (REG_VALID == regcache_register_status (regcache, ARM_FPS_REGNUM))
56be3814 231 regcache_raw_collect (regcache, ARM_FPS_REGNUM, fp + NWFPE_FPSR_OFFSET);
ed9a39eb
JM
232
233 /* Store the floating point registers. */
34e8f22d 234 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
672c9795 235 if (REG_VALID == regcache_register_status (regcache, regno))
56be3814 236 collect_nwfpe_register (regcache, regno, fp);
ed9a39eb 237
cb587d83 238 ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
ed9a39eb
JM
239 if (ret < 0)
240 {
edefbb7c 241 warning (_("Unable to store floating point registers."));
ed9a39eb
JM
242 return;
243 }
244}
245
41c49b06 246/* Fetch a general register of the process and store into
c6b92abd 247 regcache. */
41c49b06
SB
248
249static void
56be3814 250fetch_register (struct regcache *regcache, int regno)
41c49b06
SB
251{
252 int ret, tid;
c2152441 253 elf_gregset_t regs;
41c49b06
SB
254
255 /* Get the thread id for the ptrace call. */
39f77062 256 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
257
258 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
259 if (ret < 0)
260 {
edefbb7c 261 warning (_("Unable to fetch general register."));
41c49b06
SB
262 return;
263 }
264
34e8f22d 265 if (regno >= ARM_A1_REGNUM && regno < ARM_PC_REGNUM)
56be3814 266 regcache_raw_supply (regcache, regno, (char *) &regs[regno]);
41c49b06 267
34e8f22d 268 if (ARM_PS_REGNUM == regno)
41c49b06
SB
269 {
270 if (arm_apcs_32)
56be3814 271 regcache_raw_supply (regcache, ARM_PS_REGNUM,
17c12639 272 (char *) &regs[ARM_CPSR_GREGNUM]);
41c49b06 273 else
56be3814 274 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 275 (char *) &regs[ARM_PC_REGNUM]);
41c49b06
SB
276 }
277
34e8f22d 278 if (ARM_PC_REGNUM == regno)
41c49b06 279 {
bf6ae464 280 regs[ARM_PC_REGNUM] = gdbarch_addr_bits_remove
08790784
UW
281 (get_regcache_arch (regcache),
282 regs[ARM_PC_REGNUM]);
56be3814 283 regcache_raw_supply (regcache, ARM_PC_REGNUM,
23a6d369 284 (char *) &regs[ARM_PC_REGNUM]);
41c49b06
SB
285 }
286}
287
ed9a39eb 288/* Fetch all general registers of the process and store into
c6b92abd 289 regcache. */
ed9a39eb
JM
290
291static void
56be3814 292fetch_regs (struct regcache *regcache)
ed9a39eb 293{
41c49b06 294 int ret, regno, tid;
c2152441 295 elf_gregset_t regs;
ed9a39eb 296
41c49b06 297 /* Get the thread id for the ptrace call. */
39f77062 298 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
299
300 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
ed9a39eb
JM
301 if (ret < 0)
302 {
edefbb7c 303 warning (_("Unable to fetch general registers."));
ed9a39eb
JM
304 return;
305 }
306
34e8f22d 307 for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
56be3814 308 regcache_raw_supply (regcache, regno, (char *) &regs[regno]);
ed9a39eb
JM
309
310 if (arm_apcs_32)
56be3814 311 regcache_raw_supply (regcache, ARM_PS_REGNUM,
17c12639 312 (char *) &regs[ARM_CPSR_GREGNUM]);
ed9a39eb 313 else
56be3814 314 regcache_raw_supply (regcache, ARM_PS_REGNUM,
23a6d369 315 (char *) &regs[ARM_PC_REGNUM]);
ed9a39eb 316
bf6ae464 317 regs[ARM_PC_REGNUM] = gdbarch_addr_bits_remove
08790784 318 (get_regcache_arch (regcache), regs[ARM_PC_REGNUM]);
56be3814 319 regcache_raw_supply (regcache, ARM_PC_REGNUM,
23a6d369 320 (char *) &regs[ARM_PC_REGNUM]);
ed9a39eb
JM
321}
322
323/* Store all general registers of the process from the values in
c6b92abd 324 regcache. */
ed9a39eb 325
41c49b06 326static void
56be3814 327store_register (const struct regcache *regcache, int regno)
41c49b06
SB
328{
329 int ret, tid;
c2152441 330 elf_gregset_t regs;
41c49b06 331
672c9795 332 if (REG_VALID != regcache_register_status (regcache, regno))
41c49b06
SB
333 return;
334
335 /* Get the thread id for the ptrace call. */
39f77062 336 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
337
338 /* Get the general registers from the process. */
339 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
340 if (ret < 0)
341 {
edefbb7c 342 warning (_("Unable to fetch general registers."));
41c49b06
SB
343 return;
344 }
345
34e8f22d 346 if (regno >= ARM_A1_REGNUM && regno <= ARM_PC_REGNUM)
56be3814 347 regcache_raw_collect (regcache, regno, (char *) &regs[regno]);
adb8a87c 348 else if (arm_apcs_32 && regno == ARM_PS_REGNUM)
56be3814 349 regcache_raw_collect (regcache, regno,
17c12639 350 (char *) &regs[ARM_CPSR_GREGNUM]);
adb8a87c 351 else if (!arm_apcs_32 && regno == ARM_PS_REGNUM)
56be3814 352 regcache_raw_collect (regcache, ARM_PC_REGNUM,
adb8a87c 353 (char *) &regs[ARM_PC_REGNUM]);
41c49b06
SB
354
355 ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
356 if (ret < 0)
357 {
edefbb7c 358 warning (_("Unable to store general register."));
41c49b06
SB
359 return;
360 }
361}
362
ed9a39eb 363static void
56be3814 364store_regs (const struct regcache *regcache)
ed9a39eb 365{
41c49b06 366 int ret, regno, tid;
c2152441 367 elf_gregset_t regs;
ed9a39eb 368
41c49b06 369 /* Get the thread id for the ptrace call. */
39f77062 370 tid = GET_THREAD_ID (inferior_ptid);
41c49b06
SB
371
372 /* Fetch the general registers. */
373 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
ed9a39eb
JM
374 if (ret < 0)
375 {
edefbb7c 376 warning (_("Unable to fetch general registers."));
ed9a39eb
JM
377 return;
378 }
379
34e8f22d 380 for (regno = ARM_A1_REGNUM; regno <= ARM_PC_REGNUM; regno++)
ed9a39eb 381 {
672c9795 382 if (REG_VALID == regcache_register_status (regcache, regno))
56be3814 383 regcache_raw_collect (regcache, regno, (char *) &regs[regno]);
ed9a39eb
JM
384 }
385
672c9795 386 if (arm_apcs_32 && REG_VALID == regcache_register_status (regcache, ARM_PS_REGNUM))
56be3814 387 regcache_raw_collect (regcache, ARM_PS_REGNUM,
17c12639 388 (char *) &regs[ARM_CPSR_GREGNUM]);
adb8a87c 389
41c49b06 390 ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
ed9a39eb
JM
391
392 if (ret < 0)
393 {
edefbb7c 394 warning (_("Unable to store general registers."));
ed9a39eb
JM
395 return;
396 }
397}
398
05a4558a
DJ
399/* Fetch all WMMX registers of the process and store into
400 regcache. */
401
402#define IWMMXT_REGS_SIZE (16 * 8 + 6 * 4)
403
404static void
56be3814 405fetch_wmmx_regs (struct regcache *regcache)
05a4558a
DJ
406{
407 char regbuf[IWMMXT_REGS_SIZE];
408 int ret, regno, tid;
409
410 /* Get the thread id for the ptrace call. */
411 tid = GET_THREAD_ID (inferior_ptid);
412
413 ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf);
414 if (ret < 0)
415 {
416 warning (_("Unable to fetch WMMX registers."));
417 return;
418 }
419
420 for (regno = 0; regno < 16; regno++)
56be3814 421 regcache_raw_supply (regcache, regno + ARM_WR0_REGNUM,
05a4558a
DJ
422 &regbuf[regno * 8]);
423
424 for (regno = 0; regno < 2; regno++)
56be3814 425 regcache_raw_supply (regcache, regno + ARM_WCSSF_REGNUM,
05a4558a
DJ
426 &regbuf[16 * 8 + regno * 4]);
427
428 for (regno = 0; regno < 4; regno++)
56be3814 429 regcache_raw_supply (regcache, regno + ARM_WCGR0_REGNUM,
05a4558a
DJ
430 &regbuf[16 * 8 + 2 * 4 + regno * 4]);
431}
432
433static void
56be3814 434store_wmmx_regs (const struct regcache *regcache)
05a4558a
DJ
435{
436 char regbuf[IWMMXT_REGS_SIZE];
437 int ret, regno, tid;
438
439 /* Get the thread id for the ptrace call. */
440 tid = GET_THREAD_ID (inferior_ptid);
441
442 ret = ptrace (PTRACE_GETWMMXREGS, tid, 0, regbuf);
443 if (ret < 0)
444 {
445 warning (_("Unable to fetch WMMX registers."));
446 return;
447 }
448
449 for (regno = 0; regno < 16; regno++)
672c9795
YQ
450 if (REG_VALID == regcache_register_status (regcache,
451 regno + ARM_WR0_REGNUM))
56be3814 452 regcache_raw_collect (regcache, regno + ARM_WR0_REGNUM,
05a4558a
DJ
453 &regbuf[regno * 8]);
454
455 for (regno = 0; regno < 2; regno++)
672c9795
YQ
456 if (REG_VALID == regcache_register_status (regcache,
457 regno + ARM_WCSSF_REGNUM))
56be3814 458 regcache_raw_collect (regcache, regno + ARM_WCSSF_REGNUM,
05a4558a
DJ
459 &regbuf[16 * 8 + regno * 4]);
460
461 for (regno = 0; regno < 4; regno++)
672c9795
YQ
462 if (REG_VALID == regcache_register_status (regcache,
463 regno + ARM_WCGR0_REGNUM))
56be3814 464 regcache_raw_collect (regcache, regno + ARM_WCGR0_REGNUM,
05a4558a
DJ
465 &regbuf[16 * 8 + 2 * 4 + regno * 4]);
466
467 ret = ptrace (PTRACE_SETWMMXREGS, tid, 0, regbuf);
468
469 if (ret < 0)
470 {
471 warning (_("Unable to store WMMX registers."));
472 return;
473 }
474}
475
3b273a55
RE
476/* Fetch and store VFP Registers. The kernel object has space for 32
477 64-bit registers, and the FPSCR. This is even when on a VFPv2 or
478 VFPv3D16 target. */
479#define VFP_REGS_SIZE (32 * 8 + 4)
480
481static void
482fetch_vfp_regs (struct regcache *regcache)
483{
484 char regbuf[VFP_REGS_SIZE];
485 int ret, regno, tid;
486
487 /* Get the thread id for the ptrace call. */
488 tid = GET_THREAD_ID (inferior_ptid);
489
490 ret = ptrace (PTRACE_GETVFPREGS, tid, 0, regbuf);
491 if (ret < 0)
492 {
493 warning (_("Unable to fetch VFP registers."));
494 return;
495 }
496
497 for (regno = 0; regno < arm_linux_vfp_register_count; regno++)
498 regcache_raw_supply (regcache, regno + ARM_D0_REGNUM,
499 (char *) regbuf + regno * 8);
500
501 regcache_raw_supply (regcache, ARM_FPSCR_REGNUM,
502 (char *) regbuf + 32 * 8);
503}
504
505static void
506store_vfp_regs (const struct regcache *regcache)
507{
508 char regbuf[VFP_REGS_SIZE];
509 int ret, regno, tid;
510
511 /* Get the thread id for the ptrace call. */
512 tid = GET_THREAD_ID (inferior_ptid);
513
514 ret = ptrace (PTRACE_GETVFPREGS, tid, 0, regbuf);
515 if (ret < 0)
516 {
517 warning (_("Unable to fetch VFP registers (for update)."));
518 return;
519 }
520
521 for (regno = 0; regno < arm_linux_vfp_register_count; regno++)
522 regcache_raw_collect (regcache, regno + ARM_D0_REGNUM,
523 (char *) regbuf + regno * 8);
524
525 regcache_raw_collect (regcache, ARM_FPSCR_REGNUM,
526 (char *) regbuf + 32 * 8);
527
528 ret = ptrace (PTRACE_SETVFPREGS, tid, 0, regbuf);
529
530 if (ret < 0)
531 {
532 warning (_("Unable to store VFP registers."));
533 return;
534 }
535}
536
ed9a39eb
JM
537/* Fetch registers from the child process. Fetch all registers if
538 regno == -1, otherwise fetch all general registers or all floating
539 point registers depending upon the value of regno. */
540
10d6c8cd 541static void
28439f5e
PA
542arm_linux_fetch_inferior_registers (struct target_ops *ops,
543 struct regcache *regcache, int regno)
ed9a39eb 544{
41c49b06
SB
545 if (-1 == regno)
546 {
56be3814
UW
547 fetch_regs (regcache);
548 fetch_fpregs (regcache);
05a4558a 549 if (arm_linux_has_wmmx_registers)
56be3814 550 fetch_wmmx_regs (regcache);
3b273a55
RE
551 if (arm_linux_vfp_register_count > 0)
552 fetch_vfp_regs (regcache);
41c49b06
SB
553 }
554 else
555 {
05a4558a 556 if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
56be3814 557 fetch_register (regcache, regno);
05a4558a 558 else if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
56be3814 559 fetch_fpregister (regcache, regno);
05a4558a
DJ
560 else if (arm_linux_has_wmmx_registers
561 && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
56be3814 562 fetch_wmmx_regs (regcache);
3b273a55
RE
563 else if (arm_linux_vfp_register_count > 0
564 && regno >= ARM_D0_REGNUM
565 && regno <= ARM_D0_REGNUM + arm_linux_vfp_register_count)
566 fetch_vfp_regs (regcache);
41c49b06 567 }
ed9a39eb
JM
568}
569
570/* Store registers back into the inferior. Store all registers if
571 regno == -1, otherwise store all general registers or all floating
572 point registers depending upon the value of regno. */
573
10d6c8cd 574static void
28439f5e
PA
575arm_linux_store_inferior_registers (struct target_ops *ops,
576 struct regcache *regcache, int regno)
ed9a39eb 577{
41c49b06
SB
578 if (-1 == regno)
579 {
56be3814
UW
580 store_regs (regcache);
581 store_fpregs (regcache);
05a4558a 582 if (arm_linux_has_wmmx_registers)
56be3814 583 store_wmmx_regs (regcache);
3b273a55
RE
584 if (arm_linux_vfp_register_count > 0)
585 store_vfp_regs (regcache);
41c49b06
SB
586 }
587 else
588 {
05a4558a 589 if (regno < ARM_F0_REGNUM || regno == ARM_PS_REGNUM)
56be3814 590 store_register (regcache, regno);
05a4558a 591 else if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM))
56be3814 592 store_fpregister (regcache, regno);
05a4558a
DJ
593 else if (arm_linux_has_wmmx_registers
594 && regno >= ARM_WR0_REGNUM && regno <= ARM_WCGR7_REGNUM)
56be3814 595 store_wmmx_regs (regcache);
3b273a55
RE
596 else if (arm_linux_vfp_register_count > 0
597 && regno >= ARM_D0_REGNUM
598 && regno <= ARM_D0_REGNUM + arm_linux_vfp_register_count)
599 store_vfp_regs (regcache);
41c49b06 600 }
ed9a39eb
JM
601}
602
cb587d83
DJ
603/* Wrapper functions for the standard regset handling, used by
604 thread debugging. */
41c49b06
SB
605
606void
7f7fe91e
UW
607fill_gregset (const struct regcache *regcache,
608 gdb_gregset_t *gregsetp, int regno)
41c49b06 609{
7f7fe91e 610 arm_linux_collect_gregset (NULL, regcache, regno, gregsetp, 0);
41c49b06
SB
611}
612
41c49b06 613void
7f7fe91e 614supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
41c49b06 615{
7f7fe91e 616 arm_linux_supply_gregset (NULL, regcache, -1, gregsetp, 0);
41c49b06
SB
617}
618
41c49b06 619void
7f7fe91e
UW
620fill_fpregset (const struct regcache *regcache,
621 gdb_fpregset_t *fpregsetp, int regno)
41c49b06 622{
7f7fe91e 623 arm_linux_collect_nwfpe (NULL, regcache, regno, fpregsetp, 0);
41c49b06
SB
624}
625
626/* Fill GDB's register array with the floating-point register values
627 in *fpregsetp. */
628
629void
7f7fe91e 630supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
ed9a39eb 631{
7f7fe91e 632 arm_linux_supply_nwfpe (NULL, regcache, -1, fpregsetp, 0);
ed9a39eb
JM
633}
634
9308fc88
DJ
635/* Fetch the thread-local storage pointer for libthread_db. */
636
637ps_err_e
638ps_get_thread_area (const struct ps_prochandle *ph,
639 lwpid_t lwpid, int idx, void **base)
640{
641 if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
642 return PS_ERR;
643
644 /* IDX is the bias from the thread pointer to the beginning of the
645 thread descriptor. It has to be subtracted due to implementation
646 quirks in libthread_db. */
647 *base = (void *) ((char *)*base - idx);
648
649 return PS_OK;
650}
651
ed9a39eb
JM
652static unsigned int
653get_linux_version (unsigned int *vmajor,
654 unsigned int *vminor,
655 unsigned int *vrelease)
656{
657 struct utsname info;
658 char *pmajor, *pminor, *prelease, *tail;
659
660 if (-1 == uname (&info))
661 {
edefbb7c 662 warning (_("Unable to determine GNU/Linux version."));
ed9a39eb
JM
663 return -1;
664 }
665
666 pmajor = strtok (info.release, ".");
667 pminor = strtok (NULL, ".");
668 prelease = strtok (NULL, ".");
669
670 *vmajor = (unsigned int) strtoul (pmajor, &tail, 0);
671 *vminor = (unsigned int) strtoul (pminor, &tail, 0);
672 *vrelease = (unsigned int) strtoul (prelease, &tail, 0);
673
674 return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
675}
676
81adfced
DJ
677static const struct target_desc *
678arm_linux_read_description (struct target_ops *ops)
05a4558a 679{
3b273a55
RE
680 CORE_ADDR arm_hwcap = 0;
681 arm_linux_has_wmmx_registers = 0;
682 arm_linux_vfp_register_count = 0;
05a4558a 683
3b273a55
RE
684 if (target_auxv_search (ops, AT_HWCAP, &arm_hwcap) != 1)
685 {
686 return NULL;
687 }
81adfced 688
3b273a55
RE
689 if (arm_hwcap & HWCAP_IWMMXT)
690 {
691 arm_linux_has_wmmx_registers = 1;
692 if (tdesc_arm_with_iwmmxt == NULL)
693 initialize_tdesc_arm_with_iwmmxt ();
694 return tdesc_arm_with_iwmmxt;
695 }
696
697 if (arm_hwcap & HWCAP_VFP)
698 {
699 int pid;
700 char *buf;
701 const struct target_desc * result = NULL;
702
703 /* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support
704 Neon with VFPv3-D32. */
705 if (arm_hwcap & HWCAP_NEON)
706 {
707 arm_linux_vfp_register_count = 32;
708 if (tdesc_arm_with_neon == NULL)
709 initialize_tdesc_arm_with_neon ();
710 result = tdesc_arm_with_neon;
711 }
712 else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
713 {
714 arm_linux_vfp_register_count = 32;
715 if (tdesc_arm_with_vfpv3 == NULL)
716 initialize_tdesc_arm_with_vfpv3 ();
717 result = tdesc_arm_with_vfpv3;
718 }
719 else
720 {
721 arm_linux_vfp_register_count = 16;
722 if (tdesc_arm_with_vfpv2 == NULL)
723 initialize_tdesc_arm_with_vfpv2 ();
724 result = tdesc_arm_with_vfpv2;
725 }
726
727 /* Now make sure that the kernel supports reading these
728 registers. Support was added in 2.6.30. */
729 pid = GET_LWP (inferior_ptid);
730 errno = 0;
731 buf = alloca (VFP_REGS_SIZE);
732 if (ptrace (PTRACE_GETVFPREGS, pid, 0, buf) < 0
733 && errno == EIO)
734 result = NULL;
735
736 return result;
737 }
738
739 return NULL;
05a4558a
DJ
740}
741
10d6c8cd
DJ
742void _initialize_arm_linux_nat (void);
743
ed9a39eb
JM
744void
745_initialize_arm_linux_nat (void)
746{
10d6c8cd
DJ
747 struct target_ops *t;
748
ed9a39eb 749 os_version = get_linux_version (&os_major, &os_minor, &os_release);
10d6c8cd
DJ
750
751 /* Fill in the generic GNU/Linux methods. */
752 t = linux_target ();
753
754 /* Add our register access methods. */
755 t->to_fetch_registers = arm_linux_fetch_inferior_registers;
756 t->to_store_registers = arm_linux_store_inferior_registers;
757
81adfced 758 t->to_read_description = arm_linux_read_description;
05a4558a 759
10d6c8cd 760 /* Register the target. */
f973ed9c 761 linux_nat_add_target (t);
ed9a39eb 762}
This page took 0.665005 seconds and 4 git commands to generate.