From 25286543da71d927d59a7479e7e1bd0a1b9e1321 Mon Sep 17 00:00:00 2001 From: Stu Grossman Date: Mon, 2 Aug 1993 06:25:36 +0000 Subject: Sun Aug 1 22:58:18 1993 Stu Grossman (grossman at cygnus.com) * Makefile.in (CLIBS): Reorder to make Lynx ld happy. * (HFILES): New file thread.h. * (OBS): New file thread.c. * configure.in: Host config for Lynx/386. * fork-child.c (fork_inferior): Call init_thread_list(). * infrun.c (resume): Add pid to invocation of target_resume(). * (wait_for_inferior): Pay attention to pid from target_wait(). Multi-threading code now uses this to determine what to do. * inftarg.c (child_wait): Conditionalize based on CHILD_WAIT macro. Use target_pid_to_str() macro throughout when printing pid. * inferior.h (child_resume): Add pid to prototype. * hppab-nat.c hppah-nat.c infptrace.c (child_resume): Pass in pid as argument, instead of using inferior_pid. * procfs.c (procfs_resume): Pass in pid as argument. Ignored for now. Use target_pid_to_str() macro throughout for printing process id. * remote-adapt.c (adapt_resume): Pass in pid as argument. * remote-eb.c (eb_resume): Pass in pid as argument. * remote-es.c (es1800_resume): Pass in pid as argument. * remote-hms.c (hms_resume): Pass in pid as argument. * remote-mips.c (mips_resume): Pass in pid as argument. * remote-mm.c (mm_resume): Pass in pid as argument. * remote-monitor.c (monitor_resume): Pass in pid as argument. * remote-nindy.c (nindy_resume): Pass in pid as argument. * remote-sa.sparc.c (remote_resume): Pass in pid as argument. * remote-sim.c (rem_resume): Pass in pid as argument. * remote-sp64sim.c (simif_resume): Pass in pid as argument. * remote-st.c (st2000_resume): Pass in pid as argument. * remote-udi.c (udi_resume): Pass in pid as argument. * remote-vx.c (vx_resume): Pass in pid as argument. * remote-z8k.c (rem_resume): Pass in pid as argument. * remote.c (remote_resume): Pass in pid as argument. * solib.c (solid_create_inferior_hook): Pass inferior_pid to target_resume(). * target.c (normal_pid_to_str): New routine to print out process ID normally. * target.h (struct target_ops): Add pid to prototype at to_resume(). (target_resume): Add pid argument. * (target_pid_to_str): Default definition for normal type pids. * thread.c, thread.c: New modules for multi thread/process control. --- gdb/ChangeLog | 42 +++++++ gdb/Makefile.in | 10 +- gdb/configure.in | 3 +- gdb/fork-child.c | 2 + gdb/hppab-nat.c | 9 +- gdb/hppah-nat.c | 5 +- gdb/i386lynx-nat.c | 303 ++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/procfs.c | 30 ++--- gdb/remote-adapt.c | 4 +- gdb/remote-eb.c | 4 +- gdb/remote-es.c | 5 +- gdb/remote-hms.c | 4 +- gdb/remote-mips.c | 6 +- gdb/remote-mm.c | 4 +- gdb/remote-monitor.c | 4 +- gdb/remote-nindy.c | 4 +- gdb/remote-sa.sparc.c | 4 +- gdb/remote-sim.c | 2 +- gdb/remote-sp64sim.c | 4 +- gdb/remote-st.c | 4 +- gdb/remote-udi.c | 6 +- gdb/remote-vx.c | 5 +- gdb/remote-z8k.c | 3 +- gdb/thread.c | 233 ++++++++++++++++++++++++++++++++++++++ gdb/thread.h | 29 +++++ 25 files changed, 674 insertions(+), 55 deletions(-) create mode 100644 gdb/i386lynx-nat.c create mode 100644 gdb/thread.c create mode 100644 gdb/thread.h (limited to 'gdb') diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 379719a..4048467 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,45 @@ +Sun Aug 1 22:58:18 1993 Stu Grossman (grossman at cygnus.com) + + * Makefile.in (CLIBS): Reorder to make Lynx ld happy. + * (HFILES): New file thread.h. + * (OBS): New file thread.c. + * configure.in: Host config for Lynx/386. + * fork-child.c (fork_inferior): Call init_thread_list(). + * infrun.c (resume): Add pid to invocation of target_resume(). + * (wait_for_inferior): Pay attention to pid from target_wait(). + Multi-threading code now uses this to determine what to do. + * inftarg.c (child_wait): Conditionalize based on CHILD_WAIT macro. + Use target_pid_to_str() macro throughout when printing pid. + * inferior.h (child_resume): Add pid to prototype. + * hppab-nat.c hppah-nat.c infptrace.c (child_resume): Pass in pid as + argument, instead of using inferior_pid. + * procfs.c (procfs_resume): Pass in pid as argument. Ignored for + now. Use target_pid_to_str() macro throughout for printing process id. + * remote-adapt.c (adapt_resume): Pass in pid as argument. + * remote-eb.c (eb_resume): Pass in pid as argument. + * remote-es.c (es1800_resume): Pass in pid as argument. + * remote-hms.c (hms_resume): Pass in pid as argument. + * remote-mips.c (mips_resume): Pass in pid as argument. + * remote-mm.c (mm_resume): Pass in pid as argument. + * remote-monitor.c (monitor_resume): Pass in pid as argument. + * remote-nindy.c (nindy_resume): Pass in pid as argument. + * remote-sa.sparc.c (remote_resume): Pass in pid as argument. + * remote-sim.c (rem_resume): Pass in pid as argument. + * remote-sp64sim.c (simif_resume): Pass in pid as argument. + * remote-st.c (st2000_resume): Pass in pid as argument. + * remote-udi.c (udi_resume): Pass in pid as argument. + * remote-vx.c (vx_resume): Pass in pid as argument. + * remote-z8k.c (rem_resume): Pass in pid as argument. + * remote.c (remote_resume): Pass in pid as argument. + * solib.c (solid_create_inferior_hook): Pass inferior_pid to + target_resume(). + * target.c (normal_pid_to_str): New routine to print out process + ID normally. + * target.h (struct target_ops): Add pid to prototype at + to_resume(). (target_resume): Add pid argument. + * (target_pid_to_str): Default definition for normal type pids. + * thread.c, thread.c: New modules for multi thread/process control. + Sun Aug 1 13:02:42 1993 John Gilmore (gnu@cygnus.com) * README: Say that bug-gdb is also the place to send requests diff --git a/gdb/Makefile.in b/gdb/Makefile.in index be6f6bd..bdfdfd6 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -162,8 +162,8 @@ INTERNAL_CFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \ # you can use 'CLIBS=$(INSTALLED_LIBS)' 'CDEPS=' INSTALLED_LIBS=-lbfd -lreadline $(TERMCAP) -lopcodes -lmmalloc \ -liberty $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) -CLIBS = $(BFD) $(READLINE) $(TERMCAP) $(OPCODES) $(MMALLOC) \ - $(LIBIBERTY) $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) +CLIBS = $(BFD) $(READLINE) $(OPCODES) $(MMALLOC) \ + $(LIBIBERTY) $(TERMCAP) $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) \ $(BFD) $(READLINE) $(OPCODES) $(MMALLOC) $(LIBIBERTY) @@ -371,7 +371,7 @@ HFILES = buildsym.h call-cmds.h defs.h environ.h $(gdbcmd_h) \ nindy-share/env.h nindy-share/stop.h \ vx-share/dbgRpcLib.h vx-share/ptrace.h vx-share/vxTypes.h \ vx-share/vxWorks.h vx-share/wait.h vx-share/xdr_ld.h \ - vx-share/xdr_ptrace.h vx-share/xdr_rdb.h + vx-share/xdr_ptrace.h vx-share/xdr_rdb.h thread.h # GDB "info" files, which should be included in their entirety INFOFILES = gdb.info* @@ -401,7 +401,7 @@ TARFILES = $(SFILES) $(HFILES) $(NONSRC) $(ALLDEPFILES) $(ALLCONFIG) \ $(ALLPARAM) $(INFOFILES) $(POSSLIBS) $(REMOTE_EXAMPLES) -OBS = version.o main.o blockframe.o breakpoint.o findvar.o stack.o \ +OBS = version.o main.o blockframe.o breakpoint.o findvar.o stack.o thread.o \ source.o values.o eval.o valops.o valarith.o valprint.o printcmd.o \ symtab.o symfile.o symmisc.o infcmd.o infrun.o command.o \ utils.o expprint.o environ.o gdbtypes.o copying.o $(DEPFILES) \ @@ -1282,6 +1282,8 @@ tahoe-pinsn.o: tahoe-pinsn.c $(OP_INCLUDE)/tahoe.h $(defs_h) \ target.o: target.c $(bfd_h) $(defs_h) $(gdbcmd_h) $(inferior_h) \ objfiles.h symfile.h target.h +thread.o: thread.c $(defs_h) thread.h + typeprint.o: typeprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \ $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \ $(value_h) diff --git a/gdb/configure.in b/gdb/configure.in index 795dff0..55b651c 100644 --- a/gdb/configure.in +++ b/gdb/configure.in @@ -42,6 +42,7 @@ i[34]86-*-aix*) gdb_host=i386aix ;; i[34]86-*-bsd*) gdb_host=i386bsd ;; i[34]86-*-go32) gdb_host=go32 ;; i[34]86-*-linux) gdb_host=linux ;; +i[34]86-*-lynx*) gdb_host=i386lynx ;; i[34]86-*-mach) gdb_host=i386mach ;; i[34]86-*-sco3.2v4*) gdb_host=i386sco4 ;; i[34]86-*-sco*) gdb_host=i386sco ;; @@ -177,7 +178,7 @@ i[34]86-*-elf) gdb_target=i386v ;; i[34]86-*-aix*) gdb_target=i386aix ;; i[34]86-*-bsd*) gdb_target=i386bsd ;; i[34]86-*-go32) gdb_target=i386aout ;; -i[34]86-*-lynxos*) gdb_target=i386lynx +i[34]86-*-lynx*) gdb_target=i386lynx configdirs="${configdirs} gdbserver" ;; i[34]86-*-solaris*) gdb_target=i386sol2 ;; diff --git a/gdb/fork-child.c b/gdb/fork-child.c index 40f7680..8eade52 100644 --- a/gdb/fork-child.c +++ b/gdb/fork-child.c @@ -242,6 +242,8 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun) initialize anything target-vector-specific that needs initializing. */ (*init_trace_fun)(pid); + init_thread_list(); + #ifdef CREATE_INFERIOR_HOOK CREATE_INFERIOR_HOOK (pid); #endif diff --git a/gdb/hppab-nat.c b/gdb/hppab-nat.c index f86bfd0..42fe316 100644 --- a/gdb/hppab-nat.c +++ b/gdb/hppab-nat.c @@ -255,12 +255,13 @@ store_inferior_registers (regno) return; } -/* Resume execution of the inferior process. +/* Resume execution of process PID. If STEP is nonzero, single-step it. If SIGNAL is nonzero, give it that signal. */ void -child_resume (step, signal) +child_resume (pid, step, signal) + int pid; int step; int signal; { @@ -271,9 +272,9 @@ child_resume (step, signal) written a new PC value to the child.) */ if (step) - ptrace (PT_STEP, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal); + ptrace (PT_STEP, pid, (PTRACE_ARG3_TYPE) 1, signal); else - ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal); + ptrace (PT_CONTINUE, pid, (PTRACE_ARG3_TYPE) 1, signal); if (errno) perror_with_name ("ptrace"); diff --git a/gdb/hppah-nat.c b/gdb/hppah-nat.c index aadaf9d..6b37166 100644 --- a/gdb/hppah-nat.c +++ b/gdb/hppah-nat.c @@ -200,12 +200,13 @@ fetch_register (regno) error_exit:; } -/* Resume execution of the inferior process. +/* Resume execution of process PID. If STEP is nonzero, single-step it. If SIGNAL is nonzero, give it that signal. */ void -child_resume (step, signal) +child_resume (pid, step, signal) + int pid; int step; int signal; { diff --git a/gdb/i386lynx-nat.c b/gdb/i386lynx-nat.c new file mode 100644 index 0000000..c8922ad --- /dev/null +++ b/gdb/i386lynx-nat.c @@ -0,0 +1,303 @@ +/* Native-dependent code for Lynx running on i386's, for GDB. + Copyright 1988, 1989, 1991, 1992, 1993 Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "frame.h" +#include "inferior.h" +#include "gdbcore.h" +#include "target.h" + +#include +#include "/usr/include/sys/wait.h" + +/* these values indicate the offset of the named register in the econtext + structure */ + +#define EAX 10 +#define ECX 9 +#define EDX 8 +#define EBX 7 +#define ESP 16 +#define EBP 5 +#define ESI 4 +#define EDI 3 +#define EIP 13 +#define EFL 15 +#define CS 14 +#define SS 17 +#define DS 2 +#define ES 1 + +/* Currently these are not being used. So set them to 0 */ + +#define FS 0 +#define GS 0 + +/* this table must line up with REGISTER_NAMES in m-i386.h */ +static unsigned int regmap[] = +{ + EAX, ECX, EDX, EBX, + ESP, EBP, ESI, EDI, + EIP, EFL, CS, SS, + DS, ES, FS, GS, +}; + +/* Return the address in the core dump or inferior of register REGNO. + BLOCKEND is the address of the econtext structure */ + +static unsigned int +register_addr (regno, blockend) + int regno, blockend; +{ + if (regno < 0 || regno >= NUM_REGS) + error ("Invalid register number %d.", regno); + + return (blockend + regmap[regno] * sizeof (long)); +} + +/* Fetch one register. */ + +static void +fetch_register (regno, offset, bpid) + int regno, bpid; + unsigned int offset; +{ + unsigned int regaddr; + char buf[MAX_REGISTER_RAW_SIZE]; + char mess[128]; /* For messages */ + int i; + + regaddr = register_addr (regno, offset); + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) + { + errno = 0; + *(int *) &buf[i] = ptrace (PTRACE_PEEKTHREAD, bpid, + (PTRACE_ARG3_TYPE) regaddr, 0); + regaddr += sizeof (int); + if (errno != 0) + { + sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno); + perror_with_name (mess); + } + } + supply_register (regno, buf); +} + +/* Store our register values back into the inferior. + If REGNO is -1, do this for all registers. + Otherwise, REGNO specifies which register (so we can save time). */ + +static void +store_register (regno, offset, bpid) + int regno, bpid; + unsigned int offset; +{ + unsigned int regaddr; + char mess[128]; + extern char registers[]; + int i; + + regaddr = register_addr (regno, offset); + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) + { + errno = 0; + ptrace (PTRACE_POKEUSER, bpid, (PTRACE_ARG3_TYPE) regaddr, + *(int *) ®isters[REGISTER_BYTE (regno) + i]); + if (errno != 0) + { + sprintf (mess, "writing register number %d(%d)", regno, i); + perror_with_name (mess); + } + regaddr += sizeof(int); + } +} + +/* return an offset for use with register_addr() */ + +static unsigned int +fetch_offset (pid) + int pid; +{ + struct st_entry s; + unsigned int specpage_off, offset = (char *) &s.ecp - (char *) &s; + + errno = 0; + specpage_off = ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE) 0, 0); + if (errno != 0) + perror_with_name ("ptrace"); + errno = 0; + offset = ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE) offset, 0) + - specpage_off; + if (errno != 0) + perror_with_name ("ptrace"); + return offset; +} + +/* Fetch all registers, or just one, from the child process. */ + +void +fetch_inferior_registers (regno) + int regno; +{ + unsigned int offset = fetch_offset (inferior_pid); + + if (regno == -1) + { + for (regno = 0; regno < NUM_REGS; regno++) + fetch_register (regno, offset, inferior_pid); + } + else + fetch_register (regno, offset, inferior_pid); +} + +/* Store all registers, or just one, to the child process. */ + +void +store_inferior_registers (regno) + int regno; +{ + unsigned int offset = fetch_offset (inferior_pid); + + if (regno == -1) + { + for (regno = 0; regno < NUM_REGS; regno++) + store_register (regno, offset, inferior_pid); + } + else + store_register (regno, offset, inferior_pid); +} + +/* Extract the register values out of the core file and store + them where `read_register' will find them. + + CORE_REG_SECT points to the register values themselves, read into memory. + CORE_REG_SIZE is the size of that area. + WHICH says which set of registers we are handling (0 = int, 2 = float + on machines where they are discontiguous). + REG_ADDR is the offset from u.u_ar0 to the register values relative to + core_reg_sect. This is used with old-fashioned core files to + locate the registers in a large upage-plus-stack ".reg" section. + Original upage address X is at location core_reg_sect+x+reg_addr. + */ + +void +fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) + char *core_reg_sect; + unsigned core_reg_size; + int which; + unsigned reg_addr; +{ + struct st_entry s; + unsigned int regno, addr; + + for (regno = 0; regno < NUM_REGS; regno++) + { + addr = register_addr (regno, (char *) &s.ec - (char *) &s); + supply_register (regno, core_reg_sect + addr); + } +} + +/* Wait for child to do something. Return pid of child, or -1 in case + of error; store status through argument pointer STATUS. */ + +int +child_wait (status) + int *status; +{ + int pid; + int save_errno; + int thread; + + while (1) + { + int sig; + + if (attach_flag) + set_sigint_trap(); /* Causes SIGINT to be passed on to the + attached process. */ + pid = wait (status); + save_errno = errno; + + if (attach_flag) + clear_sigint_trap(); + + if (pid == -1) + { + 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; + } + + if (pid != PIDGET (inferior_pid)) /* Some other process?!? */ + continue; + +/* thread = WIFTID (*status);*/ + thread = *status >> 16; + + /* Initial thread value can only be acquired via wait, so we have to + resort to this hack. */ + + if (TIDGET (inferior_pid) == 0) + { + inferior_pid = BUILDPID (inferior_pid, thread); + add_thread (inferior_pid); + } + + pid = BUILDPID (pid, thread); + + return pid; + } +} + +/* Return the PC of the caller from the call frame. Assumes the subr prologue + has already been executed, and the frame pointer setup. If this is the + outermost frame, we check to see if we are in a system call by examining the + previous instruction. If so, then the return PC is actually at SP+4 because + system calls use a different calling sequence. */ + +CORE_ADDR +i386lynx_saved_pc_after_call (frame) + struct frame_info *frame; +{ + char opcode[7]; + static const char call_inst[] = {0x9a, 0, 0, 0, 0, 8, 0}; /* lcall 0x8,0x0 */ + + read_memory (frame->pc - 7, opcode, 7); + if (memcmp (opcode, call_inst, 7) == 0) + return read_memory_integer (read_register (SP_REGNUM) + 4, 4); + + return read_memory_integer (read_register (SP_REGNUM), 4); +} + +/* Convert a Lynx process ID to a string. Returns the string in a static + buffer. */ + +char * +i386lynx_pid_to_str (pid) + int pid; +{ + static char buf[40]; + + sprintf (buf, "process %d thread %d", PIDGET (pid), TIDGET (pid)); + + return buf; +} diff --git a/gdb/procfs.c b/gdb/procfs.c index 72a9c69..4c8ab5c 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -1599,9 +1599,9 @@ procfs_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); } @@ -1632,8 +1632,8 @@ procfs_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) @@ -1664,8 +1664,8 @@ static void procfs_files_info (ignore) struct target_ops *ignore; { - printf ("\tUsing the running image of %s process %d via /proc.\n", - attach_flag? "attached": "child", inferior_pid); + printf ("\tUsing the running image of %s %s via /proc.\n", + attach_flag? "attached": "child", target_pid_to_str (inferior_pid)); } /* ARGSUSED */ @@ -1761,7 +1761,7 @@ do_attach (pid) } else { - printf ("Ok, gdb will wait for process %u to stop.\n", pid); + printf ("Ok, gdb will wait for %s to stop.\n", target_pid_to_str (pid)); } } @@ -2150,12 +2150,13 @@ set_proc_siginfo (pip, signo) } } -/* Resume execution of the inferior process. If STEP is nozero, then +/* Resume execution of process PID. If STEP is nozero, then just single step it. If SIGNAL is nonzero, restart it with that signal activated. */ static void -procfs_resume (step, signo) +procfs_resume (pid, step, signo) + int pid; int step; int signo; { @@ -2552,7 +2553,8 @@ info_proc_siginfo (pip, summary) } if (sip -> si_code <= 0) { - printf_filtered ("sent by pid %d, uid %d ", sip -> si_pid, + printf_filtered ("sent by %s, uid %d ", + target_pid_to_str (sip -> si_pid), sip -> si_uid); } else @@ -2567,8 +2569,8 @@ info_proc_siginfo (pip, summary) } else if ((sip -> si_signo == SIGCHLD)) { - printf_filtered ("child pid %u, status %u ", - sip -> si_pid, + printf_filtered ("child %s, status %u ", + target_pid_to_str (sip -> si_pid), sip -> si_status); } else if ((sip -> si_signo == SIGPOLL)) @@ -2590,7 +2592,7 @@ info_proc_siginfo (pip, summary) } if (sip -> si_code <= 0) { - printf_filtered ("\t%-16u %s\n", sip -> si_pid, + printf_filtered ("\t%-16u %s\n", sip -> si_pid, /* XXX need target_pid_to_str() */ "PID of process sending signal"); printf_filtered ("\t%-16u %s\n", sip -> si_uid, "UID of process sending signal"); @@ -2613,7 +2615,7 @@ info_proc_siginfo (pip, summary) } else if ((sip -> si_signo == SIGCHLD)) { - printf_filtered ("\t%-16u %s.\n", sip -> si_pid, + printf_filtered ("\t%-16u %s.\n", sip -> si_pid, /* XXX need target_pid_to_str() */ "Child process ID"); printf_filtered ("\t%-16u %s.\n", sip -> si_status, "Child process exit value or signal"); diff --git a/gdb/remote-adapt.c b/gdb/remote-adapt.c index cfc94e7..390466d 100644 --- a/gdb/remote-adapt.c +++ b/gdb/remote-adapt.c @@ -675,8 +675,8 @@ adapt_detach (args,from_tty) /* Tell the remote machine to resume. */ void -adapt_resume (step, sig) - int step, sig; +adapt_resume (pid, step, sig) + int pid, step, sig; { if (step) { diff --git a/gdb/remote-eb.c b/gdb/remote-eb.c index 6e36b7e..049e87a 100644 --- a/gdb/remote-eb.c +++ b/gdb/remote-eb.c @@ -479,8 +479,8 @@ eb_detach (from_tty) /* Tell the remote machine to resume. */ void -eb_resume (step, sig) - int step, sig; +eb_resume (pid, step, sig) + int pid, step, sig; { if (step) { diff --git a/gdb/remote-es.c b/gdb/remote-es.c index 1c442d5..f61c1eb 100644 --- a/gdb/remote-es.c +++ b/gdb/remote-es.c @@ -161,7 +161,7 @@ static int es1800_wait PARAMS ((WAITTYPE *)); static void -es1800_resume PARAMS ((int, int)); +es1800_resume PARAMS ((int, int, int)); static void es1800_detach PARAMS ((char *, int)); @@ -650,7 +650,8 @@ es1800_detach (args, from_tty) siggnal - the signal value to be given to the target (0 = no signal) */ static void -es1800_resume (step, siggnal) +es1800_resume (pid, step, siggnal) + int pid; int step; int siggnal; { diff --git a/gdb/remote-hms.c b/gdb/remote-hms.c index 4546310..92cab9a 100644 --- a/gdb/remote-hms.c +++ b/gdb/remote-hms.c @@ -638,8 +638,8 @@ hms_detach (args, from_tty) /* Tell the remote machine to resume. */ void -hms_resume (step, sig) - int step, sig; +hms_resume (pid, step, sig) + int pid, step, sig; { dcache_flush (); diff --git a/gdb/remote-mips.c b/gdb/remote-mips.c index 3cf3b60..d4cfcda 100644 --- a/gdb/remote-mips.c +++ b/gdb/remote-mips.c @@ -71,7 +71,7 @@ static void mips_detach PARAMS ((char *args, int from_tty)); static void -mips_resume PARAMS ((int step, int siggnal)); +mips_resume PARAMS ((int pid, int step, int siggnal)); static int mips_wait PARAMS ((WAITTYPE *status)); @@ -957,8 +957,8 @@ mips_detach (args, from_tty) from the board. */ static void -mips_resume (step, siggnal) - int step, siggnal; +mips_resume (pid, step, siggnal) + int pid, step, siggnal; { if (siggnal) error ("Can't send signals to a remote system. Try `handle %d ignore'.", diff --git a/gdb/remote-mm.c b/gdb/remote-mm.c index dc751c2..58a4653 100644 --- a/gdb/remote-mm.c +++ b/gdb/remote-mm.c @@ -498,8 +498,8 @@ mm_detach (args,from_tty) ** Tell the remote machine to resume. */ static void -mm_resume (step, sig) - int step, sig; +mm_resume (pid, step, sig) + int pid, step, sig; { if (sig) error ("Can't send signals to a remote MiniMon system."); diff --git a/gdb/remote-monitor.c b/gdb/remote-monitor.c index 41f87c1..eb3d63c 100644 --- a/gdb/remote-monitor.c +++ b/gdb/remote-monitor.c @@ -436,8 +436,8 @@ monitor_detach (from_tty) * _resume -- Tell the remote machine to resume. */ static void -monitor_resume (step, sig) - int step, sig; +monitor_resume (pid, step, sig) + int pid, step, sig; { #ifdef LOG_FILE fprintf (log_file, "\nIn Resume (step=%d, sig=%d)\n", step, sig); diff --git a/gdb/remote-nindy.c b/gdb/remote-nindy.c index dd027bf..8dfc40f 100644 --- a/gdb/remote-nindy.c +++ b/gdb/remote-nindy.c @@ -257,8 +257,8 @@ non_dle( buf, n ) /* Tell the remote machine to resume. */ void -nindy_resume (step, siggnal) - int step, siggnal; +nindy_resume (pid, step, siggnal) + int pid, step, siggnal; { if (siggnal != 0 && siggnal != stop_signal) error ("Can't send signals to remote NINDY targets."); diff --git a/gdb/remote-sa.sparc.c b/gdb/remote-sa.sparc.c index 6dae0c9..1880ba3 100644 --- a/gdb/remote-sa.sparc.c +++ b/gdb/remote-sa.sparc.c @@ -201,8 +201,8 @@ extern int one_stepped; /* From machine dependent code */ static int remote_set_one_stepped; int -remote_resume (step, signal) - int step, signal; +remote_resume (pid, step, signal) + int pid, step, signal; { if (step) { diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c index 313c484..005515d 100644 --- a/gdb/remote-sim.c +++ b/gdb/remote-sim.c @@ -242,7 +242,7 @@ sim_before_main_loop () } -static void rem_resume(a,b) +static void rem_resume(pid, a , b) { sim_resume(a,b); } diff --git a/gdb/remote-sp64sim.c b/gdb/remote-sp64sim.c index e975c74..ced255d 100644 --- a/gdb/remote-sp64sim.c +++ b/gdb/remote-sp64sim.c @@ -311,8 +311,8 @@ simif_detach (args,from_tty) to the target, or zero for no signal. */ static void -simif_resume (step, siggnal) - int step, siggnal; +simif_resume (pid, step, siggnal) + int pid, step, siggnal; { if (sim_verbose) printf_filtered ("simif_resume: step %d, signal %d\n", step, siggnal); diff --git a/gdb/remote-st.c b/gdb/remote-st.c index 833aa20..aa1b7cd 100644 --- a/gdb/remote-st.c +++ b/gdb/remote-st.c @@ -358,8 +358,8 @@ st2000_detach (from_tty) /* Tell the remote machine to resume. */ static void -st2000_resume (step, sig) - int step, sig; +st2000_resume (pid, step, sig) + int pid, step, sig; { if (step) { diff --git a/gdb/remote-udi.c b/gdb/remote-udi.c index edb42f7..b796e90 100644 --- a/gdb/remote-udi.c +++ b/gdb/remote-udi.c @@ -52,7 +52,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ static int kiodebug; extern int stop_soon_quietly; /* for wait_for_inferior */ extern struct value *call_function_by_hand(); -static void udi_resume PARAMS ((int step, int sig)); +static void udi_resume PARAMS ((int pid, int step, int sig)); static void udi_fetch_registers PARAMS ((int regno)); static void udi_load PARAMS ((char *args, int from_tty)); static void fetch_register PARAMS ((int regno)); @@ -403,8 +403,8 @@ udi_detach (args,from_tty) ** Tell the remote machine to resume. */ static void -udi_resume (step, sig) - int step, sig; +udi_resume (pid, step, sig) + int pid, step, sig; { UDIError tip_error; UDIUInt32 Steps = 1; diff --git a/gdb/remote-vx.c b/gdb/remote-vx.c index ad5dc90..6824f80 100644 --- a/gdb/remote-vx.c +++ b/gdb/remote-vx.c @@ -578,7 +578,8 @@ vx_run_files_info () } static void -vx_resume (step, siggnal) +vx_resume (pid, step, siggnal) + int pid; int step; int siggnal; { @@ -592,7 +593,7 @@ vx_resume (step, siggnal) bzero ((char *) &ptrace_in, sizeof (ptrace_in)); bzero ((char *) &ptrace_out, sizeof (ptrace_out)); - ptrace_in.pid = inferior_pid; + ptrace_in.pid = pid; ptrace_in.addr = 1; /* Target side insists on this, or it panics. */ /* XXX change second param to be a proc number */ diff --git a/gdb/remote-z8k.c b/gdb/remote-z8k.c index 16fc73a..f93a231 100644 --- a/gdb/remote-z8k.c +++ b/gdb/remote-z8k.c @@ -310,7 +310,8 @@ sim_mourn () } static void -rem_resume (a, b) +rem_resume (pid, a, b) + int pid; int a; int b; { diff --git a/gdb/thread.c b/gdb/thread.c new file mode 100644 index 0000000..6e7c126 --- /dev/null +++ b/gdb/thread.c @@ -0,0 +1,233 @@ +/* for separate threads within the inferior process, for GDB. + Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + +GDB is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY. No author or distributor accepts responsibility to anyone +for the consequences of using it or for whether it serves any +particular purpose or works at all, unless he says so in writing. +Refer to the GDB General Public License for full details. + +Everyone is granted permission to copy, modify and redistribute GDB, +but only under the conditions described in the GDB General Public +License. A copy of this license is supposed to have been given to you +along with GDB so you can know your rights and responsibilities. It +should be in a file named COPYING. Among other things, the copyright +notice and this notice must be preserved on all copies. + +In other words, go ahead and share GDB, but don't try to stop +anyone else from sharing it farther. Help stamp out software hoarding! +*/ + +#include "defs.h" +#include "symtab.h" +#include "frame.h" +#include "inferior.h" +#include "environ.h" +#include "value.h" +#include "target.h" +#include "thread.h" + +#include +#include + +/*#include "lynxos-core.h"*/ + +struct thread_info +{ + struct thread_info *next; + int pid; /* Actual process id */ + int num; /* Convenient handle */ +}; + +static struct thread_info *thread_list = NULL; +static int highest_thread_num; + +static void thread_info PARAMS ((void)); + +static void thread_command PARAMS ((char * tidstr, int from_tty)); + +static void prune_threads PARAMS ((void)); + +static void thread_switch PARAMS ((int pid)); + +void +init_thread_list () +{ + struct thread_info *tp, *tpnext; + + if (!thread_list) + return; + + for (tp = thread_list; tp; tp = tpnext) + { + tpnext = tp->next; + free (tp); + } + + thread_list = NULL; + highest_thread_num = 0; +} + +void +add_thread (pid) + int pid; +{ + struct thread_info *tp; + + tp = xmalloc (sizeof (struct thread_info)); + + tp->pid = pid; + tp->num = ++highest_thread_num; + tp->next = thread_list; + thread_list = tp; +} + +static struct thread_info * +find_thread_id (num) + int num; +{ + struct thread_info *tp; + + for (tp = thread_list; tp; tp = tp->next) + if (tp->num == num) + return tp; + + return NULL; +} + +int +in_thread_list (pid) + int pid; +{ + struct thread_info *tp; + + for (tp = thread_list; tp; tp = tp->next) + if (tp->pid == pid) + return 1; + + return 0; /* Never heard of 'im */ +} + +#if 0 +void +bfd_get_core_threads (abfd) + bfd *abfd; +{ + int i; + + inferior_pid = BUILDPID (inferior_pid, core_thread (abfd)->pid); + for (i = 0; i < core_pss (abfd).threadcnt; i++) + add_thread (core_thread (abfd)[i].pid); +} +#endif + +static void +prune_threads () +{ + struct thread_info *tp, *tpprev; + + tpprev = 0; + + for (tp = thread_list; tp; tp = tp->next) + if (tp->pid == -1) + { + if (tpprev) + tpprev->next = tp->next; + else + thread_list = NULL; + + free (tp); + } + else + tpprev = tp; +} + +/* Print information about currently known threads */ + +static void +info_threads_command (arg, from_tty) + char *arg; + int from_tty; +{ + struct thread_info *tp; + int current_pid = inferior_pid; + + for (tp = thread_list; tp; tp = tp->next) + { + if (target_has_execution + && kill (tp->pid, 0) == -1) + { + tp->pid == -1; /* Mark it as dead */ + continue; + } + + if (tp->pid == current_pid) + printf_filtered ("* "); + else + printf_filtered (" "); + + printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid)); + + thread_switch (tp->pid); + print_stack_frame (selected_frame, -1, 0); + } + + thread_switch (current_pid); + prune_threads (); +} + +/* Switch from one thread to another. */ + +void +thread_switch (pid) + int pid; +{ + if (pid == inferior_pid) + return; + + inferior_pid = pid; + pc_changed = 0; + flush_cached_frames (); + registers_changed (); + stop_pc = read_pc(); + set_current_frame (create_new_frame (read_fp (), stop_pc)); + stop_frame_address = FRAME_FP (get_current_frame ()); + select_frame (get_current_frame (), 0); +} + +static void +thread_command (tidstr, from_tty) + char *tidstr; + int from_tty; +{ + int num; + struct thread_info *tp; + + if (!tidstr) + error ("Please specify a thread ID. Use the \"info threads\" command to\n\ +see the IDs of currently known threads."); + + + num = atoi (tidstr); + + tp = find_thread_id (num); + + if (!tp) + error ("Thread ID %d not known. Use the \"info threads\" command to\n\ +see the IDs of currently known threads.", num); + + thread_switch (tp->pid); + + printf_filtered ("[Switching to %s]\n", target_pid_to_str (inferior_pid)); + print_stack_frame (selected_frame, selected_frame_level, 1); +} + +void +_initialize_thread () +{ + add_info ("threads", info_threads_command, + "IDs of currently known threads."); + add_com ("thread", class_info, thread_command, + "Use this command to switch between threads.\n\ +The new thread ID must be currently known."); +} diff --git a/gdb/thread.h b/gdb/thread.h new file mode 100644 index 0000000..578fdaa --- /dev/null +++ b/gdb/thread.h @@ -0,0 +1,29 @@ +/************************************************************ +(C) Copyright 1987-1992 +Lynx Real-Time Systems, Inc. +Los Gatos, CA +All rights reserved. + +$Date$ +$Revision$ + +************************************************************/ + +#ifndef THREAD_H +#define THREAD_H + +extern void init_thread_list PARAMS ((void)); + +extern void add_thread PARAMS ((int)); + +extern int in_thread_list PARAMS ((int)); + +#if 0 +#ifdef __STDC__ +struct _bfd; +#endif + +extern void bfd_get_core_threads PARAMS ((struct _bfd *)); +#endif + +#endif /* THREAD_H */ -- cgit v1.1