aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog39
-rw-r--r--gdb/coff-solib.c12
-rw-r--r--gdb/fork-child.c6
-rw-r--r--gdb/hppa-tdep.c2
-rw-r--r--gdb/hppab-nat.c3
-rw-r--r--gdb/hppah-nat.c3
-rw-r--r--gdb/i386lynx-nat.c4
-rw-r--r--gdb/infrun.c58
-rw-r--r--gdb/inftarg.c288
-rw-r--r--gdb/osfsolib.c2
-rw-r--r--gdb/procfs.c900
-rw-r--r--gdb/remote-bug.c3
-rw-r--r--gdb/remote-hms.c3
-rw-r--r--gdb/remote-mips.c2
-rw-r--r--gdb/remote-mon.c3
-rw-r--r--gdb/remote-nindy.c3
-rw-r--r--gdb/remote-sim.c3
-rw-r--r--gdb/remote-udi.c3
-rw-r--r--gdb/remote-vx.c6
-rw-r--r--gdb/remote-z8k.c3
-rw-r--r--gdb/thread.c28
-rw-r--r--gdb/thread.h8
22 files changed, 863 insertions, 519 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fcb792c..61ed445 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,42 @@
+Fri Oct 15 22:46:07 1993 Stu Grossman (grossman at cygnus.com)
+
+ * breakpoint.c (breakpoint_thread_match break_command_1):
+ Thread-specific breakpoint support.
+ * breakpoint.h (struct breakpoint): Add thread id field.
+ * fork-child.c (fork_inferior): Move call to init_thread_list()
+ back a bit so that init_trace_fun can do thread functions.
+ * hppa-tdep.c (restore_pc_queue): Add pid to call to target_wait.
+ * hppab-nat.c (child_resume): Handle default pid.
+ * hppah-nat.c (child_resume): Handle default pid.
+ * i386lynx-nat.c (child_wait): New arg pid.
+ * inflow.c (kill_command): Reset thread list.
+ * infptrace.c (child_resume): Handle default pid.
+ * infrun.c: Thread-specific breakpoint support.
+ * inftarg.c (child_wait): Add pid arg.
+ * osfsolib.c (solib_create_inferior_hook): Add pid to call to
+ target_resume.
+ * procfs.c: Multi-thread support.
+ * remote-bug.c (bug_wait): Add pid arg.
+ * remote-hms.c (hms_wait): Add pid arg.
+ * remote-mips.c (mips_wait): Add pid arg.
+ * remote-mon.c (monitor_wait): Add pid arg.
+ * remote-nindy.c (nindy_wait): Add pid arg.
+ * remote-sim.c (gdbsim_wait): Add pid arg.
+ * remote-udi.c (udi_wait): Add pid arg.
+ * remote-vx.c (vx_wait): Add pid arg.
+ * remote-z8k.c (sim_wait): Add pid arg.
+ * remote.c (remote_wait): Add pid arg.
+ * solib.c (solib_create_inferior_hook): Add pid to call to
+ target_resume.
+ * target.h (struct target_ops): Add pid arg to to_wait and
+ to_notice_signals.
+ * thread.c (valid_thread_id): New func to validate thread #s.
+ * (pid_to_thread_id): New func to do the obvious.
+ * thread.h: Prototypes for above.
+
+ * coff-solib.c (coff_solib_add): Use nameoffset field to locate
+ filename.
+
Fri Oct 15 21:29:40 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
* h8300-tdep.c, h8500-tdep.c: Define sim_load only, but not
diff --git a/gdb/coff-solib.c b/gdb/coff-solib.c
index a4bf6c4..01ffc9c 100644
--- a/gdb/coff-solib.c
+++ b/gdb/coff-solib.c
@@ -62,8 +62,7 @@ coff_solib_add (arg_string, from_tty, target)
struct libent
{
bfd_byte len[4];
- bfd_byte unk[4];
- char filename[1];
+ bfd_byte nameoffset[4];
};
libsize = bfd_section_size (exec_bfd, libsect);
@@ -76,16 +75,21 @@ coff_solib_add (arg_string, from_tty, target)
{
struct libent *ent;
struct objfile *objfile;
- int len;
+ int len, nameoffset;
+ char *filename;
ent = (struct libent *)lib;
len = bfd_get_32 (exec_bfd, ent->len);
+ nameoffset = bfd_get_32 (exec_bfd, ent->nameoffset);
+
if (len <= 0)
break;
- objfile = symbol_file_add (ent->filename, from_tty,
+ filename = (char *)ent + nameoffset * 4;
+
+ objfile = symbol_file_add (filename, from_tty,
0, /* addr */
0, /* not mainline */
0, /* not mapped */
diff --git a/gdb/fork-child.c b/gdb/fork-child.c
index e982864..9aa3cfe 100644
--- a/gdb/fork-child.c
+++ b/gdb/fork-child.c
@@ -238,11 +238,15 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun)
/* Restore our environment in case a vforked child clob'd it. */
environ = save_our_env;
+ init_thread_list();
+
/* Now that we have a child process, make it our target, and
initialize anything target-vector-specific that needs initializing. */
(*init_trace_fun)(pid);
- init_thread_list();
+#ifdef CREATE_INFERIOR_HOOK
+ CREATE_INFERIOR_HOOK (pid);
+#endif
/* The process was started by the fork that created it,
but it will have stopped one instruction after execing the shell.
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
index 7ebe97d..058c874 100644
--- a/gdb/hppa-tdep.c
+++ b/gdb/hppa-tdep.c
@@ -869,7 +869,7 @@ restore_pc_queue (fsr)
for (insn_count = 0; insn_count < 3; insn_count++)
{
resume (1, 0);
- target_wait(&w);
+ target_wait(inferior_pid, &w);
if (!WIFSTOPPED (w))
{
diff --git a/gdb/hppab-nat.c b/gdb/hppab-nat.c
index b45af84..5f3cdf7 100644
--- a/gdb/hppab-nat.c
+++ b/gdb/hppab-nat.c
@@ -261,6 +261,9 @@ child_resume (pid, step, signal)
{
errno = 0;
+ if (pid == -1)
+ pid = inferior_pid;
+
/* An address of (PTRACE_ARG3_TYPE) 1 tells ptrace to continue from where
it was. (If GDB wanted it to start some other way, we have already
written a new PC value to the child.) */
diff --git a/gdb/hppah-nat.c b/gdb/hppah-nat.c
index 7c04593..60942df 100644
--- a/gdb/hppah-nat.c
+++ b/gdb/hppah-nat.c
@@ -212,6 +212,9 @@ child_resume (pid, step, signal)
{
errno = 0;
+ if (pid == -1)
+ pid = inferior_pid;
+
/* An address of (PTRACE_ARG3_TYPE) 1 tells ptrace to continue from where
it was. (If GDB wanted it to start some other way, we have already
written a new PC value to the child.) */
diff --git a/gdb/i386lynx-nat.c b/gdb/i386lynx-nat.c
index 5d3fb21..4153a47 100644
--- a/gdb/i386lynx-nat.c
+++ b/gdb/i386lynx-nat.c
@@ -187,10 +187,10 @@ store_inferior_registers (regno)
of error; store status through argument pointer STATUS. */
int
-child_wait (status)
+child_wait (pid, status)
+ int pid;
int *status;
{
- int pid;
int save_errno;
int thread;
diff --git a/gdb/infrun.c b/gdb/infrun.c
index e32d705..c4e58ce 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -306,7 +306,7 @@ resume (step, sig)
/* Install inferior's terminal modes. */
target_terminal_inferior ();
- target_resume (inferior_pid, step, sig);
+ target_resume (-1, step, sig);
discard_cleanups (old_cleanups);
}
@@ -503,7 +503,7 @@ wait_for_inferior ()
flush_cached_frames ();
registers_changed ();
- pid = target_wait (&w);
+ pid = target_wait (-1, &w);
#ifdef SIGTRAP_STOP_AFTER_LOAD
@@ -559,7 +559,41 @@ wait_for_inferior ()
#endif
break;
}
-
+
+ stop_signal = WSTOPSIG (w);
+
+ if (pid != inferior_pid)
+ {
+ int save_pid = inferior_pid;
+
+ inferior_pid = pid; /* Setup for target memory/regs */
+ registers_changed ();
+ stop_pc = read_pc ();
+ inferior_pid = save_pid;
+ registers_changed ();
+ }
+ else
+ stop_pc = read_pc ();
+
+ if (stop_signal == SIGTRAP
+ && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
+ if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
+ {
+ /* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */
+ if (breakpoints_inserted)
+ {
+ remove_breakpoints ();
+ target_resume (pid, 1, 0); /* Single step */
+ target_wait (pid, NULL);
+ insert_breakpoints ();
+ }
+ target_resume (-1, 0, 0);
+ continue;
+ }
+ else
+ if (pid != inferior_pid)
+ goto switch_thread;
+
if (pid != inferior_pid)
{
int printed = 0;
@@ -569,13 +603,11 @@ wait_for_inferior ()
fprintf (stderr, "[New %s]\n", target_pid_to_str (pid));
add_thread (pid);
- target_resume (pid, 0, 0);
+ target_resume (-1, 0, 0);
continue;
}
else
{
- stop_signal = WSTOPSIG (w);
-
if (stop_signal >= NSIG || signal_print[stop_signal])
{
char *signame;
@@ -593,8 +625,11 @@ wait_for_inferior ()
fflush (stdout);
}
- if (stop_signal >= NSIG || signal_stop[stop_signal])
+ if (stop_signal == SIGTRAP
+ || stop_signal >= NSIG
+ || signal_stop[stop_signal])
{
+switch_thread:
inferior_pid = pid;
printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
@@ -624,12 +659,14 @@ wait_for_inferior ()
if (signal_program[stop_signal] == 0)
stop_signal = 0;
- target_resume (pid, 0, stop_signal);
+ target_resume (-1, 0, stop_signal);
continue;
}
}
}
+same_pid:
+
#ifdef NO_SINGLE_STEP
if (one_stepped)
single_step (0); /* This actually cleans up the ss */
@@ -644,7 +681,6 @@ wait_for_inferior ()
continue;
}
- stop_pc = read_pc ();
set_current_frame ( create_new_frame (read_fp (), stop_pc));
stop_frame_address = FRAME_FP (get_current_frame ());
@@ -674,8 +710,6 @@ wait_for_inferior ()
3) set random_signal to 1, and the decision between 1 and 2
will be made according to the signal handling tables. */
- stop_signal = WSTOPSIG (w);
-
/* First, distinguish signals caused by the debugger from signals
that have to do with the program's own actions.
Note that breakpoint insns may cause SIGTRAP or SIGILL
@@ -1598,7 +1632,7 @@ handle_command (args, from_tty)
argv++;
}
- target_notice_signals();
+ target_notice_signals(inferior_pid);
if (from_tty)
{
diff --git a/gdb/inftarg.c b/gdb/inftarg.c
index e357c0e..3270fa6 100644
--- a/gdb/inftarg.c
+++ b/gdb/inftarg.c
@@ -24,23 +24,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "target.h"
#include "wait.h"
#include "gdbcore.h"
-#include "ieee-float.h" /* Required by REGISTER_CONVERT_TO_XXX */
-#include "terminal.h" /* For #ifdef TIOCGPGRP and new_tty */
#include <signal.h>
-#ifdef SET_STACK_LIMIT_HUGE
-#include <sys/time.h>
-#include <sys/resource.h>
-
-extern int original_stack_limit;
-#endif /* SET_STACK_LIMIT_HUGE */
-
static void
child_prepare_to_store PARAMS ((void));
+#ifndef CHILD_WAIT
static int
child_wait PARAMS ((int *));
+#endif /* CHILD_WAIT */
static void
child_open PARAMS ((char *, int));
@@ -55,6 +48,12 @@ static void
child_attach PARAMS ((char *, int));
static void
+ptrace_me PARAMS ((void));
+
+static void
+ptrace_him PARAMS ((int));
+
+static void
child_create_inferior PARAMS ((char *, char *, char **));
static void
@@ -68,31 +67,41 @@ extern char **environ;
/* Forward declaration */
extern struct target_ops child_ops;
+#ifndef CHILD_WAIT
+
/* Wait for child to do something. Return pid of child, or -1 in case
of error; store status through argument pointer STATUS. */
static int
-child_wait (status)
+child_wait (pid, status)
+ int pid;
int *status;
{
- int pid;
+ int save_errno;
do {
-#ifdef USE_PROC_FS
- pid = proc_wait (status);
-#else
+ if (attach_flag)
+ set_sigint_trap(); /* Causes SIGINT to be passed on to the
+ attached process. */
pid = wait (status);
-#endif
- if (pid == -1) /* No more children to wait for */
+ save_errno = errno;
+
+ if (attach_flag)
+ clear_sigint_trap();
+
+ if (pid == -1)
{
- fprintf (stderr, "Child process unexpectedly missing.\n");
+ if (save_errno == EINTR)
+ continue;
+ fprintf (stderr, "Child process unexpectedly missing: %s.\n",
+ safe_strerror (save_errno));
*status = 42; /* Claim it exited with signal 42 */
return -1;
}
} while (pid != inferior_pid); /* Some other child died or stopped */
return pid;
}
-
+#endif /* CHILD_WAIT */
/* Attach to process PID, then initialize for debugging it. */
@@ -120,9 +129,9 @@ child_attach (args, from_tty)
exec_file = (char *) get_exec_file (0);
if (exec_file)
- printf ("Attaching program `%s', pid %d\n", exec_file, pid);
+ printf ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
else
- printf ("Attaching pid %d\n", pid);
+ printf ("Attaching to %s\n", target_pid_to_str (pid));
fflush (stdout);
}
@@ -155,8 +164,8 @@ child_detach (args, from_tty)
char *exec_file = get_exec_file (0);
if (exec_file == 0)
exec_file = "";
- printf ("Detaching program: %s pid %d\n",
- exec_file, inferior_pid);
+ printf ("Detaching from program: %s %s\n", exec_file,
+ target_pid_to_str (inferior_pid));
fflush (stdout);
}
if (args)
@@ -190,8 +199,8 @@ static void
child_files_info (ignore)
struct target_ops *ignore;
{
- printf ("\tUsing the running image of %s process %d.\n",
- attach_flag? "attached": "child", inferior_pid);
+ printf ("\tUsing the running image of %s %s.\n",
+ attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
}
/* ARGSUSED */
@@ -203,224 +212,40 @@ child_open (arg, from_tty)
error ("Use the \"run\" command to start a Unix child process.");
}
+/* Stub function which causes the inferior that runs it, to be ptrace-able
+ by its parent process. */
+
+static void
+ptrace_me ()
+{
+ /* "Trace me, Dr. Memory!" */
+ call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0);
+}
+
+/* Stub function which causes the GDB that runs it, to start ptrace-ing
+ the child process. */
+
+static void
+ptrace_him (pid)
+ int pid;
+{
+ push_target (&child_ops);
+}
+
/* Start an inferior Unix child process and sets inferior_pid to its pid.
EXEC_FILE is the file to run.
ALLARGS is a string containing the arguments to the program.
ENV is the environment vector to pass. Errors reported with error(). */
-#ifndef SHELL_FILE
-#define SHELL_FILE "/bin/sh"
-#endif
-
static void
child_create_inferior (exec_file, allargs, env)
char *exec_file;
char *allargs;
char **env;
{
- int pid;
- char *shell_command;
- char *shell_file;
- static char default_shell_file[] = SHELL_FILE;
- int len;
- int pending_execs;
- /* Set debug_fork then attach to the child while it sleeps, to debug. */
- static int debug_fork = 0;
- /* This is set to the result of setpgrp, which if vforked, will be visible
- to you in the parent process. It's only used by humans for debugging. */
- static int debug_setpgrp = 657473;
- char **save_our_env;
-
- /* If no exec file handed to us, get it from the exec-file command -- with
- a good, common error message if none is specified. */
- if (exec_file == 0)
- exec_file = get_exec_file(1);
-
- /* The user might want tilde-expansion, and in general probably wants
- the program to behave the same way as if run from
- his/her favorite shell. So we let the shell run it for us.
- FIXME, this should probably search the local environment (as
- modified by the setenv command), not the env gdb inherited. */
- shell_file = getenv ("SHELL");
- if (shell_file == NULL)
- shell_file = default_shell_file;
-
- len = 5 + strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop*/ 10;
- /* 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) + len);
- strcpy (shell_command, SHELL_COMMAND_CONCAT);
-#else
- shell_command = (char *) alloca (len);
- shell_command[0] = '\0';
-#endif
- strcat (shell_command, "exec ");
- strcat (shell_command, exec_file);
- strcat (shell_command, " ");
- strcat (shell_command, allargs);
-
- /* exec is said to fail if the executable is open. */
- close_exec_file ();
-
- /* Retain a copy of our environment variables, since the child will
- replace the value of environ and if we're vforked, we have to
- restore it. */
- save_our_env = environ;
-
- /* Tell the terminal handling subsystem what tty we plan to run on;
- it will just record the information for later. */
-
- new_tty_prefork (inferior_io_terminal);
-
- /* It is generally good practice to flush any possible pending stdio
- output prior to doing a fork, to avoid the possibility of both the
- parent and child flushing the same data after the fork. */
-
- fflush (stdout);
- fflush (stderr);
-
-#if defined(USG) && !defined(HAVE_VFORK)
- pid = fork ();
-#else
- if (debug_fork)
- pid = fork ();
- else
- pid = vfork ();
-#endif
-
- if (pid < 0)
- perror_with_name ("vfork");
-
- if (pid == 0)
- {
- if (debug_fork)
- sleep (debug_fork);
-
-#ifdef TIOCGPGRP
- /* Run inferior in a separate process group. */
-#ifdef NEED_POSIX_SETPGID
- debug_setpgrp = setpgid (0, 0);
-#else
-#if defined(USG) && !defined(SETPGRP_ARGS)
- debug_setpgrp = setpgrp ();
-#else
- debug_setpgrp = setpgrp (getpid (), getpid ());
-#endif /* USG */
-#endif /* NEED_POSIX_SETPGID */
- if (debug_setpgrp == -1)
- perror("setpgrp failed in child");
-#endif /* TIOCGPGRP */
-
-#ifdef SET_STACK_LIMIT_HUGE
- /* Reset the stack limit back to what it was. */
- {
- struct rlimit rlim;
-
- getrlimit (RLIMIT_STACK, &rlim);
- rlim.rlim_cur = original_stack_limit;
- setrlimit (RLIMIT_STACK, &rlim);
- }
-#endif /* SET_STACK_LIMIT_HUGE */
-
- /* Ask the tty subsystem to switch to the one we specified earlier
- (or to share the current terminal, if none was specified). */
-
- new_tty ();
-
- /* Changing the signal handlers for the inferior after
- a vfork can also change them for the superior, so we don't mess
- with signals here. See comments in
- initialize_signals for how we get the right signal handlers
- for the inferior. */
-
-#ifdef USE_PROC_FS
- /* Use SVR4 /proc interface */
- proc_set_exec_trap ();
-#else
- /* "Trace me, Dr. Memory!" */
- call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0);
-#endif
-
- /* There is no execlpe call, so we have to set the environment
- for our child in the global variable. If we've vforked, this
- clobbers the parent, but environ is restored a few lines down
- in the parent. By the way, yes we do need to look down the
- path to find $SHELL. Rich Pixley says so, and I agree. */
- environ = env;
- execlp (shell_file, shell_file, "-c", shell_command, (char *)0);
-
- fprintf (stderr, "Cannot exec %s: %s.\n", shell_file,
- safe_strerror (errno));
- fflush (stderr);
- _exit (0177);
- }
-
- /* Restore our environment in case a vforked child clob'd it. */
- environ = save_our_env;
-
- /* Now that we have a child process, make it our target. */
- push_target (&child_ops);
-
-#ifdef CREATE_INFERIOR_HOOK
- CREATE_INFERIOR_HOOK (pid);
-#endif
-
-/* The process was started by the fork that created it,
- but it will have stopped one instruction after execing the shell.
- Here we must get it up to actual execution of the real program. */
-
- inferior_pid = pid; /* Needed for wait_for_inferior stuff below */
-
- clear_proceed_status ();
-
- /* We will get a trace trap after one instruction.
- Continue it automatically. Eventually (after shell does an exec)
- it will get another trace trap. Then insert breakpoints and continue. */
-
-#ifdef START_INFERIOR_TRAPS_EXPECTED
- pending_execs = START_INFERIOR_TRAPS_EXPECTED;
-#else
- pending_execs = 2;
-#endif
-
- init_wait_for_inferior ();
-
- /* Set up the "saved terminal modes" of the inferior
- based on what modes we are starting it with. */
- target_terminal_init ();
-
- /* Install inferior's terminal modes. */
- target_terminal_inferior ();
-
- while (1)
- {
- stop_soon_quietly = 1; /* Make wait_for_inferior be quiet */
- wait_for_inferior ();
- if (stop_signal != SIGTRAP)
- {
- /* Let shell child handle its own signals in its own way */
- /* FIXME, what if child has exit()ed? Must exit loop somehow */
- resume (0, stop_signal);
- }
- else
- {
- /* We handle SIGTRAP, however; it means child did an exec. */
- if (0 == --pending_execs)
- break;
- resume (0, 0); /* Just make it go on */
- }
- }
- stop_soon_quietly = 0;
-
- /* We are now in the child process of interest, having exec'd the
- correct program, and are poised at the first instruction of the
- new program. */
-#ifdef SOLIB_CREATE_INFERIOR_HOOK
- SOLIB_CREATE_INFERIOR_HOOK (pid);
-#endif
-
- /* Pedal to the metal. Away we go. */
+ fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him);
+ /* We are at the first instruction we care about. */
+ /* Pedal to the metal... */
proceed ((CORE_ADDR) -1, 0, 0);
}
@@ -465,6 +290,7 @@ struct target_ops child_ops = {
child_create_inferior, /* to_create_inferior */
child_mourn_inferior, /* to_mourn_inferior */
child_can_run, /* to_can_run */
+ 0, /* to_notice_signals */
process_stratum, /* to_stratum */
0, /* to_next */
1, /* to_has_all_memory */
diff --git a/gdb/osfsolib.c b/gdb/osfsolib.c
index 549258a..4006f17 100644
--- a/gdb/osfsolib.c
+++ b/gdb/osfsolib.c
@@ -742,7 +742,7 @@ solib_create_inferior_hook()
stop_signal = 0;
do
{
- target_resume (inferior_pid, 0, stop_signal);
+ target_resume (-1, 0, stop_signal);
wait_for_inferior ();
}
while (stop_signal != SIGTRAP);
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 4c8ab5c..04b3ae2 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -39,6 +39,8 @@ regardless of whether or not the actual target has floating point hardware.
#include <fcntl.h>
#include <errno.h>
#include <string.h>
+#include <stropts.h>
+#include <poll.h>
#include "inferior.h"
#include "target.h"
@@ -74,10 +76,11 @@ CORE_ADDR kernel_u_addr;
the inferior's procinfo information. */
struct procinfo {
- int valid; /* Nonzero if pid, fd, & pathname are valid */
+ struct procinfo *next;
int pid; /* Process ID of inferior */
int fd; /* File descriptor for /proc entry */
char *pathname; /* Pathname to /proc entry */
+ int had_event; /* poll/select says something happened */
int was_stopped; /* Nonzero if was stopped prior to attach */
int nopass_next_sigstop; /* Don't pass a sigstop on next resume */
prrun_t prrun; /* Control state when it is run */
@@ -95,7 +98,14 @@ struct procinfo {
sysset_t saved_entryset; /* Saved traced system call entry set */
};
-static struct procinfo pi; /* Inferior's process information */
+/* 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 */
+
+static int last_resume_pid = -1; /* Last pid used with procfs_resume */
/* Much of the information used in the /proc interface, particularly for
printing status information, is kept as tables of structures of the
@@ -360,7 +370,7 @@ static char *
errnoname PARAMS ((int));
static int
-proc_address_to_fd PARAMS ((CORE_ADDR, int));
+proc_address_to_fd PARAMS ((struct procinfo *, CORE_ADDR, int));
static int
open_proc_file PARAMS ((int, struct procinfo *, int));
@@ -369,10 +379,10 @@ static void
close_proc_file PARAMS ((struct procinfo *));
static void
-unconditionally_kill_inferior PARAMS ((void));
+unconditionally_kill_inferior PARAMS ((struct procinfo *));
-static void
-proc_init_failed PARAMS ((char *));
+static NORETURN void
+proc_init_failed PARAMS ((struct procinfo *, char *));
static void
info_proc PARAMS ((char *, int));
@@ -417,7 +427,10 @@ static void
procfs_create_inferior PARAMS ((char *, char *, char **));
static void
-procfs_notice_signals PARAMS ((void));
+procfs_notice_signals PARAMS ((pid_t pid));
+
+static struct procinfo *
+find_procinfo PARAMS ((pid_t pid, int okfail));
/* External function prototypes that can't be easily included in any
header file because the args are typedefs in system include files. */
@@ -438,6 +451,117 @@ fill_fpregset PARAMS ((fpregset_t *, int));
LOCAL FUNCTION
+ find_procinfo -- convert a process id to a struct procinfo
+
+SYNOPSIS
+
+ static struct procinfo * find_procinfo (pid_t pid, int okfail);
+
+DESCRIPTION
+
+ Given a process id, look it up in the procinfo chain. Returns
+ a struct procinfo *. If can't find pid, then call error(),
+ unless okfail is set, in which case, return NULL;
+ */
+
+static struct procinfo *
+find_procinfo (pid, okfail)
+ pid_t pid;
+ int okfail;
+{
+ struct procinfo *procinfo;
+
+ for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ if (procinfo->pid == pid)
+ return procinfo;
+
+ if (okfail)
+ return NULL;
+
+ error ("procfs (find_procinfo): Couldn't locate pid %d", pid);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ add_fd -- Add the fd to the poll/select list
+
+SYNOPSIS
+
+ static void add_fd (struct procinfo *);
+
+DESCRIPTION
+
+ Add the fd of the supplied procinfo to the list of fds used for
+ poll/select operations.
+ */
+
+static void
+add_fd (pi)
+ struct procinfo *pi;
+{
+ if (num_poll_list <= 0)
+ poll_list = (struct pollfd *) xmalloc (sizeof (struct pollfd));
+ else
+ poll_list = (struct pollfd *) xrealloc (poll_list,
+ (num_poll_list + 1)
+ * sizeof (struct pollfd));
+ poll_list[num_poll_list].fd = pi->fd;
+ poll_list[num_poll_list].events = POLLPRI;
+
+ num_poll_list++;
+}
+
+static void
+remove_fd (pi)
+ struct procinfo *pi;
+{
+ int i;
+
+ for (i = 0; i < num_poll_list; i++)
+ {
+ if (poll_list[i].fd == pi->fd)
+ {
+ if (i != num_poll_list - 1)
+ memcpy (poll_list, poll_list + i + 1,
+ (num_poll_list - i - 1) * sizeof (struct pollfd));
+
+ num_poll_list--;
+
+ if (num_poll_list == 0)
+ free (poll_list);
+ else
+ poll_list = (struct pollfd *) xrealloc (poll_list,
+ num_poll_list
+ * sizeof (struct pollfd));
+ return;
+ }
+ }
+}
+
+/*
+
+LOCAL MACRO
+
+ current_procinfo -- convert inferior_pid to a struct procinfo
+
+SYNOPSIS
+
+ static struct procinfo * current_procinfo;
+
+DESCRIPTION
+
+ Looks up inferior_pid in the procinfo chain. Always returns a
+ struct procinfo *. If process can't be found, we error() out.
+ */
+
+#define current_procinfo find_procinfo (inferior_pid, 0)
+
+/*
+
+LOCAL FUNCTION
+
lookupdesc -- translate a value to a summary desc string
SYNOPSIS
@@ -1011,6 +1135,9 @@ init_syscall_table ()
#if defined (SYS_seteuid)
syscall_table[SYS_seteuid] = "seteuid";
#endif
+#if defined (SYS_sproc)
+ syscall_table[SYS_sproc] = "sproc";
+#endif
}
/*
@@ -1068,11 +1195,12 @@ NOTES
static void
procfs_kill_inferior ()
{
- if (inferior_pid != 0)
- {
- unconditionally_kill_inferior ();
- target_mourn_inferior ();
- }
+ struct procinfo *pi;
+
+ for (pi = procinfo_list; pi; pi = pi->next)
+ unconditionally_kill_inferior (pi);
+
+ target_mourn_inferior ();
}
/*
@@ -1083,30 +1211,39 @@ LOCAL FUNCTION
SYNOPSIS
- static void unconditionally_kill_inferior (void)
+ static void unconditionally_kill_inferior (struct procinfo *)
DESCRIPTION
- Kill the current inferior. Should not be called until it
- is at least tested that there is an inferior.
+ Kill the specified inferior.
NOTE
A possibly useful enhancement would be to first try sending
the inferior a terminate signal, politely asking it to commit
- suicide, before we murder it.
+ suicide, before we murder it (we could call that
+ politely_kill_inferior()).
*/
static void
-unconditionally_kill_inferior ()
+unconditionally_kill_inferior (pi)
+ struct procinfo *pi;
{
int signo;
+ int ppid;
+ ppid = pi->prstatus.pr_ppid;
+
signo = SIGKILL;
- ioctl (pi.fd, PIOCKILL, &signo);
- close_proc_file (&pi);
- wait ((int *) 0);
+ ioctl (pi->fd, PIOCKILL, &signo);
+ close_proc_file (pi);
+
+/* Only wait() for our direct children. Our grandchildren zombies are killed
+ by the death of their parents. */
+
+ if (ppid == getpid())
+ wait ((int *) 0);
}
/*
@@ -1145,16 +1282,19 @@ procfs_xfer_memory (memaddr, myaddr, len, dowrite, target)
struct target_ops *target; /* ignored */
{
int nbytes = 0;
+ struct procinfo *pi;
- if (lseek (pi.fd, (off_t) memaddr, 0) == (off_t) memaddr)
+ pi = current_procinfo;
+
+ if (lseek(pi->fd, (off_t) memaddr, 0) == (off_t) memaddr)
{
if (dowrite)
{
- nbytes = write (pi.fd, myaddr, len);
+ nbytes = write (pi->fd, myaddr, len);
}
else
{
- nbytes = read (pi.fd, myaddr, len);
+ nbytes = read (pi->fd, myaddr, len);
}
if (nbytes < 0)
{
@@ -1206,12 +1346,16 @@ static void
procfs_store_registers (regno)
int regno;
{
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
if (regno != -1)
{
- ioctl (pi.fd, PIOCGREG, &pi.gregset);
+ ioctl (pi->fd, PIOCGREG, &pi->gregset);
}
- fill_gregset (&pi.gregset, regno);
- ioctl (pi.fd, PIOCSREG, &pi.gregset);
+ fill_gregset (&pi->gregset, regno);
+ ioctl (pi->fd, PIOCSREG, &pi->gregset);
#if defined (FP0_REGNUM)
@@ -1221,10 +1365,10 @@ procfs_store_registers (regno)
if (regno != -1)
{
- ioctl (pi.fd, PIOCGFPREG, &pi.fpregset);
+ ioctl (pi->fd, PIOCGFPREG, &pi->fpregset);
}
- fill_fpregset (&pi.fpregset, regno);
- ioctl (pi.fd, PIOCSFPREG, &pi.fpregset);
+ fill_fpregset (&pi->fpregset, regno);
+ ioctl (pi->fd, PIOCSFPREG, &pi->fpregset);
#endif /* FP0_REGNUM */
@@ -1234,7 +1378,64 @@ procfs_store_registers (regno)
LOCAL FUNCTION
- procfs_init_inferior - initialize access to a /proc entry
+ create_procinfo - initialize access to a /proc entry
+
+SYNOPSIS
+
+ void create_procinfo (int pid)
+
+DESCRIPTION
+
+ Allocate a procinfo structure, open the /proc file and then sets up
+ the set of signals and faults that are to be traced.
+
+NOTES
+
+ If proc_init_failed ever gets called, control returns to the command
+ processing loop via the standard error handling code.
+
+ */
+
+static void
+create_procinfo (pid)
+ int pid;
+{
+ struct procinfo *pi;
+
+ if (find_procinfo (pid, 1))
+ return; /* All done! It already exists */
+
+ pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+
+ if (!open_proc_file (pid, pi, O_RDWR))
+ proc_init_failed (pi, "can't open process file");
+
+ /* Add new process to process info list */
+
+ pi->next = procinfo_list;
+ procinfo_list = pi;
+
+ add_fd (pi); /* Add to list for poll/select */
+
+ memset ((char *) &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);
+
+ if (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)
+ proc_init_failed (pi, "PIOCWSTOP failed");
+
+ if (ioctl (pi->fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)
+ proc_init_failed (pi, "PIOCSFAULT failed");
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_init_inferior - initialize target vector and access to a
+ /proc entry
SYNOPSIS
@@ -1259,29 +1460,10 @@ static void
procfs_init_inferior (pid)
int pid;
{
-
push_target (&procfs_ops);
- if (!open_proc_file (pid, &pi, O_RDWR))
- {
- proc_init_failed ("can't open process file");
- }
- else
- {
- memset ((char *) &pi.prrun, 0, sizeof (pi.prrun));
- prfillset (&pi.prrun.pr_trace);
- procfs_notice_signals ();
- prfillset (&pi.prrun.pr_fault);
- prdelset (&pi.prrun.pr_fault, FLTPAGE);
- if (ioctl (pi.fd, PIOCWSTOP, &pi.prstatus) < 0)
- {
- proc_init_failed ("PIOCWSTOP failed");
- }
- else if (ioctl (pi.fd, PIOCSFAULT, &pi.prrun.pr_fault) < 0)
- {
- proc_init_failed ("PIOCSFAULT failed");
- }
- }
+ create_procinfo (pid);
+ add_thread (pid); /* Setup initial thread */
}
/*
@@ -1292,7 +1474,7 @@ GLOBAL FUNCTION
SYNOPSIS
- static void procfs_notice_signals (void);
+ static void procfs_notice_signals (pid_t pid);
DESCRIPTION
@@ -1310,30 +1492,31 @@ DESCRIPTION
*/
static void
-procfs_notice_signals ()
+procfs_notice_signals (pid)
+ pid_t pid;
{
int signo;
+ struct procinfo *pi;
- if (pi.valid)
+ pi = find_procinfo (pid, 0);
+
+ for (signo = 0; signo < NSIG; signo++)
{
- for (signo = 0; signo < NSIG; signo++)
+ if (signal_stop_state (signo) == 0 &&
+ signal_print_state (signo) == 0 &&
+ signal_pass_state (signo) == 1)
{
- if (signal_stop_state (signo) == 0 &&
- signal_print_state (signo) == 0 &&
- signal_pass_state (signo) == 1)
- {
- prdelset (&pi.prrun.pr_trace, signo);
- }
- else
- {
- praddset (&pi.prrun.pr_trace, signo);
- }
+ prdelset (&pi->prrun.pr_trace, signo);
}
- if (ioctl (pi.fd, PIOCSTRACE, &pi.prrun.pr_trace))
+ else
{
- print_sys_errmsg ("PIOCSTRACE failed", errno);
+ praddset (&pi->prrun.pr_trace, signo);
}
}
+ if (ioctl (pi->fd, PIOCSTRACE, &pi->prrun.pr_trace))
+ {
+ print_sys_errmsg ("PIOCSTRACE failed", errno);
+ }
}
/*
@@ -1464,15 +1647,18 @@ proc_iterate_over_mappings (func)
int funcstat = 0;
struct prmap *prmaps;
struct prmap *prmap;
+ struct procinfo *pi;
+
+ pi = current_procinfo;
- if (pi.valid && (ioctl (pi.fd, PIOCNMAP, &nmap) == 0))
+ if (ioctl (pi->fd, PIOCNMAP, &nmap) == 0)
{
prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
- if (ioctl (pi.fd, PIOCMAP, prmaps) == 0)
+ if (ioctl (pi->fd, PIOCMAP, prmaps) == 0)
{
for (prmap = prmaps; prmap -> pr_size && funcstat == 0; ++prmap)
{
- fd = proc_address_to_fd ((CORE_ADDR) prmap -> pr_vaddr, 0);
+ fd = proc_address_to_fd (pi, (CORE_ADDR) prmap -> pr_vaddr, 0);
funcstat = (*func) (fd, (CORE_ADDR) prmap -> pr_vaddr);
close (fd);
}
@@ -1511,11 +1697,14 @@ proc_base_address (addr)
struct prmap *prmaps;
struct prmap *prmap;
CORE_ADDR baseaddr = 0;
+ struct procinfo *pi;
- if (pi.valid && (ioctl (pi.fd, PIOCNMAP, &nmap) == 0))
+ pi = current_procinfo;
+
+ if (ioctl (pi->fd, PIOCNMAP, &nmap) == 0)
{
prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
- if (ioctl (pi.fd, PIOCMAP, prmaps) == 0)
+ if (ioctl (pi->fd, PIOCMAP, prmaps) == 0)
{
for (prmap = prmaps; prmap -> pr_size; ++prmap)
{
@@ -1541,7 +1730,7 @@ LOCAL FUNCTION
SYNOPSIS
- int proc_address_to_fd (CORE_ADDR addr, complain)
+ int proc_address_to_fd (struct procinfo *pi, CORE_ADDR addr, complain)
DESCRIPTION
@@ -1554,21 +1743,19 @@ DESCRIPTION
*/
static int
-proc_address_to_fd (addr, complain)
+proc_address_to_fd (pi, addr, complain)
+ struct procinfo *pi;
CORE_ADDR addr;
int complain;
{
int fd = -1;
- if (pi.valid)
+ if ((fd = ioctl (pi->fd, PIOCOPENM, (caddr_t *) &addr)) < 0)
{
- if ((fd = ioctl (pi.fd, PIOCOPENM, (caddr_t *) &addr)) < 0)
+ if (complain)
{
- if (complain)
- {
- print_sys_errmsg (pi.pathname, errno);
- warning ("can't find mapped file for address 0x%x", addr);
- }
+ print_sys_errmsg (pi->pathname, errno);
+ warning ("can't find mapped file for address 0x%x", addr);
}
}
return (fd);
@@ -1707,30 +1894,41 @@ do_attach (pid)
int pid;
{
int result;
+ struct procinfo *pi;
+
+ pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
- if (!open_proc_file (pid, &pi, O_RDWR))
+ if (!open_proc_file (pid, pi, O_RDWR))
{
- perror_with_name (pi.pathname);
+ free (pi);
+ perror_with_name (pi->pathname);
/* NOTREACHED */
}
+ /* Add new process to process info list */
+
+ pi->next = procinfo_list;
+ procinfo_list = pi;
+
+ add_fd (pi); /* Add to list for poll/select */
+
/* 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 (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)
+ if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)
{
- print_sys_errmsg (pi.pathname, errno);
- close_proc_file (&pi);
+ print_sys_errmsg (pi->pathname, errno);
+ close_proc_file (pi);
error ("PIOCSTATUS failed");
}
- if (pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+ if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
{
- pi.was_stopped = 1;
+ pi->was_stopped = 1;
}
else
{
- pi.was_stopped = 0;
+ pi->was_stopped = 0;
if (1 || query ("Process is currently running, stop it? "))
{
/* Make it run again when we close it. */
@@ -1738,26 +1936,26 @@ do_attach (pid)
{
long pr_flags;
pr_flags = PR_RLC;
- result = ioctl (pi.fd, PIOCSET, &pr_flags);
+ result = ioctl (pi->fd, PIOCSET, &pr_flags);
}
#else
#if defined (PIOCSRLC) /* Original method */
- result = ioctl (pi.fd, PIOCSRLC, 0);
+ result = ioctl (pi->fd, PIOCSRLC, 0);
#endif
#endif
if (result < 0)
{
- print_sys_errmsg (pi.pathname, errno);
- close_proc_file (&pi);
+ print_sys_errmsg (pi->pathname, errno);
+ close_proc_file (pi);
error ("PIOCSRLC or PIOCSET failed");
}
- if (ioctl (pi.fd, PIOCSTOP, &pi.prstatus) < 0)
+ if (ioctl (pi->fd, PIOCSTOP, &pi->prstatus) < 0)
{
- print_sys_errmsg (pi.pathname, errno);
- close_proc_file (&pi);
+ print_sys_errmsg (pi->pathname, errno);
+ close_proc_file (pi);
error ("PIOCSTOP failed");
}
- pi.nopass_next_sigstop = 1;
+ pi->nopass_next_sigstop = 1;
}
else
{
@@ -1768,24 +1966,24 @@ do_attach (pid)
/* Remember some things about the inferior that we will, or might, change
so that we can restore them when we detach. */
- ioctl (pi.fd, PIOCGTRACE, &pi.saved_trace);
- ioctl (pi.fd, PIOCGHOLD, &pi.saved_sighold);
- ioctl (pi.fd, PIOCGFAULT, &pi.saved_fltset);
- ioctl (pi.fd, PIOCGENTRY, &pi.saved_entryset);
- ioctl (pi.fd, PIOCGEXIT, &pi.saved_exitset);
+ ioctl (pi->fd, PIOCGTRACE, &pi->saved_trace);
+ ioctl (pi->fd, PIOCGHOLD, &pi->saved_sighold);
+ ioctl (pi->fd, PIOCGFAULT, &pi->saved_fltset);
+ ioctl (pi->fd, PIOCGENTRY, &pi->saved_entryset);
+ ioctl (pi->fd, PIOCGEXIT, &pi->saved_exitset);
/* 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 ();
- prfillset (&pi.prrun.pr_fault);
- prdelset (&pi.prrun.pr_fault, FLTPAGE);
- if (ioctl (pi.fd, PIOCSFAULT, &pi.prrun.pr_fault))
+ 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);
+ if (ioctl (pi->fd, PIOCSFAULT, &pi->prrun.pr_fault))
{
print_sys_errmsg ("PIOCSFAULT failed", errno);
}
- if (ioctl (pi.fd, PIOCSTRACE, &pi.prrun.pr_trace))
+ if (ioctl (pi->fd, PIOCSTRACE, &pi->prrun.pr_trace))
{
print_sys_errmsg ("PIOCSTRACE failed", errno);
}
@@ -1827,52 +2025,55 @@ do_detach (signal)
int signal;
{
int result;
+ struct procinfo *pi;
+
+ pi = current_procinfo;
if (signal)
{
- set_proc_siginfo (&pi, signal);
+ set_proc_siginfo (pi, signal);
}
- if (ioctl (pi.fd, PIOCSEXIT, &pi.saved_exitset) < 0)
+ if (ioctl (pi->fd, PIOCSEXIT, &pi->saved_exitset) < 0)
{
- print_sys_errmsg (pi.pathname, errno);
+ print_sys_errmsg (pi->pathname, errno);
printf ("PIOCSEXIT failed.\n");
}
- if (ioctl (pi.fd, PIOCSENTRY, &pi.saved_entryset) < 0)
+ if (ioctl (pi->fd, PIOCSENTRY, &pi->saved_entryset) < 0)
{
- print_sys_errmsg (pi.pathname, errno);
+ print_sys_errmsg (pi->pathname, errno);
printf ("PIOCSENTRY failed.\n");
}
- if (ioctl (pi.fd, PIOCSTRACE, &pi.saved_trace) < 0)
+ if (ioctl (pi->fd, PIOCSTRACE, &pi->saved_trace) < 0)
{
- print_sys_errmsg (pi.pathname, errno);
+ print_sys_errmsg (pi->pathname, errno);
printf ("PIOCSTRACE failed.\n");
}
- if (ioctl (pi.fd, PIOCSHOLD, &pi.saved_sighold) < 0)
+ if (ioctl (pi->fd, PIOCSHOLD, &pi->saved_sighold) < 0)
{
- print_sys_errmsg (pi.pathname, errno);
+ print_sys_errmsg (pi->pathname, errno);
printf ("PIOSCHOLD failed.\n");
}
- if (ioctl (pi.fd, PIOCSFAULT, &pi.saved_fltset) < 0)
+ if (ioctl (pi->fd, PIOCSFAULT, &pi->saved_fltset) < 0)
{
- print_sys_errmsg (pi.pathname, errno);
+ print_sys_errmsg (pi->pathname, errno);
printf ("PIOCSFAULT failed.\n");
}
- if (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)
+ if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)
{
- print_sys_errmsg (pi.pathname, errno);
+ print_sys_errmsg (pi->pathname, errno);
printf ("PIOCSTATUS failed.\n");
}
else
{
- if (signal || (pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+ if (signal || (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
{
- if (signal || !pi.was_stopped ||
+ if (signal || !pi->was_stopped ||
query ("Was stopped when attached, make it runnable again? "))
{
/* Clear any fault that might have stopped it. */
- if (ioctl (pi.fd, PIOCCFAULT, 0))
+ if (ioctl (pi->fd, PIOCCFAULT, 0))
{
- print_sys_errmsg (pi.pathname, errno);
+ print_sys_errmsg (pi->pathname, errno);
printf ("PIOCCFAULT failed.\n");
}
@@ -1881,22 +2082,22 @@ do_detach (signal)
{
long pr_flags;
pr_flags = PR_RLC;
- result = ioctl (pi.fd, PIOCSET, &pr_flags);
+ result = ioctl (pi->fd, PIOCSET, &pr_flags);
}
#else
#if defined (PIOCSRLC) /* Original method */
- result = ioctl (pi.fd, PIOCSRLC, 0);
+ result = ioctl (pi->fd, PIOCSRLC, 0);
#endif
#endif
if (result)
{
- print_sys_errmsg (pi.pathname, errno);
+ print_sys_errmsg (pi->pathname, errno);
printf ("PIOCSRLC or PIOCSET failed.\n");
}
}
}
}
- close_proc_file (&pi);
+ close_proc_file (pi);
attach_flag = 0;
}
@@ -1911,7 +2112,7 @@ LOCAL FUNCTION
SYNOPSIS
- int procfs_wait (int *statloc)
+ int procfs_wait (int pid, int *statloc)
DESCRIPTION
@@ -1941,7 +2142,8 @@ NOTES
*/
static int
-procfs_wait (statloc)
+procfs_wait (pid, statloc)
+ int pid;
int *statloc;
{
short what;
@@ -1949,24 +2151,73 @@ procfs_wait (statloc)
int statval = 0;
int checkerr = 0;
int rtnval = -1;
-
- if (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)
- {
- checkerr++;
- }
- else if (!(pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+ struct procinfo *pi;
+
+ if (pid != -1) /* Non-specific process? */
+ pi = NULL;
+ else
+ for (pi = procinfo_list; pi; pi = pi->next)
+ if (pi->had_event)
+ break;
+
+wait_again:
+
+ if (!pi)
{
+ int num_fds;
+ int i;
+
if (attach_flag)
set_sigint_trap(); /* Causes SIGINT to be passed on to the
attached process. */
- if (ioctl (pi.fd, PIOCWSTOP, &pi.prstatus) < 0)
+ num_fds = poll (poll_list, num_poll_list, -1);
+
+ if (attach_flag)
+ clear_sigint_trap();
+
+ if (num_fds <= 0)
{
- checkerr++;
+ print_sys_errmsg (pi->pathname, errno);
+ error ("poll failed, returned %d\n", num_fds);
}
- if (attach_flag)
- clear_sigint_trap();
+ for (i = 0; i < num_poll_list && num_fds > 0; i++)
+ {
+ if ((poll_list[i].revents & (POLLPRI|POLLERR|POLLHUP|POLLNVAL)) == 0)
+ continue;
+ for (pi = procinfo_list; pi; pi = pi->next)
+ {
+ if (poll_list[i].fd == pi->fd)
+ {
+ if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)
+ checkerr++;
+ /* perror_with_name (pi->pathname);*/
+ num_fds--;
+ pi->had_event = 1;
+ break;
+ }
+ }
+ if (!pi)
+ error ("procfs_wait: Couldn't find procinfo for fd %d\n",
+ poll_list[i].fd);
+ }
+ }
+
+ if (pid != -1)
+ for (pi = procinfo_list; pi; pi = pi->next)
+ if (pi->pid == pid && pi->had_event)
+ break;
+
+ if (!pi && !checkerr)
+ goto wait_again;
+
+ if (!checkerr && !(pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+ {
+ if (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)
+ {
+ checkerr++;
+ }
}
if (checkerr)
{
@@ -1975,55 +2226,86 @@ procfs_wait (statloc)
rtnval = wait (&statval);
if (rtnval != inferior_pid)
{
- print_sys_errmsg (pi.pathname, errno);
+ print_sys_errmsg (pi->pathname, errno);
error ("PIOCWSTOP, wait failed, returned %d", rtnval);
/* NOTREACHED */
}
}
else
{
- print_sys_errmsg (pi.pathname, errno);
+ print_sys_errmsg (pi->pathname, errno);
error ("PIOCSTATUS or PIOCWSTOP failed.");
/* NOTREACHED */
}
}
- else if (pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+ else if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
{
- rtnval = pi.prstatus.pr_pid;
- why = pi.prstatus.pr_why;
- what = pi.prstatus.pr_what;
- if (why == PR_SIGNALLED)
+ rtnval = pi->prstatus.pr_pid;
+ why = pi->prstatus.pr_why;
+ what = pi->prstatus.pr_what;
+
+ switch (why)
{
+ case PR_SIGNALLED:
statval = (what << 8) | 0177;
- }
- else if ((why == PR_SYSEXIT)
- &&
- (
+ break;
+ case PR_SYSEXIT:
+ switch (what)
+ {
#ifdef SYS_exec
- what == SYS_exec
-#else
- 0 == 0
+ case SYS_exec:
#endif
#ifdef SYS_execve
- || what == SYS_execve
+ case SYS_execve:
#endif
#ifdef SYS_execv
- || what == SYS_execv
+ case SYS_execv:
#endif
- ))
- {
- statval = (SIGTRAP << 8) | 0177;
- }
- else if (why == PR_REQUESTED)
- {
+ statval = (SIGTRAP << 8) | 0177;
+ break;
+#ifdef SYS_sproc
+ case SYS_sproc:
+/* We've just detected the completion of an sproc system call. Now we need to
+ setup a procinfo struct for this thread, and notify the thread system of the
+ new arrival. */
+
+/* If sproc failed, then nothing interesting happened. Continue the process and
+ go back to sleep. */
+
+ if (pi->prstatus.pr_errno != 0)
+ {
+ pi->prrun.pr_flags &= PRSTEP;
+ pi->prrun.pr_flags |= PRCFAULT;
+
+ if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)
+ perror_with_name (pi->pathname);
+
+ goto wait_again;
+ }
+
+/* At this point, the new thread is stopped at it's first instruction, and
+ the parent is stopped at the exit from sproc. */
+
+/* Notify the caller of the arrival of a new thread. */
+ create_procinfo (pi->prstatus.pr_rval1);
+
+ rtnval = pi->prstatus.pr_rval1;
+ statval = (SIGTRAP << 8) | 0177;
+
+ break;
+#endif /* SYS_sproc */
+
+ default:
+ error ("PIOCSTATUS (PR_SYSEXIT): Unknown system call %d", what);
+ }
+ break;
+ case PR_REQUESTED:
statval = (SIGSTOP << 8) | 0177;
- }
- else if (why == PR_JOBCONTROL)
- {
+ break;
+ case PR_JOBCONTROL:
statval = (what << 8) | 0177;
- }
- else if (why == PR_FAULTED)
- {
+ break;
+ case PR_FAULTED:
switch (what)
{
case FLTPRIV:
@@ -2046,23 +2328,32 @@ procfs_wait (statloc)
break;
case FLTPAGE: /* Recoverable page fault */
default:
- rtnval = -1;
error ("PIOCWSTOP, unknown why %d, what %d", why, what);
- /* NOTREACHED */
}
- }
- else
- {
- rtnval = -1;
+ break;
+ default:
error ("PIOCWSTOP, unknown why %d, what %d", why, what);
- /* NOTREACHED */
}
+/* Stop all the other threads when any of them stops. */
+
+ {
+ struct procinfo *procinfo;
+
+ for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ {
+ if (!procinfo->had_event)
+ if (ioctl (procinfo->fd, PIOCSTOP, &procinfo->prstatus) < 0)
+ {
+ print_sys_errmsg (procinfo->pathname, errno);
+ error ("PIOCSTOP failed");
+ }
+ }
+ }
}
else
{
error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x",
- pi.prstatus.pr_flags);
- /* NOTREACHED */
+ pi->prstatus.pr_flags);
}
if (statloc)
@@ -2077,6 +2368,7 @@ procfs_wait (statloc)
return rtnval;
}
+ pi->had_event = 0; /* Indicate that we've seen this one */
return (rtnval);
}
@@ -2126,27 +2418,24 @@ set_proc_siginfo (pip, signo)
struct siginfo newsiginfo;
struct siginfo *sip;
- if (pip -> valid)
+ if (signo == pip -> prstatus.pr_info.si_signo)
{
- if (signo == pip -> prstatus.pr_info.si_signo)
- {
- sip = &pip -> prstatus.pr_info;
- }
- else
- {
- memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
- sip = &newsiginfo;
- sip -> si_signo = signo;
- sip -> si_code = 0;
- sip -> si_errno = 0;
- sip -> si_pid = getpid ();
- sip -> si_uid = getuid ();
- }
- if (ioctl (pip -> fd, PIOCSSIG, sip) < 0)
- {
- print_sys_errmsg (pip -> pathname, errno);
- warning ("PIOCSSIG failed");
- }
+ sip = &pip -> prstatus.pr_info;
+ }
+ else
+ {
+ memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
+ sip = &newsiginfo;
+ sip -> si_signo = signo;
+ sip -> si_code = 0;
+ sip -> si_errno = 0;
+ sip -> si_pid = getpid ();
+ sip -> si_uid = getuid ();
+ }
+ if (ioctl (pip -> fd, PIOCSSIG, sip) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ warning ("PIOCSSIG failed");
}
}
@@ -2161,9 +2450,12 @@ procfs_resume (pid, step, signo)
int signo;
{
int signal_to_pass;
+ struct procinfo *pi, *procinfo;
+
+ pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
errno = 0;
- pi.prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;
+ pi->prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;
#if 0
/* It should not be necessary. If the user explicitly changes the value,
@@ -2180,12 +2472,12 @@ procfs_resume (pid, step, signo)
random garbage. We have to rely on the fact that PC and nPC have been
written previously via PIOCSREG during a register flush. */
- pi.prrun.pr_vaddr = (caddr_t) *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
- pi.prrun.pr_flags != PRSVADDR;
+ pi->prrun.pr_vaddr = (caddr_t) *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
+ pi->prrun.pr_flags != PRSVADDR;
#endif
#endif
- if (signo == SIGSTOP && pi.nopass_next_sigstop)
+ if (signo == SIGSTOP && pi->nopass_next_sigstop)
/* When attaching to a child process, if we forced it to stop with
a PIOCSTOP, then we will have set the nopass_next_sigstop flag.
Upon resuming the first time after such a stop, we explicitly
@@ -2198,8 +2490,8 @@ procfs_resume (pid, step, signo)
an inferior to continue running at the same time as gdb. (FIXME?) */
signal_to_pass = 0;
else if (signo == SIGTSTP
- && pi.prstatus.pr_cursig == SIGTSTP
- && pi.prstatus.pr_action.sa_handler == SIG_DFL)
+ && pi->prstatus.pr_cursig == SIGTSTP
+ && pi->prstatus.pr_action.sa_handler == SIG_DFL)
/* We are about to pass the inferior a SIGTSTP whose action is
SIG_DFL. The SIG_DFL action for a SIGTSTP is to stop
@@ -2221,22 +2513,48 @@ procfs_resume (pid, step, signo)
if (signal_to_pass)
{
- set_proc_siginfo (&pi, signal_to_pass);
+ set_proc_siginfo (pi, signal_to_pass);
}
else
{
- pi.prrun.pr_flags |= PRCSIG;
+ pi->prrun.pr_flags |= PRCSIG;
}
- pi.nopass_next_sigstop = 0;
+ pi->nopass_next_sigstop = 0;
if (step)
{
- pi.prrun.pr_flags |= PRSTEP;
+ pi->prrun.pr_flags |= PRSTEP;
}
- if (ioctl (pi.fd, PIOCRUN, &pi.prrun) != 0)
+ if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)
{
- perror_with_name (pi.pathname);
+ perror_with_name (pi->pathname);
/* NOTREACHED */
}
+
+ pi->had_event = 0;
+
+ /* Continue all the other threads that haven't had an event of
+ interest. */
+
+ if (pid == -1)
+ for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ {
+ if (pi != procinfo && !procinfo->had_event)
+ {
+ procinfo->prrun.pr_flags &= PRSTEP;
+ procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
+ ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus);
+ if (ioctl (procinfo->fd, PIOCRUN, &procinfo->prrun) < 0)
+ {
+ if (ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus) < 0)
+ {
+ fprintf(stderr, "PIOCSTATUS failed, errno=%d\n", errno);
+ }
+ print_sys_errmsg (procinfo->pathname, errno);
+ error ("PIOCRUN failed");
+ }
+ ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus);
+ }
+ }
}
/*
@@ -2261,14 +2579,18 @@ static void
procfs_fetch_registers (regno)
int regno;
{
- if (ioctl (pi.fd, PIOCGREG, &pi.gregset) != -1)
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
+ if (ioctl (pi->fd, PIOCGREG, &pi->gregset) != -1)
{
- supply_gregset (&pi.gregset);
+ supply_gregset (&pi->gregset);
}
#if defined (FP0_REGNUM)
- if (ioctl (pi.fd, PIOCGFPREG, &pi.fpregset) != -1)
+ if (ioctl (pi->fd, PIOCGFPREG, &pi->fpregset) != -1)
{
- supply_fpregset (&pi.fpregset);
+ supply_fpregset (&pi->fpregset);
}
#endif
}
@@ -2277,11 +2599,12 @@ procfs_fetch_registers (regno)
LOCAL FUNCTION
- proc_init_failed - called whenever /proc access initialization fails
+ proc_init_failed - called whenever /proc access initialization
+fails
SYNOPSIS
- static void proc_init_failed (char *why)
+ static void proc_init_failed (struct procinfo *pi, char *why)
DESCRIPTION
@@ -2292,12 +2615,13 @@ DESCRIPTION
*/
static void
-proc_init_failed (why)
+proc_init_failed (pi, why)
+ struct procinfo *pi;
char *why;
{
- print_sys_errmsg (pi.pathname, errno);
- kill (pi.pid, SIGKILL);
- close_proc_file (&pi);
+ print_sys_errmsg (pi->pathname, errno);
+ kill (pi->pid, SIGKILL);
+ close_proc_file (pi);
error (why);
/* NOTREACHED */
}
@@ -2325,18 +2649,24 @@ static void
close_proc_file (pip)
struct procinfo *pip;
{
- pip -> pid = 0;
- if (pip -> valid)
- {
- close (pip -> fd);
- }
- pip -> fd = -1;
- if (pip -> pathname)
- {
- free (pip -> pathname);
- pip -> pathname = NULL;
- }
- pip -> valid = 0;
+ struct procinfo *procinfo;
+
+ remove_fd (pip); /* Remove fd from poll/select list */
+
+ close (pip -> fd);
+
+ free (pip -> pathname);
+
+ /* Unlink pip from the procinfo chain. Note pip might not be on the list. */
+
+ if (procinfo_list == pip)
+ procinfo_list = pip->next;
+ else
+ for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ if (procinfo->next == pip)
+ procinfo->next = pip->next;
+
+ free (pip);
}
/*
@@ -2369,22 +2699,16 @@ open_proc_file (pid, pip, mode)
struct procinfo *pip;
int mode;
{
- pip -> valid = 0; /* FIXME, what is this? ?! */
- if (pip -> valid)
- {
- close (pip -> fd);
- }
- if (pip -> pathname == NULL)
- {
- pip -> pathname = xmalloc (32);
- }
+ pip -> next = NULL;
+ pip -> had_event = 0;
+ pip -> pathname = xmalloc (32);
+ pip -> pid = pid;
+
sprintf (pip -> pathname, PROC_NAME_FMT, pid);
- if ((pip -> fd = open (pip -> pathname, mode)) >= 0)
- {
- pip -> valid = 1;
- pip -> pid = pid;
- }
- return (pip -> valid);
+ if ((pip -> fd = open (pip -> pathname, mode)) < 0)
+ return 0;
+
+ return 1;
}
static char *
@@ -2874,7 +3198,6 @@ info_proc (args, from_tty)
int from_tty;
{
int pid;
- struct procinfo pii;
struct procinfo *pip;
struct cleanup *old_chain;
char **argv;
@@ -2892,9 +3215,10 @@ info_proc (args, from_tty)
old_chain = make_cleanup (null_cleanup, 0);
- /* Default to using the current inferior if no pid specified */
+ /* Default to using the current inferior if no pid specified. Note
+ that inferior_pid may be 0, hence we set okerr. */
- pip = &pi;
+ pip = find_procinfo (inferior_pid, 1);
if (args != NULL)
{
@@ -2952,11 +3276,12 @@ info_proc (args, from_tty)
summary = 0;
times = 1;
}
- else if ((pii.pid = atoi (*argv)) > 0)
+ else if ((pid = atoi (*argv)) > 0)
{
- pid = pii.pid;
- pip = &pii;
- memset (&pii, 0, sizeof (pii));
+ pip = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+ memset (pip, 0, sizeof (*pip));
+
+ pip->pid = pid;
if (!open_proc_file (pid, pip, O_RDONLY))
{
perror_with_name (pip -> pathname);
@@ -2975,7 +3300,7 @@ info_proc (args, from_tty)
/* If we don't have a valid open process at this point, then we have no
inferior or didn't specify a specific pid. */
- if (!pip -> valid)
+ if (!pip)
{
error ("\
No process. Start debugging a program or specify an explicit process ID.");
@@ -3026,6 +3351,64 @@ No process. Start debugging a program or specify an explicit process ID.");
do_cleanups (old_chain);
}
+/*
+
+LOCAL FUNCTION
+
+ procfs_set_sproc_trap -- arrange for exec'd child stop on sproc
+
+SYNOPSIS
+
+ void procfs_set_sproc_trap (void)
+
+DESCRIPTION
+
+ This function sets up a trap on sproc system call exits so that we can
+ detect the arrival of a new thread. We are called with the child
+ stopped prior to it's first instruction.
+
+ Also note that we turn on the inherit-on-fork flag in the child process
+ so that any grand-children start with all tracing flags set.
+ */
+
+static void
+procfs_set_sproc_trap (pi)
+ struct procinfo *pi;
+{
+ sysset_t exitset;
+
+ if (ioctl (pi->fd, PIOCGEXIT, &exitset) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCGEXIT failed");
+ }
+
+#ifdef SYS_sproc
+ praddset (&exitset, SYS_sproc);
+#endif
+
+ if (ioctl (pi->fd, PIOCSEXIT, &exitset) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSEXIT failed");
+ }
+
+ /* Turn on inherit-on-fork flag so that all grand-children of gdb start with
+ tracing flags set. */
+
+#ifdef PIOCSET /* New method */
+ {
+ long pr_flags;
+ pr_flags = PR_FORK;
+ ioctl (pi->fd, PIOCSET, &pr_flags);
+ }
+#else
+#ifdef PIOCSFORK /* Original method */
+ ioctl (pi->fd, PIOCSFORK, NULL);
+#endif
+#endif
+}
+
/* Fork an inferior process, and start debugging it with /proc. */
static void
@@ -3038,6 +3421,11 @@ procfs_create_inferior (exec_file, allargs, env)
proc_set_exec_trap, procfs_init_inferior);
/* We are at the first instruction we care about. */
/* Pedal to the metal... */
+
+ /* Setup traps on exit from sproc() */
+
+ procfs_set_sproc_trap(current_procinfo);
+
proceed ((CORE_ADDR) -1, 0, 0);
}
diff --git a/gdb/remote-bug.c b/gdb/remote-bug.c
index 641895e..e1f3603 100644
--- a/gdb/remote-bug.c
+++ b/gdb/remote-bug.c
@@ -273,7 +273,8 @@ static char *wait_strings[] = {
};
int
-bug_wait (status)
+bug_wait (pid, status)
+ int pid;
WAITTYPE *status;
{
int old_timeout = sr_get_timeout();
diff --git a/gdb/remote-hms.c b/gdb/remote-hms.c
index 212b0fc..32ca1c9 100644
--- a/gdb/remote-hms.c
+++ b/gdb/remote-hms.c
@@ -664,7 +664,8 @@ hms_resume (pid, step, sig)
storing status in STATUS just as `wait' would. */
int
-hms_wait (status)
+hms_wait (pid, status)
+ int pid;
WAITTYPE *status;
{
/* Strings to look for. '?' means match any single character.
diff --git a/gdb/remote-mips.c b/gdb/remote-mips.c
index f04f0e8..6f60284 100644
--- a/gdb/remote-mips.c
+++ b/gdb/remote-mips.c
@@ -75,7 +75,7 @@ static void
mips_resume PARAMS ((int pid, int step, int siggnal));
static int
-mips_wait PARAMS ((WAITTYPE *status));
+mips_wait PARAMS ((int pid, WAITTYPE *status));
static int
mips_map_regno PARAMS ((int regno));
diff --git a/gdb/remote-mon.c b/gdb/remote-mon.c
index db323d5..56a90a7 100644
--- a/gdb/remote-mon.c
+++ b/gdb/remote-mon.c
@@ -461,7 +461,8 @@ monitor_resume (pid, step, sig)
*/
static int
-monitor_wait (status)
+monitor_wait (pid, status)
+ int pid;
WAITTYPE *status;
{
int old_timeout = timeout;
diff --git a/gdb/remote-nindy.c b/gdb/remote-nindy.c
index 35365c1..d6551fc 100644
--- a/gdb/remote-nindy.c
+++ b/gdb/remote-nindy.c
@@ -299,7 +299,8 @@ You may need to reset the 80960 and/or reload your program.\n");
*/
static int
-nindy_wait( status )
+nindy_wait( pid, status )
+ int pid;
WAITTYPE *status;
{
fd_set fds;
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index 83600e8..dbecaa0 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -345,7 +345,8 @@ gdbsim_resume (pid, step, siggnal)
just as `wait' would. */
static int
-gdbsim_wait (status)
+gdbsim_wait (pid, status)
+ int pid;
WAITTYPE *status;
{
if (sr_get_debug ())
diff --git a/gdb/remote-udi.c b/gdb/remote-udi.c
index 2702326..bfcbea1 100644
--- a/gdb/remote-udi.c
+++ b/gdb/remote-udi.c
@@ -406,7 +406,8 @@ udi_resume (pid, step, sig)
storing status in STATUS just as `wait' would. */
static int
-udi_wait (status)
+udi_wait (pid, status)
+ int pid;
WAITTYPE *status;
{
UDIInt32 MaxTime;
diff --git a/gdb/remote-vx.c b/gdb/remote-vx.c
index cb67787..3aea4d1 100644
--- a/gdb/remote-vx.c
+++ b/gdb/remote-vx.c
@@ -583,6 +583,9 @@ vx_resume (pid, step, siggnal)
Rptrace ptrace_in;
Ptrace_return ptrace_out;
+ if (pid == -1)
+ pid = inferior_pid;
+
if (siggnal != 0 && siggnal != stop_signal)
error ("Cannot send signals to VxWorks processes");
@@ -855,7 +858,8 @@ sleep_ms (ms)
*/
static int
-vx_wait (status)
+vx_wait (pid, status)
+ int pid;
int *status;
{
register int pid;
diff --git a/gdb/remote-z8k.c b/gdb/remote-z8k.c
index f93a231..6c1b286 100644
--- a/gdb/remote-z8k.c
+++ b/gdb/remote-z8k.c
@@ -210,7 +210,8 @@ sim_detach (args, from_tty)
storing status in STATUS just as `wait' would. */
int
-sim_wait (status)
+sim_wait (pid, status)
+ int pid;
WAITTYPE *status;
{
*status = sim_stop_signal ();
diff --git a/gdb/thread.c b/gdb/thread.c
index fdc13bc..f14b41f 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -51,6 +51,8 @@ static void prune_threads PARAMS ((void));
static void thread_switch PARAMS ((int pid));
+static struct thread_info * find_thread_id PARAMS ((int num));
+
void
init_thread_list ()
{
@@ -97,6 +99,32 @@ find_thread_id (num)
}
int
+valid_thread_id (num)
+ int num;
+{
+ struct thread_info *tp;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->num == num)
+ return 1;
+
+ return 0;
+}
+
+int
+pid_to_thread_id (pid)
+ int pid;
+{
+ struct thread_info *tp;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->pid == pid)
+ return tp->num;
+
+ return 0;
+}
+
+int
in_thread_list (pid)
int pid;
{
diff --git a/gdb/thread.h b/gdb/thread.h
index 36b0035..2ec94fc 100644
--- a/gdb/thread.h
+++ b/gdb/thread.h
@@ -25,8 +25,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
extern void init_thread_list PARAMS ((void));
-extern void add_thread PARAMS ((int));
+extern void add_thread PARAMS ((int pid));
-extern int in_thread_list PARAMS ((int));
+extern int in_thread_list PARAMS ((int pid));
+
+extern int pid_to_thread_id PARAMS ((int pid));
+
+extern int valid_thread_id PARAMS ((int thread));
#endif /* THREAD_H */