aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog40
-rw-r--r--gdb/procfs.c858
-rw-r--r--gdb/sol-thread.c167
-rw-r--r--gdb/thread.c30
4 files changed, 715 insertions, 380 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8fdbff9..17ba1e8 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,43 @@
+Wed May 21 16:03:25 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
+
+ * procfs.c (init_procinfo): new function, abstracts some code
+ shared by create_procinfo and do_attach;
+ (procfs_set_inferior_syscall_traps): new function, abstracts
+ some code needed by procfs_init_inferior, do_attach, and
+ procfs_lwp_creation_handler; (procfs_first_available): new
+ function, find any LWP that's runnable; (procfs_thread_alive):
+ replace stub function with real implementation;
+ (procfs_lwp_creation_handler): fix bug starting new child
+ threads; (info_proc): bug fixes and enhancements for the
+ "INFO PROCESSES" command; (close_procinfo_file): call new
+ function "delete_thread" to cleanup GDB's thread database;
+ (proc_init_failed): add new argument "kill", to control whether
+ process is killed (so this function can be shared by
+ create_procinfo and do_attach); (procfs_exit_handler): handle
+ exit from an attached process, and cleanup procinfo handles
+ when the process exits; (procfs_resume, procfs_wait): cleanup
+ after a thread when it exits; (do_attach, do_detach): handle
+ attached processes with multiple threads; plus some general
+ improvements in the diagnostic output.
+ * sol-thread.c (sol_thread_alive): replace stub with real
+ implementation; (thread_to_lwp, lwp_to_thread): enhance to
+ handle threads that may have exited; (sol_thread_attach): add
+ startup setup stuff; (sol_thread_detach): add unpush_target
+ call; (sol_thread_mourn_inferior): add unpush_target call;
+ (sol_thread_wait, sol_thread_resume): enhance to deal with
+ thread exit cleanly; (sol_thread_new_objfile,
+ sol_thread_pid_to_str): detect unsuccessful startup and
+ don't crash; plus some general cleanup.
+ * thread.c (delete_thread): new function, allows targets to
+ notify gdb when a thread is no longer valid.
+ * infrun.c (wait_for_inferior): don't try to detect a new
+ thread on receiving a TARGET_EXITED event.
+
+Tue May 20 09:32:02 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * remote-sim.c (gdbsim_open): Pass callback struct.
+ (init_callbacks): Remove call to sim_set_callbacks.
+
Thu May 15 07:56:50 1997 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
* config/rs6000/tm-rs6000.h (SIG_FRAME_LR_OFFSET): Define.
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 9d3c969..c6a74a3 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -181,14 +181,15 @@ struct procinfo {
struct sig_ctl saved_trace; /* Saved traced signal set */
struct sys_ctl saved_exitset; /* Saved traced system call exit set */
struct sys_ctl saved_entryset;/* Saved traced system call entry set */
- int num_syscall_handlers; /* Number of syscall handlers currently installed */
- struct procfs_syscall_handler *syscall_handlers; /* Pointer to list of syscall trap handlers */
+ int num_syscall_handlers; /* Number of syscall trap handlers
+ currently installed */
+ /* Pointer to list of syscall trap handlers */
+ struct procfs_syscall_handler *syscall_handlers;
int new_child; /* Non-zero if it's a new thread */
};
/* List of inferior process information */
static struct procinfo *procinfo_list = NULL;
-
static struct pollfd *poll_list; /* pollfds used for waiting on /proc */
static int num_poll_list = 0; /* Number of entries in poll_list */
@@ -248,6 +249,15 @@ static struct trans pr_flag_table[] =
#if defined (PR_PCOMPAT)
{ PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect" },
#endif
+#if defined (PR_MSACCT)
+ { PR_MSACCT, "PR_MSACCT", "Microstate accounting enabled" },
+#endif
+#if defined (PR_BPTADJ)
+ { PR_BPTADJ, "PR_BPTADJ", "Breakpoint PC adjustment in effect" },
+#endif
+#if defined (PR_ASLWP)
+ { PR_ASLWP, "PR_ASLWP", "Asynchronus signal LWP" },
+#endif
{ 0, NULL, NULL }
};
@@ -261,9 +271,6 @@ static struct trans pr_why_table[] =
#if defined (PR_SIGNALLED)
{ PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal" },
#endif
-#if defined (PR_FAULTED)
- { PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" },
-#endif
#if defined (PR_SYSENTRY)
{ PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call" },
#endif
@@ -273,9 +280,15 @@ static struct trans pr_why_table[] =
#if defined (PR_JOBCONTROL)
{ PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action" },
#endif
+#if defined (PR_FAULTED)
+ { PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" },
+#endif
#if defined (PR_SUSPENDED)
{ PR_SUSPENDED, "PR_SUSPENDED", "Process suspended" },
#endif
+#if defined (PR_CHECKPOINT)
+ { PR_CHECKPOINT, "PR_CHECKPOINT", "(???)" },
+#endif
{ 0, NULL, NULL }
};
@@ -502,7 +515,7 @@ static void close_proc_file PARAMS ((struct procinfo *));
static void unconditionally_kill_inferior PARAMS ((struct procinfo *));
-static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *)) ATTR_NORETURN;
+static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *, int)) ATTR_NORETURN;
static void info_proc PARAMS ((char *, int));
@@ -538,8 +551,8 @@ static void notice_signals PARAMS ((struct procinfo *, struct sig_ctl *));
static struct procinfo *find_procinfo PARAMS ((pid_t pid, int okfail));
-static int procfs_read_status PARAMS ((struct procinfo *));
static int procfs_write_pcwstop PARAMS ((struct procinfo *));
+static int procfs_read_status PARAMS ((struct procinfo *));
static void procfs_write_pckill PARAMS ((struct procinfo *));
typedef int syscall_func_t PARAMS ((struct procinfo *pi, int syscall_num,
@@ -684,6 +697,22 @@ add_fd (pi)
num_poll_list++;
}
+/*
+
+LOCAL FUNCTION
+
+ remove_fd -- Remove the fd from the poll/select list
+
+SYNOPSIS
+
+ static void remove_fd (struct procinfo *);
+
+DESCRIPTION
+
+ Remove the fd of the supplied procinfo from the list of fds used
+ for poll/select operations.
+ */
+
static void
remove_fd (pi)
struct procinfo *pi;
@@ -859,7 +888,8 @@ wait_fd ()
for (i = 0; i < num_poll_list && num_fds > 0; i++)
{
- if ((poll_list[i].revents & (POLLWRNORM|POLLPRI|POLLERR|POLLHUP|POLLNVAL)) == 0)
+ if (0 == (poll_list[i].revents &
+ (POLLWRNORM | POLLPRI | POLLERR | POLLHUP | POLLNVAL)))
continue;
for (pi = procinfo_list; pi; pi = pi->next)
{
@@ -867,8 +897,11 @@ wait_fd ()
{
if (!procfs_read_status(pi))
{
- print_sys_errmsg (pi->pathname, errno);
- error ("procfs_read_status failed");
+ /* The LWP has apparently terminated. */
+ if (info_verbose)
+ printf_filtered ("LWP %d doesn't respond.\n",
+ (pi->pid >> 16) & 0xffff);
+ /* could call close_proc_file here, but I'm afraid to... */
}
num_fds--;
@@ -1549,23 +1582,23 @@ init_syscall_table ()
#if defined (SYS_settimeofday)
syscall_table[SYS_settimeofday] = "settimeofday";
#endif
-#if defined (SYS_lwpcreate)
- syscall_table[SYS_lwpcreate] = "lwpcreate";
+#if defined (SYS_lwp_create)
+ syscall_table[SYS_lwp_create] = "_lwp_create";
#endif
-#if defined (SYS_lwpexit)
- syscall_table[SYS_lwpexit] = "lwpexit";
+#if defined (SYS_lwp_exit)
+ syscall_table[SYS_lwp_exit] = "_lwp_exit";
#endif
-#if defined (SYS_lwpwait)
- syscall_table[SYS_lwpwait] = "lwpwait";
+#if defined (SYS_lwp_wait)
+ syscall_table[SYS_lwp_wait] = "_lwp_wait";
#endif
-#if defined (SYS_lwpself)
- syscall_table[SYS_lwpself] = "lwpself";
+#if defined (SYS_lwp_self)
+ syscall_table[SYS_lwp_self] = "_lwp_self";
#endif
-#if defined (SYS_lwpinfo)
- syscall_table[SYS_lwpinfo] = "lwpinfo";
+#if defined (SYS_lwp_info)
+ syscall_table[SYS_lwp_info] = "_lwp_info";
#endif
-#if defined (SYS_lwpprivate)
- syscall_table[SYS_lwpprivate] = "lwpprivate";
+#if defined (SYS_lwp_private)
+ syscall_table[SYS_lwp_private] = "_lwp_private";
#endif
#if defined (SYS_processor_bind)
syscall_table[SYS_processor_bind] = "processor_bind";
@@ -1600,8 +1633,8 @@ init_syscall_table ()
#if defined (SYS_ftruncate)
syscall_table[SYS_ftruncate] = "ftruncate";
#endif
-#if defined (SYS_lwpkill)
- syscall_table[SYS_lwpkill] = "lwpkill";
+#if defined (SYS_lwp_kill)
+ syscall_table[SYS_lwp_kill] = "_lwp_kill";
#endif
#if defined (SYS_sigwait)
syscall_table[SYS_sigwait] = "sigwait";
@@ -1630,11 +1663,11 @@ init_syscall_table ()
#if defined (SYS_getksym)
syscall_table[SYS_getksym] = "getksym";
#endif
-#if defined (SYS_lwpsuspend)
- syscall_table[SYS_lwpsuspend] = "lwpsuspend";
+#if defined (SYS_lwp_suspend)
+ syscall_table[SYS_lwp_suspend] = "_lwp_suspend";
#endif
-#if defined (SYS_lwpcontinue)
- syscall_table[SYS_lwpcontinue] = "lwpcontinue";
+#if defined (SYS_lwp_continue)
+ syscall_table[SYS_lwp_continue] = "_lwp_continue";
#endif
#if defined (SYS_priocntllst)
syscall_table[SYS_priocntllst] = "priocntllst";
@@ -1643,10 +1676,10 @@ init_syscall_table ()
syscall_table[SYS_sleep] = "sleep";
#endif
#if defined (SYS_lwp_sema_wait)
- syscall_table[SYS_lwp_sema_wait] = "lwp_sema_wait";
+ syscall_table[SYS_lwp_sema_wait] = "_lwp_sema_wait";
#endif
#if defined (SYS_lwp_sema_post)
- syscall_table[SYS_lwp_sema_post] = "lwp_sema_post";
+ syscall_table[SYS_lwp_sema_post] = "_lwp_sema_post";
#endif
#if defined (SYS_lwp_sema_trywait)
syscall_table[SYS_lwp_sema_trywait] = "lwp_sema_trywait";
@@ -1928,17 +1961,17 @@ procfs_store_registers (regno)
LOCAL FUNCTION
- create_procinfo - initialize access to a /proc entry
+ init_procinfo - setup a procinfo struct and connect it to a process
SYNOPSIS
- struct procinfo * create_procinfo (int pid)
+ struct procinfo * init_procinfo (int pid)
DESCRIPTION
Allocate a procinfo structure, open the /proc file and then set up the
set of signals and faults that are to be traced. Returns a pointer to
- the new procinfo structure.
+ the new procinfo structure.
NOTES
@@ -1948,21 +1981,16 @@ NOTES
*/
static struct procinfo *
-create_procinfo (pid)
+init_procinfo (pid, kill)
int pid;
+ int kill;
{
- struct procinfo *pi;
- struct sig_ctl sctl;
- struct flt_ctl fctl;
-
- pi = find_procinfo (pid, 1);
- if (pi != NULL)
- return pi; /* All done! It already exists */
-
- pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+ struct procinfo *pi = (struct procinfo *)
+ xmalloc (sizeof (struct procinfo));
+ memset ((char *) pi, 0, sizeof (*pi));
if (!open_proc_file (pid, pi, O_RDWR, 1))
- proc_init_failed (pi, "can't open process file");
+ proc_init_failed (pi, "can't open process file", kill);
/* open_proc_file may modify pid. */
@@ -1975,14 +2003,34 @@ create_procinfo (pid)
add_fd (pi); /* Add to list for poll/select */
- pi->num_syscall_handlers = 0;
- pi->syscall_handlers = NULL;
+ /* Remember some things about the inferior that we will, or might, change
+ so that we can restore them when we detach. */
#ifdef UNIXWARE
+ memcpy ((char *) &pi->saved_trace.sigset,
+ (char *) &pi->prstatus.pr_sigtrace, sizeof (sigset_t));
+ memcpy ((char *) &pi->saved_fltset.fltset,
+ (char *) &pi->prstatus.pr_flttrace, sizeof (fltset_t));
+ memcpy ((char *) &pi->saved_entryset.sysset,
+ (char *) &pi->prstatus.pr_sysentry, sizeof (sysset_t));
+ memcpy ((char *) &pi->saved_exitset.sysset,
+ (char *) &pi->prstatus.pr_sysexit, sizeof (sysset_t));
+
+ /* Set up trace and fault sets, as gdb expects them. */
+
prfillset (&sctl.sigset);
- notice_signals (pi, &sctl);
+ notice_signals (pi, &sctl);
prfillset (&fctl.fltset);
prdelset (&fctl.fltset, FLTPAGE);
-#else /* UNIXWARE */
+
+#else /* ! UNIXWARE */
+ ioctl (pi->ctl_fd, PIOCGTRACE, &pi->saved_trace.sigset);
+ ioctl (pi->ctl_fd, PIOCGHOLD, &pi->saved_sighold.sigset);
+ ioctl (pi->ctl_fd, PIOCGFAULT, &pi->saved_fltset.fltset);
+ ioctl (pi->ctl_fd, PIOCGENTRY, &pi->saved_entryset.sysset);
+ ioctl (pi->ctl_fd, PIOCGEXIT, &pi->saved_exitset.sysset);
+
+ /* Set up trace and fault sets, as gdb expects them. */
+
memset ((char *) &pi->prrun, 0, sizeof (pi->prrun));
prfillset (&pi->prrun.pr_trace);
procfs_notice_signals (pid);
@@ -1994,24 +2042,63 @@ create_procinfo (pid)
#endif /* UNIXWARE */
if (!procfs_read_status (pi))
- proc_init_failed (pi, "procfs_read_status failed");
+ proc_init_failed (pi, "procfs_read_status failed", kill);
-/* A bug in Solaris (2.5 at least) causes PIOCWSTOP to hang on LWPs that are
- already stopped, even if they all have PR_ASYNC set. */
+ return pi;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ create_procinfo - initialize access to a /proc entry
+
+SYNOPSIS
+
+ struct procinfo * create_procinfo (int pid)
+
+DESCRIPTION
+
+ Allocate a procinfo structure, open the /proc file and then set up the
+ set of signals and faults that are to be traced. Returns a pointer to
+ the new procinfo structure.
+
+NOTES
+
+ If proc_init_failed ever gets called, control returns to the command
+ processing loop via the standard error handling code.
+
+ */
+
+static struct procinfo *
+create_procinfo (pid)
+ int pid;
+{
+ struct procinfo *pi;
+ struct sig_ctl sctl;
+ struct flt_ctl fctl;
+
+ pi = find_procinfo (pid, 1);
+ if (pi != NULL)
+ return pi; /* All done! It already exists */
+
+ pi = init_procinfo (pid, 1);
#ifndef UNIXWARE
+/* A bug in Solaris (2.5 at least) causes PIOCWSTOP to hang on LWPs that are
+ already stopped, even if they all have PR_ASYNC set. */
if (!(pi->prstatus.pr_flags & PR_STOPPED))
#endif
if (!procfs_write_pcwstop (pi))
- proc_init_failed (pi, "procfs_write_pcwstop failed");
+ proc_init_failed (pi, "procfs_write_pcwstop failed", 1);
#ifdef PROCFS_USE_READ_WRITE
fctl.cmd = PCSFAULT;
if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
- proc_init_failed (pi, "PCSFAULT failed");
+ proc_init_failed (pi, "PCSFAULT failed", 1);
#else
if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)
- proc_init_failed (pi, "PIOCSFAULT failed");
+ proc_init_failed (pi, "PIOCSFAULT failed", 1);
#endif
return pi;
@@ -2047,15 +2134,37 @@ procfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)
int *rtnvalp;
int *statvalp;
{
+ struct procinfo *temp_pi, *next_pi;
+
pi->prrun.pr_flags = PRCFAULT;
if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
perror_with_name (pi->pathname);
- *rtnvalp = wait (statvalp);
- if (*rtnvalp >= 0)
- *rtnvalp = pi->pid;
+ if (attach_flag)
+ {
+ /* Claim it exited (don't call wait). */
+ if (info_verbose)
+ printf_filtered ("(attached process has exited)\n");
+ *statvalp = 0;
+ *rtnvalp = inferior_pid;
+ }
+ else
+ {
+ *rtnvalp = wait (statvalp);
+ if (*rtnvalp >= 0)
+ *rtnvalp = pi->pid;
+ }
+ /* Close ALL open proc file handles,
+ except the one that called SYS_exit. */
+ for (temp_pi = procinfo_list; temp_pi; temp_pi = next_pi)
+ {
+ next_pi = temp_pi->next;
+ if (temp_pi == pi)
+ continue; /* Handled below */
+ close_proc_file (temp_pi);
+ }
return 1;
}
@@ -2223,39 +2332,24 @@ procfs_fork_handler (pi, syscall_num, why, rtnvalp, statvalp)
LOCAL FUNCTION
- procfs_init_inferior - initialize target vector and access to a
- /proc entry
+ procfs_set_inferior_syscall_traps - setup the syscall traps
SYNOPSIS
- int procfs_init_inferior (int pid)
+ void procfs_set_inferior_syscall_traps (struct procinfo *pip)
DESCRIPTION
- When gdb starts an inferior, this function is called in the parent
- process immediately after the fork. It waits for the child to stop
- on the return from the exec system call (the child itself takes care
- of ensuring that this is set up), then sets up the set of signals
- and faults that are to be traced. Returns the pid, which may have had
- the thread-id added to it.
-
-NOTES
-
- If proc_init_failed ever gets called, control returns to the command
- processing loop via the standard error handling code.
+ Called for each "procinfo" (process, thread, or LWP) in the
+ inferior, to register for notification of and handlers for
+ syscall traps in the inferior.
*/
-static int
-procfs_init_inferior (pid)
- int pid;
+static void
+procfs_set_inferior_syscall_traps (pip)
+ struct procinfo *pip;
{
- struct procinfo *pip;
-
- push_target (&procfs_ops);
-
- pip = create_procinfo (pid);
-
#ifndef PIOCSSPCACT
procfs_set_syscall_trap (pip, SYS_exit, PROCFS_SYSCALL_ENTRY,
procfs_exit_handler);
@@ -2297,6 +2391,46 @@ procfs_init_inferior (pid)
procfs_set_syscall_trap (pip, SYS_lwp_create, PROCFS_SYSCALL_EXIT,
procfs_lwp_creation_handler);
#endif
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_init_inferior - initialize target vector and access to a
+ /proc entry
+
+SYNOPSIS
+
+ int procfs_init_inferior (int pid)
+
+DESCRIPTION
+
+ When gdb starts an inferior, this function is called in the parent
+ process immediately after the fork. It waits for the child to stop
+ on the return from the exec system call (the child itself takes care
+ of ensuring that this is set up), then sets up the set of signals
+ and faults that are to be traced. Returns the pid, which may have had
+ the thread-id added to it.
+
+NOTES
+
+ If proc_init_failed ever gets called, control returns to the command
+ processing loop via the standard error handling code.
+
+ */
+
+static int
+procfs_init_inferior (pid)
+ int pid;
+{
+ struct procinfo *pip;
+
+ push_target (&procfs_ops);
+
+ pip = create_procinfo (pid);
+
+ procfs_set_inferior_syscall_traps (pip);
/* create_procinfo may change the pid, so we have to update inferior_pid
here before calling other gdb routines that need the right pid. */
@@ -2863,131 +2997,93 @@ do_attach (pid)
struct procinfo *pi;
struct sig_ctl sctl;
struct flt_ctl fctl;
+ int nlwp, *lwps;
- pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
-
- if (!open_proc_file (pid, pi, O_RDWR, 1))
- {
- free (pi);
- perror_with_name (pi->pathname);
- /* NOTREACHED */
- }
-
- pid = pi -> pid;
-
- /* Add new process to process info list */
-
- pi->next = procinfo_list;
- procinfo_list = pi;
+ pi = init_procinfo (pid, 0);
- add_fd (pi); /* Add to list for poll/select */
+#ifdef PIOCLWPIDS
+ nlwp = pi->prstatus.pr_nlwp;
+ lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
- /* Get current status of process and if it is not already stopped,
- then stop it. Remember whether or not it was stopped when we first
- examined it. */
- if (!procfs_read_status (pi))
+ if (ioctl (pi->ctl_fd, PIOCLWPIDS, lwps))
{
- print_sys_errmsg (pi->pathname, errno);
- close_proc_file (pi);
- error ("procfs_read_status failed");
+ print_sys_errmsg (pi -> pathname, errno);
+ error ("PIOCLWPIDS failed");
}
+#else /* PIOCLWPIDS */
+ nlwp = 1;
+ lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
+ lwps[0] = 0;
+#endif
+ for (; nlwp > 0; nlwp--, lwps++)
+ {
+ /* First one has already been created above. */
+ if ((pi = find_procinfo ((*lwps << 16) | pid, 1)) == 0)
+ pi = init_procinfo ((*lwps << 16) | pid, 0);
+
#ifdef UNIXWARE
- if (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP))
+ if (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP))
#else
- if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+ if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
#endif
- {
- pi->was_stopped = 1;
- }
- else
- {
- pi->was_stopped = 0;
- if (1 || query ("Process is currently running, stop it? "))
{
- long cmd;
- /* Make it run again when we close it. */
-
- modify_run_on_last_close_flag (pi->ctl_fd, 1);
-
+ pi->was_stopped = 1;
+ }
+ else
+ {
+ pi->was_stopped = 0;
+ if (1 || query ("Process is currently running, stop it? "))
+ {
+ long cmd;
+ /* Make it run again when we close it. */
+ modify_run_on_last_close_flag (pi->ctl_fd, 1);
#ifdef PROCFS_USE_READ_WRITE
- cmd = PCSTOP;
- if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+ cmd = PCSTOP;
+ if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
#else
- if (ioctl (pi->ctl_fd, PIOCSTOP, &pi->prstatus) < 0)
+ if (ioctl (pi->ctl_fd, PIOCSTOP, &pi->prstatus) < 0)
#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- close_proc_file (pi);
- error ("PIOCSTOP failed");
- }
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ close_proc_file (pi);
+ error ("PIOCSTOP failed");
+ }
#ifdef UNIXWARE
- if (!procfs_read_status (pi))
- {
- print_sys_errmsg (pi->pathname, errno);
- close_proc_file (pi);
- error ("procfs_read_status failed");
- }
+ if (!procfs_read_status (pi))
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ close_proc_file (pi);
+ error ("procfs_read_status failed");
+ }
#endif
- pi->nopass_next_sigstop = 1;
- }
- else
- {
- printf_unfiltered ("Ok, gdb will wait for %s to stop.\n", target_pid_to_str (pid));
+ pi->nopass_next_sigstop = 1;
+ }
+ else
+ {
+ printf_unfiltered ("Ok, gdb will wait for %s to stop.\n",
+ target_pid_to_str (pi->pid));
+ }
}
- }
- /* Remember some things about the inferior that we will, or might, change
- so that we can restore them when we detach. */
#ifdef PROCFS_USE_READ_WRITE
- memcpy ((char *) &pi->saved_trace.sigset,
- (char *) &pi->prstatus.pr_sigtrace, sizeof (sigset_t));
- memcpy ((char *) &pi->saved_fltset.fltset,
- (char *) &pi->prstatus.pr_flttrace, sizeof (fltset_t));
- memcpy ((char *) &pi->saved_entryset.sysset,
- (char *) &pi->prstatus.pr_sysentry, sizeof (sysset_t));
- memcpy ((char *) &pi->saved_exitset.sysset,
- (char *) &pi->prstatus.pr_sysexit, sizeof (sysset_t));
-
- /* Set up trace and fault sets, as gdb expects them. */
-
- prfillset (&sctl.sigset);
- notice_signals (pi, &sctl);
- prfillset (&fctl.fltset);
- prdelset (&fctl.fltset, FLTPAGE);
-
- fctl.cmd = PCSFAULT;
- if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
- print_sys_errmsg ("PCSFAULT failed", errno);
+ fctl.cmd = PCSFAULT;
+ if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
+ print_sys_errmsg ("PCSFAULT failed", errno);
#else /* PROCFS_USE_READ_WRITE */
- ioctl (pi->ctl_fd, PIOCGTRACE, &pi->saved_trace.sigset);
- ioctl (pi->ctl_fd, PIOCGHOLD, &pi->saved_sighold.sigset);
- ioctl (pi->ctl_fd, PIOCGFAULT, &pi->saved_fltset.fltset);
- ioctl (pi->ctl_fd, PIOCGENTRY, &pi->saved_entryset.sysset);
- ioctl (pi->ctl_fd, PIOCGEXIT, &pi->saved_exitset.sysset);
-
- /* Set up trace and fault sets, as gdb expects them. */
-
- memset (&pi->prrun, 0, sizeof (pi->prrun));
- prfillset (&pi->prrun.pr_trace);
- procfs_notice_signals (pid);
- prfillset (&pi->prrun.pr_fault);
- prdelset (&pi->prrun.pr_fault, FLTPAGE);
-
-#ifdef PROCFS_DONT_TRACE_FAULTS
- premptyset (&pi->prrun.pr_fault);
-#endif
-
- if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault))
- {
- print_sys_errmsg ("PIOCSFAULT failed", errno);
- }
- if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->prrun.pr_trace))
- {
- print_sys_errmsg ("PIOCSTRACE failed", errno);
+ if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault))
+ {
+ print_sys_errmsg ("PIOCSFAULT failed", errno);
+ }
+ if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->prrun.pr_trace))
+ {
+ print_sys_errmsg ("PIOCSTRACE failed", errno);
+ }
+ add_thread (pi->pid);
+ procfs_set_inferior_syscall_traps (pi);
}
#endif /* PROCFS_USE_READ_WRITE */
attach_flag = 1;
- return (pid);
+ return (pi->pid);
}
/*
@@ -3025,106 +3121,107 @@ do_detach (signal)
{
struct procinfo *pi;
- pi = current_procinfo;
-
- if (signal)
+ for (pi = procinfo_list; pi; pi = pi->next)
{
- set_proc_siginfo (pi, signal);
- }
+ if (signal)
+ {
+ set_proc_siginfo (pi, signal);
+ }
#ifdef PROCFS_USE_READ_WRITE
- pi->saved_exitset.cmd = PCSEXIT;
- if (write (pi->ctl_fd, (char *) &pi->saved_exitset,
- sizeof (struct sys_ctl)) < 0)
+ pi->saved_exitset.cmd = PCSEXIT;
+ if (write (pi->ctl_fd, (char *) &pi->saved_exitset,
+ sizeof (struct sys_ctl)) < 0)
#else
- if (ioctl (pi->ctl_fd, PIOCSEXIT, &pi->saved_exitset.sysset) < 0)
+ if (ioctl (pi->ctl_fd, PIOCSEXIT, &pi->saved_exitset.sysset) < 0)
#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSEXIT failed.\n");
- }
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSEXIT failed.\n");
+ }
#ifdef PROCFS_USE_READ_WRITE
- pi->saved_entryset.cmd = PCSENTRY;
- if (write (pi->ctl_fd, (char *) &pi->saved_entryset,
- sizeof (struct sys_ctl)) < 0)
+ pi->saved_entryset.cmd = PCSENTRY;
+ if (write (pi->ctl_fd, (char *) &pi->saved_entryset,
+ sizeof (struct sys_ctl)) < 0)
#else
- if (ioctl (pi->ctl_fd, PIOCSENTRY, &pi->saved_entryset.sysset) < 0)
+ if (ioctl (pi->ctl_fd, PIOCSENTRY, &pi->saved_entryset.sysset) < 0)
#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSENTRY failed.\n");
- }
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSENTRY failed.\n");
+ }
#ifdef PROCFS_USE_READ_WRITE
- pi->saved_trace.cmd = PCSTRACE;
- if (write (pi->ctl_fd, (char *) &pi->saved_trace,
- sizeof (struct sig_ctl)) < 0)
+ pi->saved_trace.cmd = PCSTRACE;
+ if (write (pi->ctl_fd, (char *) &pi->saved_trace,
+ sizeof (struct sig_ctl)) < 0)
#else
- if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->saved_trace.sigset) < 0)
+ if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->saved_trace.sigset) < 0)
#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSTRACE failed.\n");
- }
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSTRACE failed.\n");
+ }
#ifndef UNIXWARE
- if (ioctl (pi->ctl_fd, PIOCSHOLD, &pi->saved_sighold.sigset) < 0)
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOSCHOLD failed.\n");
- }
+ if (ioctl (pi->ctl_fd, PIOCSHOLD, &pi->saved_sighold.sigset) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOSCHOLD failed.\n");
+ }
#endif
#ifdef PROCFS_USE_READ_WRITE
- pi->saved_fltset.cmd = PCSFAULT;
- if (write (pi->ctl_fd, (char *) &pi->saved_fltset,
- sizeof (struct flt_ctl)) < 0)
+ pi->saved_fltset.cmd = PCSFAULT;
+ if (write (pi->ctl_fd, (char *) &pi->saved_fltset,
+ sizeof (struct flt_ctl)) < 0)
#else
- if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->saved_fltset.fltset) < 0)
+ if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->saved_fltset.fltset) < 0)
#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSFAULT failed.\n");
- }
- if (!procfs_read_status (pi))
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("procfs_read_status failed.\n");
- }
- else
- {
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSFAULT failed.\n");
+ }
+ if (!procfs_read_status (pi))
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("procfs_read_status failed.\n");
+ }
+ else
+ {
#ifdef UNIXWARE
- if (signal || (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)))
+ if (signal || (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)))
#else
- if (signal || (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+ if (signal || (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
#endif
- {
- long cmd;
- struct proc_ctl pctl;
-
- if (signal || !pi->was_stopped ||
- query ("Was stopped when attached, make it runnable again? "))
{
- /* Clear any pending signal if we want to detach without
- a signal. */
- if (signal == 0)
- set_proc_siginfo (pi, signal);
+ long cmd;
+ struct proc_ctl pctl;
- /* Clear any fault that might have stopped it. */
+ if (signal || !pi->was_stopped ||
+ query ("Was stopped when attached, make it runnable again? "))
+ {
+ /* Clear any pending signal if we want to detach without
+ a signal. */
+ if (signal == 0)
+ set_proc_siginfo (pi, signal);
+
+ /* Clear any fault that might have stopped it. */
#ifdef PROCFS_USE_READ_WRITE
- cmd = PCCFAULT;
- if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+ cmd = PCCFAULT;
+ if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
#else
- if (ioctl (pi->ctl_fd, PIOCCFAULT, 0))
+ if (ioctl (pi->ctl_fd, PIOCCFAULT, 0))
#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCCFAULT failed.\n");
- }
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCCFAULT failed.\n");
+ }
- /* Make it run again when we close it. */
+ /* Make it run again when we close it. */
- modify_run_on_last_close_flag (pi->ctl_fd, 1);
+ modify_run_on_last_close_flag (pi->ctl_fd, 1);
+ }
}
}
+ close_proc_file (pi);
}
- close_proc_file (pi);
attach_flag = 0;
}
@@ -3152,7 +3249,6 @@ do_detach (signal)
FIXME: Investigate why wait() seems to have problems with programs
being control by /proc routines. */
-
static int
procfs_wait (pid, ourstatus)
int pid;
@@ -3203,16 +3299,17 @@ procfs_wait (pid, ourstatus)
{
checkerr++;
}
- }
+ }
if (checkerr)
{
if (errno == ENOENT)
{
+ /* XXX Fixme -- what to do if attached? Can't call wait... */
rtnval = wait (&statval);
- if (rtnval != inferior_pid)
+ if ((rtnval) != (inferior_pid))
{
print_sys_errmsg (pi->pathname, errno);
- error ("procfs_write_pcwstop, wait failed, returned %d", rtnval);
+ error ("procfs_wait: wait failed, returned %d", rtnval);
/* NOTREACHED */
}
}
@@ -3319,7 +3416,7 @@ procfs_wait (pid, ourstatus)
case FLTBPT:
case FLTTRACE:
statval = (SIGTRAP << 8) | 0177;
- break;
+ break;
case FLTSTACK:
case FLTACCESS:
case FLTBOUNDS:
@@ -3350,10 +3447,11 @@ procfs_wait (pid, ourstatus)
/* Stop all the other threads when any of them stops. */
{
- struct procinfo *procinfo;
+ struct procinfo *procinfo, *next_pi;
- for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
{
+ next_pi = procinfo->next;
if (!procinfo->had_event)
{
#ifdef PROCFS_USE_READ_WRITE
@@ -3369,15 +3467,20 @@ procfs_wait (pid, ourstatus)
order to avoid the hang. */
if (!procfs_read_status (procinfo))
{
- print_sys_errmsg (procinfo->pathname, errno);
- error ("procfs_read_status failed");
+ /* The LWP has apparently terminated. */
+ if (info_verbose)
+ printf_filtered ("LWP %d doesn't respond.\n",
+ (procinfo->pid >> 16) & 0xffff);
+ close_proc_file (procinfo);
+ continue;
}
if (!(procinfo->prstatus.pr_flags & PR_STOPPED))
- if (ioctl (procinfo->ctl_fd, PIOCSTOP, &procinfo->prstatus) < 0)
+ if (ioctl (procinfo->ctl_fd, PIOCSTOP, &procinfo->prstatus)
+ < 0)
{
print_sys_errmsg (procinfo->pathname, errno);
- error ("PIOCSTOP failed");
+ warning ("PIOCSTOP failed");
}
#endif
}
@@ -3394,7 +3497,7 @@ procfs_wait (pid, ourstatus)
if (rtnval == -1) /* No more children to wait for */
{
- fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing.\n");
+ warning ("Child process unexpectedly missing");
/* Claim it exited with unknown signal. */
ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
@@ -3514,7 +3617,7 @@ procfs_resume (pid, step, signo)
enum target_signal signo;
{
int signal_to_pass;
- struct procinfo *pi, *procinfo;
+ struct procinfo *pi, *procinfo, *next_pi;
struct proc_ctl pctl;
pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
@@ -3562,11 +3665,12 @@ procfs_resume (pid, step, signo)
else if (signo == TARGET_SIGNAL_TSTP
#ifdef UNIXWARE
&& pi->prstatus.pr_lwp.pr_cursig == SIGTSTP
- && pi->prstatus.pr_lwp.pr_action.sa_handler == SIG_DFL)
+ && pi->prstatus.pr_lwp.pr_action.sa_handler == SIG_DFL
#else
&& pi->prstatus.pr_cursig == SIGTSTP
- && pi->prstatus.pr_action.sa_handler == SIG_DFL)
+ && pi->prstatus.pr_action.sa_handler == SIG_DFL
#endif
+ )
/* We are about to pass the inferior a SIGTSTP whose action is
SIG_DFL. The SIG_DFL action for a SIGTSTP is to stop
@@ -3607,65 +3711,91 @@ procfs_resume (pid, step, signo)
pi->prrun.pr_flags |= PRSTEP;
#endif
}
-
+ pi->had_event = 0;
/* Don't try to start a process unless it's stopped on an
`event of interest'. Doing so will cause errors. */
+ if (!procfs_read_status (pi))
+ {
+ /* The LWP has apparently terminated. */
+ if (info_verbose)
+ printf_filtered ("LWP %d doesn't respond.\n",
+ (pi->pid >> 16) & 0xffff);
+ close_proc_file (pi);
+ }
+ else
+ {
#ifdef PROCFS_USE_READ_WRITE
- if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+ if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
#else
- if ((pi->prstatus.pr_flags & PR_ISTOP)
- && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+ if ((pi->prstatus.pr_flags & PR_ISTOP)
+ && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
#endif
- {
- perror_with_name (pi->pathname);
- /* NOTREACHED */
+ {
+ /* The LWP has apparently terminated. */
+ if (info_verbose)
+ printf_filtered ("LWP %d doesn't respond.\n",
+ (pi->pid >> 16) & 0xffff);
+ close_proc_file (pi);
+ }
}
- pi->had_event = 0;
-
- /* Continue all the other threads that haven't had an event of
- interest. */
+ /* Continue all the other threads that haven't had an event of interest.
+ Also continue them if they have NOPASS_NEXT_SIGSTOP set; this is only
+ set by do_attach, and means this is the first resume after an attach.
+ All threads were CSTOP'd by do_attach, and should be resumed now. */
if (pid == -1)
- for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
{
- if (pi != procinfo && !procinfo->had_event)
- {
+ next_pi = procinfo->next;
+ if (pi != procinfo)
+ if (!procinfo->had_event ||
+ (procinfo->nopass_next_sigstop && signo == TARGET_SIGNAL_STOP))
+ {
+ procinfo->had_event = procinfo->nopass_next_sigstop = 0;
#ifdef PROCFS_USE_READ_WRITE
- pctl.data = PRCFAULT | PRCSIG;
- if (write (procinfo->ctl_fd, (char *) &pctl,
- sizeof (struct proc_ctl)) < 0)
- {
- if (!procfs_read_status (procinfo))
- {
- fprintf_unfiltered(gdb_stderr, "procfs_read_status failed, errno=%d\n", errno);
- }
- print_sys_errmsg (procinfo->pathname, errno);
- error ("PCRUN failed");
- }
- procfs_read_status (procinfo);
+ pctl.data = PRCFAULT | PRCSIG;
+ if (write (procinfo->ctl_fd, (char *) &pctl,
+ sizeof (struct proc_ctl)) < 0)
+ {
+ if (!procfs_read_status (procinfo))
+ fprintf_unfiltered(gdb_stderr,
+ "procfs_read_status failed, errno=%d\n",
+ errno);
+ print_sys_errmsg (procinfo->pathname, errno);
+ error ("PCRUN failed");
+ }
+ procfs_read_status (procinfo);
#else
- procinfo->prrun.pr_flags &= PRSTEP;
- procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
- procfs_read_status (procinfo);
+ procinfo->prrun.pr_flags &= PRSTEP;
+ procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
+ if (!procfs_read_status (procinfo))
+ {
+ /* The LWP has apparently terminated. */
+ if (info_verbose)
+ printf_filtered ("LWP %d doesn't respond.\n",
+ (procinfo->pid >> 16) & 0xffff);
+ close_proc_file (procinfo);
+ continue;
+ }
- /* Don't try to start a process unless it's stopped on an
- `event of interest'. Doing so will cause errors. */
+ /* Don't try to start a process unless it's stopped on an
+ `event of interest'. Doing so will cause errors. */
- if ((procinfo->prstatus.pr_flags & PR_ISTOP)
- && ioctl (procinfo->ctl_fd, PIOCRUN, &procinfo->prrun) < 0)
- {
- if (!procfs_read_status (procinfo))
- {
- fprintf_unfiltered(gdb_stderr, "procfs_read_status failed, errno=%d\n", errno);
- }
- print_sys_errmsg (procinfo->pathname, errno);
- error ("PIOCRUN failed");
- }
- procfs_read_status (procinfo);
+ if ((procinfo->prstatus.pr_flags & PR_ISTOP)
+ && ioctl (procinfo->ctl_fd, PIOCRUN, &procinfo->prrun) < 0)
+ {
+ if (!procfs_read_status (procinfo))
+ fprintf_unfiltered(gdb_stderr,
+ "procfs_read_status failed, errno=%d\n",
+ errno);
+ print_sys_errmsg (procinfo->pathname, errno);
+ warning ("PIOCRUN failed");
+ }
+ }
+ procfs_read_status (procinfo);
#endif
- }
}
}
@@ -3721,28 +3851,31 @@ procfs_fetch_registers (regno)
LOCAL FUNCTION
- proc_init_failed - called whenever /proc access initialization
+ proc_init_failed - called when /proc access initialization fails
fails
SYNOPSIS
- static void proc_init_failed (struct procinfo *pi, char *why)
+ static void proc_init_failed (struct procinfo *pi,
+ char *why, int kill_p)
DESCRIPTION
This function is called whenever initialization of access to a /proc
entry fails. It prints a suitable error message, does some cleanup,
and then invokes the standard error processing routine which dumps
- us back into the command loop.
+ us back into the command loop. If KILL_P is true, sends SIGKILL.
*/
static void
-proc_init_failed (pi, why)
+proc_init_failed (pi, why, kill_p)
struct procinfo *pi;
char *why;
+ int kill_p;
{
print_sys_errmsg (pi->pathname, errno);
- kill (pi->pid, SIGKILL);
+ if (kill_p)
+ kill (pi->pid, SIGKILL);
close_proc_file (pi);
error (why);
/* NOTREACHED */
@@ -3773,6 +3906,7 @@ close_proc_file (pip)
{
struct procinfo *procinfo;
+ delete_thread (pip->pid); /* remove thread from GDB's thread list */
remove_fd (pip); /* Remove fd from poll/select list */
close (pip->ctl_fd);
@@ -3890,7 +4024,7 @@ open_proc_file (pid, pip, mode, control)
close (pip->as_fd);
close (pip->map_fd);
return 0;
- }
+ }
}
#else /* HAVE_MULTIPLE_PROC_FDS */
@@ -4531,7 +4665,7 @@ info_proc (args, from_tty)
char *args;
int from_tty;
{
- int pid = inferior_pid;
+ int pid;
struct procinfo *pip;
struct cleanup *old_chain;
char **argv;
@@ -4554,7 +4688,10 @@ info_proc (args, from_tty)
/* Default to using the current inferior if no pid specified. Note
that inferior_pid may be 0, hence we set okerr. */
- pip = find_procinfo (inferior_pid, 1);
+ pid = inferior_pid & 0x7fffffff; /* strip off sol-thread bit */
+ if (!(pip = find_procinfo (pid, 1))) /* inferior_pid no good? */
+ pip = procinfo_list; /* take first available */
+ pid = pid & 0xffff; /* extract "real" pid */
if (args != NULL)
{
@@ -4652,12 +4789,12 @@ No process. Start debugging a program or specify an explicit process ID.");
#ifndef PROCFS_USE_READ_WRITE
#ifdef PIOCLWPIDS
nlwp = pip->prstatus.pr_nlwp;
- lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
+ lwps = alloca ((2 * nlwp + 2) * sizeof (*lwps));
if (ioctl (pip->ctl_fd, PIOCLWPIDS, lwps))
{
print_sys_errmsg (pip -> pathname, errno);
- error ("PIOCLWPIDS failed");
+ error ("PIOCLWPIDS failed");
}
#else /* PIOCLWPIDS */
nlwp = 1;
@@ -4698,6 +4835,10 @@ No process. Start debugging a program or specify an explicit process ID.");
if (summary || all)
{
info_proc_stop (pip, summary);
+ supply_gregset (&pip->prstatus.pr_reg);
+ printf_filtered ("PC: ");
+ print_address (read_pc (), gdb_stdout);
+ printf_filtered ("\n");
}
if (summary || all || signals || faults)
{
@@ -5005,7 +5146,7 @@ procfs_set_syscall_trap (pi, syscall_num, flags, func)
syscall_func_t *func;
{
sysset_t sysset;
-
+
if (flags & PROCFS_SYSCALL_ENTRY)
{
if (ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0)
@@ -5148,7 +5289,7 @@ procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
/* We're the proud parent of a new thread. Setup an exit trap for lwp_create
in the child and continue the parent. */
-
+
/* Third arg is pointer to new thread id. */
lwp_id = read_memory_integer (pi->prstatus.pr_sysarg[2], sizeof (int));
@@ -5157,18 +5298,36 @@ procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
childpi = create_procinfo (lwp_id);
/* The new process has actually inherited the lwp_create syscall trap from
- it's parent, but we still have to call this to register a handler for
+ it's parent, but we still have to call this to register handlers for
that child. */
- procfs_set_syscall_trap (childpi, SYS_lwp_create, PROCFS_SYSCALL_EXIT,
- procfs_lwp_creation_handler);
+ procfs_set_inferior_syscall_traps (childpi);
+ add_thread (lwp_id);
+ printf_filtered ("[New %s]\n", target_pid_to_str (lwp_id));
- childpi->new_child = 1; /* Flag this as an unseen child process */
+ /* Continue the parent */
- *rtnvalp = lwp_id; /* the new arrival. */
- *statvalp = (SIGTRAP << 8) | 0177;
+ pi->prrun.pr_flags &= PRSTEP;
+ pi->prrun.pr_flags |= PRCFAULT;
+ if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+ perror_with_name (pi->pathname);
- return 1;
+ /* The new child may have been created in one of two states:
+ SUSPENDED or RUNNABLE. If runnable, we will simply signal it to run.
+ If suspended, we flag it to be continued later, when it has an event. */
+
+ if (childpi->prstatus.pr_why == PR_SUSPENDED)
+ childpi->new_child = 1; /* Flag this as an unseen child process */
+ else
+ {
+ /* Continue the child */
+ childpi->prrun.pr_flags &= PRSTEP;
+ childpi->prrun.pr_flags |= PRCFAULT;
+
+ if (ioctl (childpi->ctl_fd, PIOCRUN, &childpi->prrun) != 0)
+ perror_with_name (childpi->pathname);
+ }
+ return 0;
}
#endif /* SYS_lwp_create */
@@ -5356,7 +5515,34 @@ static int
procfs_thread_alive (pid)
int pid;
{
- return 1;
+ struct procinfo *pi, *next_pi;
+
+ for (pi = procinfo_list; pi; pi = next_pi)
+ {
+ next_pi = pi->next;
+ if (pi -> pid == pid)
+ if (procfs_read_status (pi)) /* alive */
+ return 1;
+ else /* defunct (exited) */
+ {
+ close_proc_file (pi);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+int
+procfs_first_available ()
+{
+ struct procinfo *pi;
+
+ for (pi = procinfo_list; pi; pi = pi->next)
+ {
+ if (procfs_read_status (pi))
+ return pi->pid;
+ }
+ return -1;
}
/* Send a SIGINT to the process group. This acts just like the user typed a
@@ -5449,7 +5635,7 @@ _initialize_procfs ()
add_target (&procfs_ops);
- add_info ("proc", info_proc,
+ add_info ("processes", info_proc,
"Show process status information using /proc entry.\n\
Specify process id or use current inferior by default.\n\
Specify keywords for detailed information; default is summary.\n\
diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c
index 00bdc60..4b73c19 100644
--- a/gdb/sol-thread.c
+++ b/gdb/sol-thread.c
@@ -72,6 +72,7 @@ extern struct target_ops sol_thread_ops; /* Forward declaration */
extern int procfs_suppress_run;
extern struct target_ops procfs_ops; /* target vector for procfs.c */
+extern char *procfs_pid_to_str PARAMS ((int pid));
/* Note that these prototypes differ slightly from those used in procfs.c
for of two reasons. One, we can't use gregset_t, as that's got a whole
@@ -110,10 +111,11 @@ static struct cleanup * save_inferior_pid PARAMS ((void));
static void restore_inferior_pid PARAMS ((int pid));
static char *td_err_string PARAMS ((td_err_e errcode));
static char *td_state_string PARAMS ((td_thr_state_e statecode));
-static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
+static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
static void sol_thread_resume PARAMS ((int pid, int step,
enum target_signal signo));
static int lwp_to_thread PARAMS ((int lwp));
+static int sol_thread_alive PARAMS ((int pid));
#define THREAD_FLAG 0x80000000
#define is_thread(ARG) (((ARG) & THREAD_FLAG) != 0)
@@ -306,24 +308,22 @@ thread_to_lwp (thread_id, default_lwp)
td_thrinfo_t ti;
td_thrhandle_t th;
td_err_e val;
- int pid;
- int lwp;
if (is_lwp (thread_id))
return thread_id; /* It's already an LWP id */
/* It's a thread. Convert to lwp */
- pid = PIDGET (thread_id);
- thread_id = GET_THREAD(thread_id);
-
- val = p_td_ta_map_id2thr (main_ta, thread_id, &th);
- if (val != TD_OK)
+ val = p_td_ta_map_id2thr (main_ta, GET_THREAD (thread_id), &th);
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
error ("thread_to_lwp: td_ta_map_id2thr %s", td_err_string (val));
val = p_td_thr_get_info (&th, &ti);
-
- if (val != TD_OK)
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val));
if (ti.ti_state != TD_THR_ACTIVE)
@@ -333,10 +333,8 @@ thread_to_lwp (thread_id, default_lwp)
error ("thread_to_lwp: thread state not active: %s",
td_state_string (ti.ti_state));
}
-
- lwp = BUILD_LWP (ti.ti_lid, pid);
- return lwp;
+ return BUILD_LWP (ti.ti_lid, PIDGET (thread_id));
}
/*
@@ -367,29 +365,34 @@ lwp_to_thread (lwp)
td_thrinfo_t ti;
td_thrhandle_t th;
td_err_e val;
- int pid;
- int thread_id;
if (is_thread (lwp))
return lwp; /* It's already a thread id */
/* It's an lwp. Convert it to a thread id. */
- pid = PIDGET (lwp);
- lwp = GET_LWP (lwp);
+ if (!sol_thread_alive (lwp))
+ return -1; /* defunct lwp */
- val = p_td_ta_map_lwp2thr (main_ta, lwp, &th);
- if (val != TD_OK)
+ val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th);
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
- val = p_td_thr_get_info (&th, &ti);
+ val = p_td_thr_validate (&th);
+ if (val == TD_NOTHR)
+ return lwp; /* libthread doesn't know about it, just return lwp */
+ else if (val != TD_OK)
+ error ("lwp_to_thread: td_thr_validate: %s.", td_err_string (val));
- if (val != TD_OK)
+ val = p_td_thr_get_info (&th, &ti);
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
- thread_id = BUILD_THREAD (ti.ti_tid, pid);
-
- return thread_id;
+ return BUILD_THREAD (ti.ti_tid, PIDGET (lwp));
}
/*
@@ -456,7 +459,19 @@ sol_thread_attach (args, from_tty)
int from_tty;
{
procfs_ops.to_attach (args, from_tty);
-
+ /* Must get symbols from solibs before libthread_db can run! */
+ SOLIB_ADD ((char *)0, from_tty, (struct target_ops *)0);
+ if (sol_thread_active)
+ {
+ printf_filtered ("sol-thread active.\n");
+ main_ph.pid = inferior_pid; /* Save for xfer_memory */
+ push_target (&sol_thread_ops);
+ inferior_pid = lwp_to_thread (inferior_pid);
+ if (inferior_pid == -1)
+ inferior_pid = main_ph.pid;
+ else
+ add_thread (inferior_pid);
+ }
/* XXX - might want to iterate over all the threads and register them. */
}
@@ -473,6 +488,7 @@ sol_thread_detach (args, from_tty)
char *args;
int from_tty;
{
+ unpush_target (&sol_thread_ops);
procfs_ops.to_detach (args, from_tty);
}
@@ -492,12 +508,19 @@ sol_thread_resume (pid, step, signo)
old_chain = save_inferior_pid ();
inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
+ if (inferior_pid == -1)
+ inferior_pid = procfs_first_available ();
if (pid != -1)
{
+ int save_pid = pid;
+
pid = thread_to_lwp (pid, -2);
if (pid == -2) /* Inactive thread */
error ("This version of Solaris can't start inactive threads.");
+ if (info_verbose && pid == -1)
+ warning ("Specified thread %d seems to have terminated",
+ GET_THREAD (save_pid));
}
procfs_ops.to_resume (pid, step, signo);
@@ -521,28 +544,44 @@ sol_thread_wait (pid, ourstatus)
old_chain = save_inferior_pid ();
inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
+ if (inferior_pid == -1)
+ inferior_pid = procfs_first_available ();
if (pid != -1)
- pid = thread_to_lwp (pid, -1);
+ {
+ int save_pid = pid;
+
+ pid = thread_to_lwp (pid, -2);
+ if (pid == -2) /* Inactive thread */
+ error ("This version of Solaris can't start inactive threads.");
+ if (info_verbose && pid == -1)
+ warning ("Specified thread %d seems to have terminated",
+ GET_THREAD (save_pid));
+ }
rtnval = procfs_ops.to_wait (pid, ourstatus);
- if (rtnval != save_pid
- && !in_thread_list (rtnval))
+ if (ourstatus->kind != TARGET_WAITKIND_EXITED)
{
- fprintf_unfiltered (gdb_stderr, "[New %s]\n",
- target_pid_to_str (rtnval));
- add_thread (rtnval);
+ /* Map the LWP of interest back to the appropriate thread ID */
+ rtnval = lwp_to_thread (rtnval);
+ if (rtnval == -1)
+ rtnval = save_pid;
+
+ /* See if we have a new thread */
+ if (is_thread (rtnval)
+ && rtnval != save_pid
+ && !in_thread_list (rtnval))
+ {
+ printf_filtered ("[New %s]\n", target_pid_to_str (rtnval));
+ add_thread (rtnval);
+ }
}
/* During process initialization, we may get here without the thread package
being initialized, since that can only happen after we've found the shared
libs. */
- /* Map the LWP of interest back to the appropriate thread ID */
-
- rtnval = lwp_to_thread (rtnval);
-
do_cleanups (old_chain);
return rtnval;
@@ -751,8 +790,6 @@ sol_thread_notice_signals (pid)
procfs_ops.to_notice_signals (pid);
}
-void target_new_objfile PARAMS ((struct objfile *objfile));
-
/* Fork an inferior process, and start debugging it with /proc. */
static void
@@ -763,13 +800,15 @@ sol_thread_create_inferior (exec_file, allargs, env)
{
procfs_ops.to_create_inferior (exec_file, allargs, env);
- if (sol_thread_active)
+ if (sol_thread_active && inferior_pid != 0)
{
main_ph.pid = inferior_pid; /* Save for xfer_memory */
push_target (&sol_thread_ops);
inferior_pid = lwp_to_thread (inferior_pid);
+ if (inferior_pid == -1)
+ inferior_pid = main_ph.pid;
add_thread (inferior_pid);
}
@@ -794,6 +833,10 @@ sol_thread_new_objfile (objfile)
return;
}
+ /* don't do anything if init failed to resolve the libthread_db library */
+ if (!procfs_suppress_run)
+ return;
+
/* Now, initialize the thread debugging library. This needs to be done after
the shared libraries are located because it needs information from the
user's thread library. */
@@ -816,6 +859,7 @@ sol_thread_new_objfile (objfile)
static void
sol_thread_mourn_inferior ()
{
+ unpush_target (&sol_thread_ops);
procfs_ops.to_mourn_inferior ();
}
@@ -827,11 +871,40 @@ sol_thread_can_run ()
return procfs_suppress_run;
}
+/*
+
+LOCAL FUNCTION
+
+ sol_thread_alive - test thread for "aliveness"
+
+SYNOPSIS
+
+ static bool sol_thread_alive (int pid);
+
+DESCRIPTION
+
+ returns true if thread still active in inferior.
+
+ */
+
static int
sol_thread_alive (pid)
int pid;
{
- return 1;
+ if (is_thread (pid)) /* non-kernel thread */
+ {
+ td_err_e val;
+ td_thrhandle_t th;
+
+ pid = GET_THREAD (pid);
+ if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK)
+ return 0; /* thread not found */
+ if ((val = p_td_thr_validate (&th)) != TD_OK)
+ return 0; /* thread not valid */
+ return 1; /* known thread: return true */
+ }
+ else /* kernel thread (LWP): let procfs test it */
+ return procfs_ops.to_thread_alive (pid);
}
static void
@@ -910,9 +983,9 @@ rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
if (cc < 0)
{
if (dowrite == 0)
- print_sys_errmsg ("ps_pdread (): read", errno);
+ print_sys_errmsg ("rw_common (): read", errno);
else
- print_sys_errmsg ("ps_pdread (): write", errno);
+ print_sys_errmsg ("rw_common (): write", errno);
do_cleanups (old_chain);
@@ -1123,19 +1196,27 @@ solaris_pid_to_str (pid)
{
static char buf[100];
+ /* in case init failed to resolve the libthread_db library */
+ if (!procfs_suppress_run)
+ return procfs_pid_to_str (pid);
+
if (is_thread (pid))
{
int lwp;
lwp = thread_to_lwp (pid, -2);
- if (lwp != -2)
+ if (lwp == -1)
+ sprintf (buf, "Thread %d (defunct)", GET_THREAD (pid));
+ else if (lwp != -2)
sprintf (buf, "Thread %d (LWP %d)", GET_THREAD (pid), GET_LWP (lwp));
else
sprintf (buf, "Thread %d ", GET_THREAD (pid));
}
- else
+ else if (GET_LWP (pid) != 0)
sprintf (buf, "LWP %d ", GET_LWP (pid));
+ else
+ sprintf (buf, "process %d ", PIDGET (pid));
return buf;
}
diff --git a/gdb/thread.c b/gdb/thread.c
index 7ffc65a..b8bf9e1 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -125,6 +125,31 @@ add_thread (pid)
thread_list = tp;
}
+void
+delete_thread (pid)
+ int pid;
+{
+ struct thread_info *tp, *tpprev;
+
+ tpprev = NULL;
+
+ for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
+ if (tp->pid == pid)
+ break;
+
+ if (!tp)
+ return;
+
+ if (tpprev)
+ tpprev->next = tp->next;
+ else
+ thread_list = tp->next;
+
+ free (tp);
+
+ return;
+}
+
static struct thread_info *
find_thread_id (num)
int num;
@@ -332,7 +357,10 @@ info_threads_command (arg, from_tty)
printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
switch_to_thread (tp->pid);
- print_stack_frame (selected_frame, -1, 0);
+ if (selected_frame)
+ print_stack_frame (selected_frame, -1, 0);
+ else
+ printf_filtered ("[No stack.]\n");
}
switch_to_thread (current_pid);