1 /* Native-dependent code for LynxOS.
3 Copyright (C) 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2003 Free
4 Software Foundation, Inc.
6 This file is part of GDB.
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.
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.
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
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
30 #include <sys/ptrace.h>
34 static unsigned long registers_addr (int pid
);
35 static void fetch_core_registers (char *, unsigned, int, CORE_ADDR
);
37 #define X(ENTRY)(offsetof(struct econtext, ENTRY))
40 /* Mappings from tm-i386v.h */
58 X (ecode
), /* Lynx doesn't give us either fs or gs, so */
59 X (fault
), /* we just substitute these two in the hopes
60 that they are useful. */
65 /* Mappings from tm-m68k.h */
79 X (regs
[10]), /* a2 */
80 X (regs
[11]), /* a3 */
81 X (regs
[12]), /* a4 */
82 X (regs
[13]), /* a5 */
83 X (regs
[14]), /* fp */
84 offsetof (st_t
, usp
) - offsetof (st_t
, ec
), /* sp */
88 X (fregs
[0 * 3]), /* fp0 */
89 X (fregs
[1 * 3]), /* fp1 */
90 X (fregs
[2 * 3]), /* fp2 */
91 X (fregs
[3 * 3]), /* fp3 */
92 X (fregs
[4 * 3]), /* fp4 */
93 X (fregs
[5 * 3]), /* fp5 */
94 X (fregs
[6 * 3]), /* fp6 */
95 X (fregs
[7 * 3]), /* fp7 */
97 X (fcregs
[0]), /* fpcontrol */
98 X (fcregs
[1]), /* fpstatus */
99 X (fcregs
[2]), /* fpiaddr */
100 X (ssw
), /* fpcode */
101 X (fault
), /* fpflags */
106 /* Mappings from tm-sparc.h */
108 #define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
110 static int regmap
[] =
117 -1, /* g5->g7 aren't saved by Lynx */
130 -1, -1, -1, -1, -1, -1, -1, -1, /* l0 -> l7 */
132 -1, -1, -1, -1, -1, -1, -1, -1, /* i0 -> i7 */
134 FX (f
.fregs
[0]), /* f0 */
180 static int regmap
[] =
182 X (iregs
[0]), /* r0 */
215 X (fregs
[0]), /* f0 */
248 X (srr0
), /* IAR (PC) */
249 X (srr1
), /* MSR (PS) */
259 #if defined (I386) || defined (M68K) || defined (rs6000)
261 /* Return the offset relative to the start of the per-thread data to the
262 saved context block. */
265 registers_addr (int pid
)
268 int ecpoff
= offsetof (st_t
, ecp
);
272 stblock
= (CORE_ADDR
) ptrace (PTRACE_THREADUSER
, pid
, (PTRACE_ARG3_TYPE
) 0,
275 perror_with_name ("ptrace(PTRACE_THREADUSER)");
277 ecp
= (CORE_ADDR
) ptrace (PTRACE_PEEKTHREAD
, pid
, (PTRACE_ARG3_TYPE
) ecpoff
,
280 perror_with_name ("ptrace(PTRACE_PEEKTHREAD)");
282 return ecp
- stblock
;
285 /* Fetch one or more registers from the inferior. REGNO == -1 to get
286 them all. We actually fetch more than requested, when convenient,
287 marking them as valid so we won't fetch them again. */
290 fetch_inferior_registers (int regno
)
299 reghi
= NUM_REGS
- 1;
302 reglo
= reghi
= regno
;
304 ecp
= registers_addr (PIDGET (inferior_ptid
));
307 char buf
[MAX_REGISTER_SIZE
];
308 for (regno
= reglo
; regno
<= reghi
; regno
++)
310 int ptrace_fun
= PTRACE_PEEKTHREAD
;
313 ptrace_fun
= regno
== SP_REGNUM
? PTRACE_PEEKUSP
: PTRACE_PEEKTHREAD
;
316 for (i
= 0; i
< register_size (current_gdbarch
, regno
); i
+= sizeof (int))
321 reg
= ptrace (ptrace_fun
, PIDGET (inferior_ptid
),
322 (PTRACE_ARG3_TYPE
) (ecp
+ regmap
[regno
] + i
), 0);
324 perror_with_name ("ptrace(PTRACE_PEEKUSP)");
326 *(int *) &buf
[i
] = reg
;
328 regcache_raw_supply (current_regcache
, regno
, buf
);
333 /* Store our register values back into the inferior.
334 If REGNO is -1, do this for all registers.
335 Otherwise, REGNO specifies which register (so we can save time). */
338 store_inferior_registers (int regno
)
347 reghi
= NUM_REGS
- 1;
350 reglo
= reghi
= regno
;
352 ecp
= registers_addr (PIDGET (inferior_ptid
));
354 for (regno
= reglo
; regno
<= reghi
; regno
++)
356 int ptrace_fun
= PTRACE_POKEUSER
;
358 if (CANNOT_STORE_REGISTER (regno
))
362 ptrace_fun
= regno
== SP_REGNUM
? PTRACE_POKEUSP
: PTRACE_POKEUSER
;
365 for (i
= 0; i
< register_size (current_gdbarch
, regno
); i
+= sizeof (int))
369 reg
= *(unsigned int *) &deprecated_registers
[DEPRECATED_REGISTER_BYTE (regno
) + i
];
372 ptrace (ptrace_fun
, PIDGET (inferior_ptid
),
373 (PTRACE_ARG3_TYPE
) (ecp
+ regmap
[regno
] + i
), reg
);
375 perror_with_name ("ptrace(PTRACE_POKEUSP)");
379 #endif /* defined (I386) || defined (M68K) || defined (rs6000) */
381 /* Wait for child to do something. Return pid of child, or -1 in case
382 of error; store status through argument pointer OURSTATUS. */
385 child_wait (ptid_t ptid
, struct target_waitstatus
*ourstatus
)
396 set_sigint_trap (); /* Causes SIGINT to be passed on to the
398 pid
= wait (&status
);
402 clear_sigint_trap ();
406 if (save_errno
== EINTR
)
408 fprintf_unfiltered (gdb_stderr
, "Child process unexpectedly missing: %s.\n",
409 safe_strerror (save_errno
));
410 /* Claim it exited with unknown signal. */
411 ourstatus
->kind
= TARGET_WAITKIND_SIGNALLED
;
412 ourstatus
->value
.sig
= TARGET_SIGNAL_UNKNOWN
;
416 if (pid
!= PIDGET (inferior_ptid
)) /* Some other process?!? */
419 thread
= status
.w_tid
; /* Get thread id from status */
421 /* Initial thread value can only be acquired via wait, so we have to
422 resort to this hack. */
424 if (TIDGET (inferior_ptid
) == 0 && thread
!= 0)
426 inferior_ptid
= MERGEPID (PIDGET (inferior_ptid
), thread
);
427 add_thread (inferior_ptid
);
430 ptid
= BUILDPID (pid
, thread
);
432 /* We've become a single threaded process again. */
434 inferior_ptid
= ptid
;
436 /* Check for thread creation. */
437 if (WIFSTOPPED (status
)
438 && WSTOPSIG (status
) == SIGTRAP
439 && !in_thread_list (ptid
))
443 realsig
= ptrace (PTRACE_GETTRACESIG
, PIDGET (ptid
),
444 (PTRACE_ARG3_TYPE
) 0, 0);
446 if (realsig
== SIGNEWTHREAD
)
448 /* It's a new thread notification. We don't want to much with
449 realsig -- the code in wait_for_inferior expects SIGTRAP. */
450 ourstatus
->kind
= TARGET_WAITKIND_SPURIOUS
;
451 ourstatus
->value
.sig
= TARGET_SIGNAL_0
;
455 error ("Signal for unknown thread was not SIGNEWTHREAD");
458 /* Check for thread termination. */
459 else if (WIFSTOPPED (status
)
460 && WSTOPSIG (status
) == SIGTRAP
461 && in_thread_list (ptid
))
465 realsig
= ptrace (PTRACE_GETTRACESIG
, PIDGET (ptid
),
466 (PTRACE_ARG3_TYPE
) 0, 0);
468 if (realsig
== SIGTHREADEXIT
)
470 ptrace (PTRACE_CONT
, PIDGET (ptid
), (PTRACE_ARG3_TYPE
) 0, 0);
476 /* SPARC Lynx uses an byte reversed wait status; we must use the
477 host macros to access it. These lines just a copy of
478 store_waitstatus. We can't use CHILD_SPECIAL_WAITSTATUS
479 because target.c can't include the Lynx <sys/wait.h>. */
480 if (WIFEXITED (status
))
482 ourstatus
->kind
= TARGET_WAITKIND_EXITED
;
483 ourstatus
->value
.integer
= WEXITSTATUS (status
);
485 else if (!WIFSTOPPED (status
))
487 ourstatus
->kind
= TARGET_WAITKIND_SIGNALLED
;
488 ourstatus
->value
.sig
=
489 target_signal_from_host (WTERMSIG (status
));
493 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
494 ourstatus
->value
.sig
=
495 target_signal_from_host (WSTOPSIG (status
));
498 store_waitstatus (ourstatus
, status
.w_status
);
505 /* Return nonzero if the given thread is still alive. */
507 child_thread_alive (ptid_t ptid
)
509 int pid
= PIDGET (ptid
);
511 /* Arggh. Apparently pthread_kill only works for threads within
512 the process that calls pthread_kill.
514 We want to avoid the lynx signal extensions as they simply don't
515 map well to the generic gdb interface we want to keep.
517 All we want to do is determine if a particular thread is alive;
518 it appears as if we can just make a harmless thread specific
519 ptrace call to do that. */
520 return (ptrace (PTRACE_THREADUSER
, pid
, 0, 0) != -1);
523 /* Resume execution of the inferior process.
524 If STEP is nonzero, single-step it.
525 If SIGNAL is nonzero, give it that signal. */
528 child_resume (ptid_t ptid
, int step
, enum target_signal signal
)
531 int pid
= PIDGET (ptid
);
535 /* If pid == -1, then we want to step/continue all threads, else
536 we only want to step/continue a single thread. */
539 pid
= PIDGET (inferior_ptid
);
540 func
= step
? PTRACE_SINGLESTEP
: PTRACE_CONT
;
543 func
= step
? PTRACE_SINGLESTEP_ONE
: PTRACE_CONT_ONE
;
546 /* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
547 it was. (If GDB wanted it to start some other way, we have already
548 written a new PC value to the child.)
550 If this system does not support PT_STEP, a higher level function will
551 have called single_step() to transmute the step request into a
552 continue request (by setting breakpoints on all possible successor
553 instructions), so we don't have to worry about that here. */
555 ptrace (func
, pid
, (PTRACE_ARG3_TYPE
) 1, target_signal_to_host (signal
));
558 perror_with_name ("ptrace");
561 /* Convert a Lynx process ID to a string. Returns the string in a static
565 child_pid_to_str (ptid_t ptid
)
569 sprintf (buf
, "process %d thread %d", PIDGET (ptid
), TIDGET (ptid
));
574 /* Extract the register values out of the core file and store
575 them where `read_register' will find them.
577 CORE_REG_SECT points to the register values themselves, read into memory.
578 CORE_REG_SIZE is the size of that area.
579 WHICH says which set of registers we are handling (0 = int, 2 = float
580 on machines where they are discontiguous).
581 REG_ADDR is the offset from u.u_ar0 to the register values relative to
582 core_reg_sect. This is used with old-fashioned core files to
583 locate the registers in a large upage-plus-stack ".reg" section.
584 Original upage address X is at location core_reg_sect+x+reg_addr.
588 fetch_core_registers (char *core_reg_sect
, unsigned core_reg_size
, int which
,
594 for (regno
= 0; regno
< NUM_REGS
; regno
++)
595 if (regmap
[regno
] != -1)
596 regcache_raw_supply (current_regcache
, regno
,
597 core_reg_sect
+ offsetof (st_t
, ec
) + regmap
[regno
]);
600 /* Fetching this register causes all of the I & L regs to be read from the
601 stack and validated. */
603 fetch_inferior_registers (I0_REGNUM
);
608 /* Register that we are able to handle lynx core file formats.
609 FIXME: is this really bfd_target_unknown_flavour? */
611 static struct core_fns lynx_core_fns
=
613 bfd_target_unknown_flavour
, /* core_flavour */
614 default_check_format
, /* check_format */
615 default_core_sniffer
, /* core_sniffer */
616 fetch_core_registers
, /* core_read_registers */
621 _initialize_core_lynx (void)
623 deprecated_add_core_fns (&lynx_core_fns
);