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