aboutsummaryrefslogtreecommitdiff
path: root/gdb/inflow.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/inflow.c')
-rw-r--r--gdb/inflow.c337
1 files changed, 310 insertions, 27 deletions
diff --git a/gdb/inflow.c b/gdb/inflow.c
index b88352c..386a2e1 100644
--- a/gdb/inflow.c
+++ b/gdb/inflow.c
@@ -27,14 +27,18 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
+#ifndef UMAX_PTRACE
#include <sys/user.h>
+#endif
#include <signal.h>
#include <sys/ioctl.h>
-#include <sgtty.h>
#include <fcntl.h>
#ifdef UMAX_PTRACE
#include <a.out.h>
+#include <sys/ptrace.h>
+#define PTRACE_ATTACH PT_ATTACH
+#define PTRACE_DETACH PT_FREEPROC
#endif
#ifdef NEW_SUN_PTRACE
@@ -42,6 +46,26 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <machine/reg.h>
#endif
+#ifdef HP9K320
+#include <sys/ptrace.h>
+#include <sys/reg.h>
+#include <sys/trap.h>
+#endif
+
+#ifdef HAVE_TERMIO
+#include <termio.h>
+#undef TIOCGETP
+#define TIOCGETP TCGETA
+#undef TIOCSETN
+#define TIOCSETN TCSETA
+#undef TIOCSETP
+#define TIOCSETP TCSETAF
+#define TERMINAL struct termio
+#else
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+#endif
+
extern int errno;
/* Nonzero if we are debugging an attached outside process
@@ -53,19 +77,27 @@ START_FILE
/* Record terminal status separately for debugger and inferior. */
-static struct sgttyb sg_inferior;
-static struct tchars tc_inferior;
-static struct ltchars ltc_inferior;
-static int lmode_inferior;
+static TERMINAL sg_inferior;
+static TERMINAL sg_ours;
static int tflags_inferior;
-static int pgrp_inferior;
+static int tflags_ours;
-static struct sgttyb sg_ours;
+#ifdef TIOCGLTC
+static struct tchars tc_inferior;
static struct tchars tc_ours;
+static struct ltchars ltc_inferior;
static struct ltchars ltc_ours;
+static int lmode_inferior;
static int lmode_ours;
-static int tflags_ours;
+#endif /* TIOCGLTC */
+
+#ifdef TIOCGPGRP
+static int pgrp_inferior;
static int pgrp_ours;
+#else
+static int (*sigint_ours) ();
+static int (*sigquit_ours) ();
+#endif /* TIOCGPGRP */
/* Copy of inferior_io_terminal when inferior was last started. */
static char *inferior_thisrun_terminal;
@@ -86,11 +118,17 @@ terminal_init_inferior ()
return;
sg_inferior = sg_ours;
+ tflags_inferior = tflags_ours;
+
+#ifdef TIOCGLTC
tc_inferior = tc_ours;
ltc_inferior = ltc_ours;
lmode_inferior = lmode_ours;
- tflags_inferior = tflags_ours;
+#endif /* TIOCGLTC */
+
+#ifdef TIOCGPGRP
pgrp_inferior = inferior_pid;
+#endif /* TIOCGPGRP */
terminal_is_ours = 1;
}
@@ -109,10 +147,19 @@ terminal_inferior ()
fcntl (0, F_SETFL, tflags_inferior);
fcntl (0, F_SETFL, tflags_inferior);
ioctl (0, TIOCSETN, &sg_inferior);
+
+#ifdef TIOCGLTC
ioctl (0, TIOCSETC, &tc_inferior);
ioctl (0, TIOCSLTC, &ltc_inferior);
ioctl (0, TIOCLSET, &lmode_inferior);
+#endif /* TIOCGLTC */
+
+#ifdef TIOCGPGRP
ioctl (0, TIOCSPGRP, &pgrp_inferior);
+#else
+ sigint_ours = (signal (SIGINT, SIG_IGN));
+ sigquit_ours = (signal (SIGQUIT, SIG_IGN));
+#endif /* TIOCGPGRP */
}
terminal_is_ours = 0;
}
@@ -151,38 +198,63 @@ static void
terminal_ours_1 (output_only)
int output_only;
{
+#ifdef TIOCGPGRP
/* Ignore this signal since it will happen when we try to set the pgrp. */
int (*osigttou) ();
+#endif /* TIOCGPGRP */
if (!terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
{
terminal_is_ours = 1;
+#ifdef TIOCGPGRP
osigttou = signal (SIGTTOU, SIG_IGN);
ioctl (0, TIOCGPGRP, &pgrp_inferior);
ioctl (0, TIOCSPGRP, &pgrp_ours);
signal (SIGTTOU, osigttou);
+#else
+ signal (SIGINT, sigint_ours);
+ signal (SIGQUIT, sigquit_ours);
+#endif /* TIOCGPGRP */
tflags_inferior = fcntl (0, F_GETFL, 0);
ioctl (0, TIOCGETP, &sg_inferior);
+
+#ifdef TIOCGLTC
ioctl (0, TIOCGETC, &tc_inferior);
ioctl (0, TIOCGLTC, &ltc_inferior);
ioctl (0, TIOCLGET, &lmode_inferior);
+#endif /* TIOCGLTC */
}
+#ifdef HAVE_TERMIO
+ sg_ours.c_lflag |= ICANON;
+ if (output_only && !(sg_inferior.c_lflag & ICANON))
+ sg_ours.c_lflag &= ~ICANON;
+#else /* not HAVE_TERMIO */
sg_ours.sg_flags &= ~RAW & ~CBREAK;
if (output_only)
sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
+#endif /* not HAVE_TERMIO */
fcntl (0, F_SETFL, tflags_ours);
fcntl (0, F_SETFL, tflags_ours);
ioctl (0, TIOCSETN, &sg_ours);
+
+#ifdef TIOCGLTC
ioctl (0, TIOCSETC, &tc_ours);
ioctl (0, TIOCSLTC, &ltc_ours);
ioctl (0, TIOCLSET, &lmode_ours);
+#endif /* TIOCGLTC */
+
+
+#ifdef HAVE_TERMIO
+ sg_ours.c_lflag |= ICANON;
+#else /* not HAVE_TERMIO */
sg_ours.sg_flags &= ~RAW & ~CBREAK;
+#endif /* not HAVE_TERMIO */
}
static void
@@ -197,6 +269,20 @@ term_status_command ()
}
printf ("Inferior's terminal status (currently saved by GDB):\n");
+
+#ifdef HAVE_TERMIO
+
+ printf ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n",
+ tflags_inferior, sg_inferior.c_iflag, sg_inferior.c_oflag);
+ printf ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
+ sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line);
+ printf ("c_cc: ");
+ for (i = 0; (i < NCC); i += 1)
+ printf ("0x%x ", sg_inferior.c_cc[i]);
+ printf ("\n");
+
+#else /* not HAVE_TERMIO */
+
printf ("fcntl flags = 0x%x, lmode = 0x%x,\nsgttyb.sg_flags = 0x%x, owner pid = %d.\n",
tflags_inferior, lmode_inferior,
sg_inferior.sg_flags, pgrp_inferior);
@@ -207,7 +293,8 @@ term_status_command ()
printf ("ltchars: ");
for (i = 0; i < sizeof (struct ltchars); i++)
printf ("0x%x ", ((char *)&ltc_inferior)[i]);
- printf ("\n");
+
+#endif /* not HAVE_TERMIO */
}
static void
@@ -243,19 +330,34 @@ new_tty (ttyname)
}
/* Start an inferior process and returns its pid.
- ALLARGS is a vector of program-name and args.
+ ALLARGS is a string containing shell command to run the program.
ENV is the environment vector to pass. */
+#ifndef SHELL_FILE
+#define SHELL_FILE "/bin/sh"
+#endif
+
int
create_inferior (allargs, env)
- char **allargs;
+ char *allargs;
char **env;
{
int pid;
+ char *shell_command;
extern int sys_nerr;
extern char *sys_errlist[];
extern int errno;
+ /* If desired, concat something onto the front of ALLARGS.
+ SHELL_COMMAND is the result. */
+#ifdef SHELL_COMMAND_CONCAT
+ shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + strlen (allargs) + 1);
+ strcpy (shell_command, SHELL_COMMAND_CONCAT);
+ strcat (shell_command, allargs);
+#else
+ shell_command = allargs;
+#endif
+
/* exec is said to fail if the executable is open. */
close_exec_file ();
@@ -265,8 +367,12 @@ create_inferior (allargs, env)
if (pid == 0)
{
+ char *args[4];
+
+#ifdef TIOCGPGRP
/* Run inferior in a separate process group. */
setpgrp (getpid (), getpid ());
+#endif /* TIOCGPGRP */
inferior_thisrun_terminal = inferior_io_terminal;
if (inferior_io_terminal != 0)
@@ -278,9 +384,15 @@ create_inferior (allargs, env)
signal (SIGINT, SIG_DFL); */
ptrace (0);
- execle ("/bin/sh", "sh", "-c", allargs, 0, env);
- fprintf (stderr, "Cannot exec /bin/sh: %s.\n",
+ args[0] = "sh";
+ args[1] = "-c";
+ args[2] = shell_command;
+ args[3] = 0;
+
+ execve (SHELL_FILE, args, env);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", SHELL_FILE,
errno < sys_nerr ? sys_errlist[errno] : "unknown error");
fflush (stderr);
_exit (0177);
@@ -313,6 +425,18 @@ kill_inferior ()
inferior_died ();
}
+/* This is used when GDB is exiting. It gives less chance of error.*/
+
+kill_inferior_fast ()
+{
+ if (remote_debugging)
+ return;
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+}
+
inferior_died ()
{
inferior_pid = 0;
@@ -343,7 +467,7 @@ resume (step, signal)
}
}
-#ifdef NEW_SUN_PTRACE
+#ifdef ATTACH_DETACH
/* Start debugging the process whose number is PID. */
@@ -372,7 +496,7 @@ detach (signal)
perror_with_name ("ptrace");
attach_flag = 0;
}
-#endif
+#endif /* ATTACH_DETACH */
#ifdef NEW_SUN_PTRACE
@@ -431,6 +555,146 @@ store_inferior_registers (regno)
}
#else
+#ifdef HP9K320
+
+#define FP_REGISTER_ADDR_DIFF(u, regno) \
+ (((char *) (FP_REGISTER_ADDR (u, regno))) - ((char *) &(u)))
+
+#define INFERIOR_AR0(u) \
+ ((ptrace \
+ (PT_RUAREA, inferior_pid, ((char *) &u.u_ar0 - (char *) &u), 0)) \
+ - KERNEL_U_ADDR)
+
+static void
+fetch_inferior_register (regno, regaddr)
+ register int regno;
+ register unsigned int regaddr;
+{
+#ifndef HPUX_VERSION_5
+ if (regno == PS_REGNUM)
+ {
+ union { int i; short s[2]; } ps_val;
+ int regval;
+
+ ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
+ regval = ps_val.s[0];
+ supply_register (regno, &regval);
+ }
+ else
+#endif /* not HPUX_VERSION_5 */
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (PT_RUAREA, inferior_pid, regaddr, 0);
+ regaddr += sizeof (int);
+ }
+ supply_register (regno, buf);
+ }
+ return;
+}
+
+static void
+store_inferior_register_1 (regno, regaddr, value)
+ int regno;
+ unsigned int regaddr;
+ int value;
+{
+ errno = 0;
+ ptrace (PT_WUAREA, inferior_pid, regaddr, value);
+#if 0
+ /* HP-UX randomly sets errno to non-zero for regno == 25.
+ However, the value is correctly written, so ignore errno. */
+ if (errno != 0)
+ {
+ char string_buf[64];
+
+ sprintf (string_buf, "writing register number %d", regno);
+ perror_with_name (string_buf);
+ }
+#endif
+ return;
+}
+
+static void
+store_inferior_register (regno, regaddr)
+ register int regno;
+ register unsigned int regaddr;
+{
+#ifndef HPUX_VERSION_5
+ if (regno == PS_REGNUM)
+ {
+ union { int i; short s[2]; } ps_val;
+
+ ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
+ ps_val.s[0] = (read_register (regno));
+ store_inferior_register_1 (regno, regaddr, ps_val.i);
+ }
+ else
+#endif /* not HPUX_VERSION_5 */
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+ extern char registers[];
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ store_inferior_register_1
+ (regno, regaddr,
+ (*(int *) &registers[(REGISTER_BYTE (regno)) + i]));
+ regaddr += sizeof (int);
+ }
+ }
+ return;
+}
+
+void
+fetch_inferior_registers ()
+{
+ struct user u;
+ register int regno;
+ register unsigned int ar0_offset;
+
+ ar0_offset = (INFERIOR_AR0 (u));
+ for (regno = 0; (regno < FP0_REGNUM); regno++)
+ fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+ for (; (regno < NUM_REGS); regno++)
+ fetch_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno)));
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ register int regno;
+{
+ struct user u;
+ register unsigned int ar0_offset;
+
+ if (regno >= FP0_REGNUM)
+ {
+ store_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno)));
+ return;
+ }
+
+ ar0_offset = (INFERIOR_AR0 (u));
+ if (regno >= 0)
+ {
+ store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+ return;
+ }
+
+ for (regno = 0; (regno < FP0_REGNUM); regno++)
+ store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+ for (; (regno < NUM_REGS); regno++)
+ store_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno)));
+ return;
+}
+
+#else /* not HP9K320 */
void
fetch_inferior_registers ()
@@ -469,6 +733,8 @@ store_inferior_registers (regno)
{
register unsigned int regaddr;
char buf[80];
+ extern char registers[];
+ int i;
#ifdef UMAX_PTRACE
unsigned int offset = 0;
@@ -481,27 +747,38 @@ store_inferior_registers (regno)
if (regno >= 0)
{
regaddr = register_addr (regno, offset);
- errno = 0;
- ptrace (6, inferior_pid, regaddr, read_register (regno));
- if (errno != 0)
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
{
- sprintf (buf, "writing register number %d", regno);
- perror_with_name (buf);
+ errno = 0;
+ ptrace (6, inferior_pid, regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d(%d)", regno, i);
+ perror_with_name (buf);
+ }
+ regaddr += sizeof(int);
}
}
else for (regno = 0; regno < NUM_REGS; regno++)
{
regaddr = register_addr (regno, offset);
- errno = 0;
- ptrace (6, inferior_pid, regaddr, read_register (regno));
- if (errno != 0)
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
{
- sprintf (buf, "writing register number %d", regno);
- perror_with_name (buf);
+ errno = 0;
+ ptrace (6, inferior_pid, regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d(%d)", regno, i);
+ perror_with_name (buf);
+ }
+ regaddr += sizeof(int);
}
}
}
+#endif /* not HP9K320 */
#endif /* not NEW_SUN_PTRACE */
/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
@@ -641,11 +918,17 @@ Report which ones can be written.");
inferior_pid = 0;
ioctl (0, TIOCGETP, &sg_ours);
+ fcntl (0, F_GETFL, tflags_ours);
+
+#ifdef TIOCGLTC
ioctl (0, TIOCGETC, &tc_ours);
ioctl (0, TIOCGLTC, &ltc_ours);
ioctl (0, TIOCLGET, &lmode_ours);
- fcntl (0, F_GETFL, tflags_ours);
+#endif /* TIOCGLTC */
+
+#ifdef TIOCGPGRP
ioctl (0, TIOCGPGRP, &pgrp_ours);
+#endif /* TIOCGPGRP */
terminal_is_ours = 1;
}