* gdbcore.h (struct regcache): Add forward declaration.
[deliverable/binutils-gdb.git] / gdb / m68klinux-nat.c
CommitLineData
a4b6fc86
AC
1/* Motorola m68k native support for GNU/Linux.
2
6aba47ca 3 Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
10d6c8cd 4 Free Software Foundation, Inc.
c906108c 5
c5aa993b 6 This file is part of GDB.
c906108c 7
c5aa993b
JM
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
c906108c 12
c5aa993b
JM
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
c906108c 17
c5aa993b
JM
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
197e01b6
EZ
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
c906108c
SS
22
23#include "defs.h"
24#include "frame.h"
25#include "inferior.h"
26#include "language.h"
27#include "gdbcore.h"
32eeb91a 28#include "gdb_string.h"
4e052eda 29#include "regcache.h"
10d6c8cd
DJ
30#include "target.h"
31#include "linux-nat.h"
c906108c 32
32eeb91a
AS
33#include "m68k-tdep.h"
34
c906108c
SS
35#include <sys/param.h>
36#include <sys/dir.h>
37#include <signal.h>
0280a90a 38#include <sys/ptrace.h>
c906108c
SS
39#include <sys/user.h>
40#include <sys/ioctl.h>
41#include <fcntl.h>
42#include <sys/procfs.h>
43
0280a90a
AS
44#ifdef HAVE_SYS_REG_H
45#include <sys/reg.h>
46#endif
47
c906108c
SS
48#include <sys/file.h>
49#include "gdb_stat.h"
50
51#include "floatformat.h"
52
53#include "target.h"
3e00823e
UW
54
55/* Prototypes for supply_gregset etc. */
56#include "gregset.h"
c906108c 57\f
77949794 58/* This table must line up with REGISTER_NAME in "m68k-tdep.c". */
c5aa993b 59static const int regmap[] =
c906108c
SS
60{
61 PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7,
62 PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP,
63 PT_SR, PT_PC,
64 /* PT_FP0, ..., PT_FP7 */
65 21, 24, 27, 30, 33, 36, 39, 42,
66 /* PT_FPCR, PT_FPSR, PT_FPIAR */
67 45, 46, 47
68};
69
0280a90a
AS
70/* Which ptrace request retrieves which registers?
71 These apply to the corresponding SET requests as well. */
72#define NUM_GREGS (18)
73#define MAX_NUM_REGS (NUM_GREGS + 11)
74
75int
76getregs_supplies (int regno)
77{
78 return 0 <= regno && regno < NUM_GREGS;
79}
80
81int
82getfpregs_supplies (int regno)
83{
32eeb91a 84 return FP0_REGNUM <= regno && regno <= M68K_FPI_REGNUM;
0280a90a
AS
85}
86
87/* Does the current host support the GETREGS request? */
88int have_ptrace_getregs =
89#ifdef HAVE_PTRACE_GETREGS
90 1
91#else
92 0
93#endif
94;
95
96\f
97
0280a90a
AS
98/* Fetching registers directly from the U area, one at a time. */
99
100/* FIXME: This duplicates code from `inptrace.c'. The problem is that we
101 define FETCH_INFERIOR_REGISTERS since we want to use our own versions
102 of {fetch,store}_inferior_registers that use the GETREGS request. This
103 means that the code in `infptrace.c' is #ifdef'd out. But we need to
104 fall back on that code when GDB is running on top of a kernel that
105 doesn't support the GETREGS request. */
106
107#ifndef PT_READ_U
108#define PT_READ_U PTRACE_PEEKUSR
109#endif
110#ifndef PT_WRITE_U
111#define PT_WRITE_U PTRACE_POKEUSR
112#endif
113
0280a90a
AS
114/* Fetch one register. */
115
116static void
117fetch_register (int regno)
118{
119 /* This isn't really an address. But ptrace thinks of it as one. */
120 CORE_ADDR regaddr;
121 char mess[128]; /* For messages */
52f0bd74 122 int i;
123a958e 123 char buf[MAX_REGISTER_SIZE];
0280a90a
AS
124 int tid;
125
126 if (CANNOT_FETCH_REGISTER (regno))
127 {
8de307e0 128 memset (buf, '\0', register_size (current_gdbarch, regno)); /* Supply zeroes */
23a6d369 129 regcache_raw_supply (current_regcache, regno, buf);
0280a90a
AS
130 return;
131 }
132
133 /* Overload thread id onto process id */
8de307e0
AS
134 tid = TIDGET (inferior_ptid);
135 if (tid == 0)
0280a90a
AS
136 tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
137
de732108 138 regaddr = 4 * regmap[regno];
8de307e0 139 for (i = 0; i < register_size (current_gdbarch, regno);
5f402660 140 i += sizeof (PTRACE_TYPE_RET))
0280a90a
AS
141 {
142 errno = 0;
5f402660
UW
143 *(PTRACE_TYPE_RET *) &buf[i] = ptrace (PT_READ_U, tid,
144 (PTRACE_TYPE_ARG3) regaddr, 0);
145 regaddr += sizeof (PTRACE_TYPE_RET);
0280a90a
AS
146 if (errno != 0)
147 {
148 sprintf (mess, "reading register %s (#%d)",
149 REGISTER_NAME (regno), regno);
150 perror_with_name (mess);
151 }
152 }
23a6d369 153 regcache_raw_supply (current_regcache, regno, buf);
0280a90a
AS
154}
155
156/* Fetch register values from the inferior.
157 If REGNO is negative, do this for all registers.
158 Otherwise, REGNO specifies which register (so we can save time). */
c906108c 159
10d6c8cd 160static void
0280a90a
AS
161old_fetch_inferior_registers (int regno)
162{
163 if (regno >= 0)
164 {
165 fetch_register (regno);
166 }
167 else
168 {
169 for (regno = 0; regno < NUM_REGS; regno++)
170 {
171 fetch_register (regno);
172 }
173 }
174}
175
176/* Store one register. */
177
178static void
179store_register (int regno)
180{
181 /* This isn't really an address. But ptrace thinks of it as one. */
182 CORE_ADDR regaddr;
183 char mess[128]; /* For messages */
52f0bd74 184 int i;
0280a90a 185 int tid;
d9d9c31f 186 char buf[MAX_REGISTER_SIZE];
0280a90a
AS
187
188 if (CANNOT_STORE_REGISTER (regno))
189 {
190 return;
191 }
192
193 /* Overload thread id onto process id */
8de307e0
AS
194 tid = TIDGET (inferior_ptid);
195 if (tid == 0)
0280a90a
AS
196 tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
197
de732108 198 regaddr = 4 * regmap[regno];
9852326a
AS
199
200 /* Put the contents of regno into a local buffer */
822c9732 201 regcache_raw_collect (current_regcache, regno, buf);
9852326a
AS
202
203 /* Store the local buffer into the inferior a chunk at the time. */
8de307e0 204 for (i = 0; i < register_size (current_gdbarch, regno);
5f402660 205 i += sizeof (PTRACE_TYPE_RET))
0280a90a
AS
206 {
207 errno = 0;
5f402660
UW
208 ptrace (PT_WRITE_U, tid, (PTRACE_TYPE_ARG3) regaddr,
209 *(PTRACE_TYPE_RET *) (buf + i));
210 regaddr += sizeof (PTRACE_TYPE_RET);
0280a90a
AS
211 if (errno != 0)
212 {
213 sprintf (mess, "writing register %s (#%d)",
214 REGISTER_NAME (regno), regno);
215 perror_with_name (mess);
216 }
217 }
218}
219
220/* Store our register values back into the inferior.
221 If REGNO is negative, do this for all registers.
222 Otherwise, REGNO specifies which register (so we can save time). */
223
10d6c8cd 224static void
0280a90a
AS
225old_store_inferior_registers (int regno)
226{
227 if (regno >= 0)
228 {
229 store_register (regno);
230 }
231 else
232 {
233 for (regno = 0; regno < NUM_REGS; regno++)
234 {
235 store_register (regno);
236 }
237 }
238}
239\f
f175af98
DJ
240/* Given a pointer to a general register set in /proc format
241 (elf_gregset_t *), unpack the register contents and supply
242 them as gdb's idea of the current register values. */
c906108c 243
c906108c 244void
7f7fe91e 245supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
c906108c 246{
7f7fe91e 247 const elf_greg_t *regp = (const elf_greg_t *) gregsetp;
c906108c
SS
248 int regi;
249
32eeb91a 250 for (regi = M68K_D0_REGNUM; regi <= SP_REGNUM; regi++)
7f7fe91e
UW
251 regcache_raw_supply (regcache, regi, &regp[regmap[regi]]);
252 regcache_raw_supply (regcache, PS_REGNUM, &regp[PT_SR]);
253 regcache_raw_supply (regcache, PC_REGNUM, &regp[PT_PC]);
0280a90a
AS
254}
255
256/* Fill register REGNO (if it is a general-purpose register) in
257 *GREGSETPS with the value in GDB's register array. If REGNO is -1,
258 do this for all registers. */
259void
7f7fe91e
UW
260fill_gregset (const struct regcache *regcache,
261 elf_gregset_t *gregsetp, int regno)
0280a90a
AS
262{
263 elf_greg_t *regp = (elf_greg_t *) gregsetp;
264 int i;
265
266 for (i = 0; i < NUM_GREGS; i++)
8de307e0 267 if (regno == -1 || regno == i)
7f7fe91e 268 regcache_raw_collect (regcache, i, regp + regmap[i]);
0280a90a
AS
269}
270
271#ifdef HAVE_PTRACE_GETREGS
272
273/* Fetch all general-purpose registers from process/thread TID and
274 store their values in GDB's register array. */
275
276static void
277fetch_regs (int tid)
278{
279 elf_gregset_t regs;
280
281 if (ptrace (PTRACE_GETREGS, tid, 0, (int) &regs) < 0)
282 {
283 if (errno == EIO)
284 {
285 /* The kernel we're running on doesn't support the GETREGS
286 request. Reset `have_ptrace_getregs'. */
287 have_ptrace_getregs = 0;
288 return;
289 }
290
e2e0b3e5 291 perror_with_name (_("Couldn't get registers"));
0280a90a
AS
292 }
293
7f7fe91e 294 supply_gregset (current_regcache, (const elf_gregset_t *) &regs);
c906108c
SS
295}
296
0280a90a
AS
297/* Store all valid general-purpose registers in GDB's register array
298 into the process/thread specified by TID. */
299
300static void
301store_regs (int tid, int regno)
302{
303 elf_gregset_t regs;
304
305 if (ptrace (PTRACE_GETREGS, tid, 0, (int) &regs) < 0)
e2e0b3e5 306 perror_with_name (_("Couldn't get registers"));
0280a90a 307
7f7fe91e 308 fill_gregset (current_regcache, &regs, regno);
0280a90a
AS
309
310 if (ptrace (PTRACE_SETREGS, tid, 0, (int) &regs) < 0)
e2e0b3e5 311 perror_with_name (_("Couldn't write registers"));
0280a90a
AS
312}
313
314#else
315
316static void fetch_regs (int tid) {}
317static void store_regs (int tid, int regno) {}
318
319#endif
320
321\f
322/* Transfering floating-point registers between GDB, inferiors and cores. */
323
324/* What is the address of fpN within the floating-point register set F? */
7f7fe91e 325#define FPREG_ADDR(f, n) (&(f)->fpregs[(n) * 3])
0280a90a
AS
326
327/* Fill GDB's register array with the floating-point register values in
328 *FPREGSETP. */
c906108c 329
c5aa993b 330void
7f7fe91e 331supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
c906108c
SS
332{
333 int regi;
334
32eeb91a 335 for (regi = FP0_REGNUM; regi < FP0_REGNUM + 8; regi++)
7f7fe91e 336 regcache_raw_supply (regcache, regi,
23a6d369 337 FPREG_ADDR (fpregsetp, regi - FP0_REGNUM));
7f7fe91e
UW
338 regcache_raw_supply (regcache, M68K_FPC_REGNUM, &fpregsetp->fpcntl[0]);
339 regcache_raw_supply (regcache, M68K_FPS_REGNUM, &fpregsetp->fpcntl[1]);
340 regcache_raw_supply (regcache, M68K_FPI_REGNUM, &fpregsetp->fpcntl[2]);
c906108c
SS
341}
342
0280a90a
AS
343/* Fill register REGNO (if it is a floating-point register) in
344 *FPREGSETP with the value in GDB's register array. If REGNO is -1,
345 do this for all registers. */
346
347void
7f7fe91e
UW
348fill_fpregset (const struct regcache *regcache,
349 elf_fpregset_t *fpregsetp, int regno)
0280a90a
AS
350{
351 int i;
352
353 /* Fill in the floating-point registers. */
354 for (i = FP0_REGNUM; i < FP0_REGNUM + 8; i++)
355 if (regno == -1 || regno == i)
7f7fe91e 356 regcache_raw_collect (regcache, i,
822c9732 357 FPREG_ADDR (fpregsetp, i - FP0_REGNUM));
0280a90a
AS
358
359 /* Fill in the floating-point control registers. */
32eeb91a 360 for (i = M68K_FPC_REGNUM; i <= M68K_FPI_REGNUM; i++)
0280a90a 361 if (regno == -1 || regno == i)
7f7fe91e
UW
362 regcache_raw_collect (regcache, i,
363 &fpregsetp->fpcntl[i - M68K_FPC_REGNUM]);
0280a90a
AS
364}
365
366#ifdef HAVE_PTRACE_GETREGS
367
368/* Fetch all floating-point registers from process/thread TID and store
369 thier values in GDB's register array. */
370
371static void
372fetch_fpregs (int tid)
373{
374 elf_fpregset_t fpregs;
375
376 if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0)
e2e0b3e5 377 perror_with_name (_("Couldn't get floating point status"));
0280a90a 378
7f7fe91e 379 supply_fpregset (current_regcache, (const elf_fpregset_t *) &fpregs);
0280a90a
AS
380}
381
382/* Store all valid floating-point registers in GDB's register array
383 into the process/thread specified by TID. */
384
385static void
386store_fpregs (int tid, int regno)
387{
388 elf_fpregset_t fpregs;
389
390 if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0)
e2e0b3e5 391 perror_with_name (_("Couldn't get floating point status"));
0280a90a 392
7f7fe91e 393 fill_fpregset (current_regcache, &fpregs, regno);
0280a90a
AS
394
395 if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0)
e2e0b3e5 396 perror_with_name (_("Couldn't write floating point status"));
0280a90a
AS
397}
398
399#else
400
401static void fetch_fpregs (int tid) {}
402static void store_fpregs (int tid, int regno) {}
403
c906108c 404#endif
0280a90a
AS
405\f
406/* Transferring arbitrary registers between GDB and inferior. */
407
408/* Fetch register REGNO from the child process. If REGNO is -1, do
409 this for all registers (including the floating point and SSE
410 registers). */
411
10d6c8cd
DJ
412static void
413m68k_linux_fetch_inferior_registers (int regno)
0280a90a
AS
414{
415 int tid;
416
417 /* Use the old method of peeking around in `struct user' if the
418 GETREGS request isn't available. */
419 if (! have_ptrace_getregs)
420 {
421 old_fetch_inferior_registers (regno);
422 return;
423 }
424
a4b6fc86 425 /* GNU/Linux LWP ID's are process ID's. */
8de307e0
AS
426 tid = TIDGET (inferior_ptid);
427 if (tid == 0)
0280a90a 428 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
f175af98 429
0280a90a
AS
430 /* Use the PTRACE_GETFPXREGS request whenever possible, since it
431 transfers more registers in one system call, and we'll cache the
432 results. But remember that fetch_fpxregs can fail, and return
433 zero. */
434 if (regno == -1)
435 {
436 fetch_regs (tid);
437
438 /* The call above might reset `have_ptrace_getregs'. */
439 if (! have_ptrace_getregs)
440 {
441 old_fetch_inferior_registers (-1);
442 return;
443 }
444
445 fetch_fpregs (tid);
446 return;
447 }
448
449 if (getregs_supplies (regno))
450 {
451 fetch_regs (tid);
452 return;
453 }
454
455 if (getfpregs_supplies (regno))
456 {
457 fetch_fpregs (tid);
458 return;
459 }
460
461 internal_error (__FILE__, __LINE__,
e2e0b3e5 462 _("Got request for bad register number %d."), regno);
0280a90a
AS
463}
464
465/* Store register REGNO back into the child process. If REGNO is -1,
466 do this for all registers (including the floating point and SSE
467 registers). */
10d6c8cd
DJ
468static void
469m68k_linux_store_inferior_registers (int regno)
0280a90a
AS
470{
471 int tid;
472
473 /* Use the old method of poking around in `struct user' if the
474 SETREGS request isn't available. */
475 if (! have_ptrace_getregs)
476 {
477 old_store_inferior_registers (regno);
478 return;
479 }
480
a4b6fc86 481 /* GNU/Linux LWP ID's are process ID's. */
8de307e0
AS
482 tid = TIDGET (inferior_ptid);
483 if (tid == 0)
0280a90a
AS
484 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
485
486 /* Use the PTRACE_SETFPREGS requests whenever possible, since it
487 transfers more registers in one system call. But remember that
488 store_fpregs can fail, and return zero. */
489 if (regno == -1)
490 {
491 store_regs (tid, regno);
492 store_fpregs (tid, regno);
493 return;
494 }
495
496 if (getregs_supplies (regno))
497 {
498 store_regs (tid, regno);
499 return;
500 }
501
502 if (getfpregs_supplies (regno))
503 {
504 store_fpregs (tid, regno);
505 return;
506 }
507
508 internal_error (__FILE__, __LINE__,
e2e0b3e5 509 _("Got request to store bad register number %d."), regno);
0280a90a 510}
f175af98
DJ
511\f
512/* Interpreting register set info found in core files. */
513
514/* Provide registers to GDB from a core file.
515
516 (We can't use the generic version of this function in
517 core-regset.c, because we need to use elf_gregset_t instead of
518 gregset_t.)
519
520 CORE_REG_SECT points to an array of bytes, which are the contents
521 of a `note' from a core file which BFD thinks might contain
522 register contents. CORE_REG_SIZE is its size.
523
524 WHICH says which register set corelow suspects this is:
525 0 --- the general-purpose register set, in elf_gregset_t format
526 2 --- the floating-point register set, in elf_fpregset_t format
527
a4b6fc86 528 REG_ADDR isn't used on GNU/Linux. */
f175af98
DJ
529
530static void
9eefc95f
UW
531fetch_core_registers (struct regcache *regcache,
532 char *core_reg_sect, unsigned core_reg_size,
f175af98
DJ
533 int which, CORE_ADDR reg_addr)
534{
535 elf_gregset_t gregset;
536 elf_fpregset_t fpregset;
537
538 switch (which)
539 {
540 case 0:
541 if (core_reg_size != sizeof (gregset))
8a3fe4f8 542 warning (_("Wrong size gregset in core file."));
f175af98
DJ
543 else
544 {
545 memcpy (&gregset, core_reg_sect, sizeof (gregset));
9eefc95f 546 supply_gregset (regcache, (const elf_gregset_t *) &gregset);
f175af98
DJ
547 }
548 break;
549
550 case 2:
551 if (core_reg_size != sizeof (fpregset))
8a3fe4f8 552 warning (_("Wrong size fpregset in core file."));
f175af98
DJ
553 else
554 {
555 memcpy (&fpregset, core_reg_sect, sizeof (fpregset));
9eefc95f 556 supply_fpregset (regcache, (const elf_fpregset_t *) &fpregset);
f175af98
DJ
557 }
558 break;
559
560 default:
561 /* We've covered all the kinds of registers we know about here,
562 so this must be something we wouldn't know what to do with
563 anyway. Just ignore it. */
564 break;
565 }
566}
c906108c 567\f
c5aa993b 568
a4b6fc86
AC
569/* Register that we are able to handle GNU/Linux ELF core file
570 formats. */
f175af98
DJ
571
572static struct core_fns linux_elf_core_fns =
573{
574 bfd_target_elf_flavour, /* core_flavour */
575 default_check_format, /* check_format */
576 default_core_sniffer, /* core_sniffer */
577 fetch_core_registers, /* core_read_registers */
578 NULL /* next */
579};
580
10d6c8cd
DJ
581void _initialize_m68k_linux_nat (void);
582
f175af98 583void
5ae5f592 584_initialize_m68k_linux_nat (void)
f175af98 585{
10d6c8cd
DJ
586 struct target_ops *t;
587
588 /* Fill in the generic GNU/Linux methods. */
589 t = linux_target ();
590
591 /* Add our register access methods. */
592 t->to_fetch_registers = m68k_linux_fetch_inferior_registers;
593 t->to_store_registers = m68k_linux_store_inferior_registers;
594
595 /* Register the target. */
f973ed9c 596 linux_nat_add_target (t);
10d6c8cd 597
00e32a35 598 deprecated_add_core_fns (&linux_elf_core_fns);
f175af98 599}
This page took 0.591645 seconds and 4 git commands to generate.