diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 47 | ||||
-rw-r--r-- | gdb/proc-api.c | 11 | ||||
-rw-r--r-- | gdb/proc-events.c | 4 | ||||
-rw-r--r-- | gdb/proc-utils.h | 8 | ||||
-rw-r--r-- | gdb/procfs.c | 995 |
5 files changed, 775 insertions, 290 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e880aeb..23b7de5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,52 @@ 2001-03-26 Kevin Buettner <kevinb@redhat.com> + * proc-utils.h (procfs_ctl_t): New typedef. + * proc-api.c (write_with_trace): Change type of ``opcode'' from + long to procfs_ctl_t. Don't assume that the target has defined + BREAKPOINT. Handle case in which PCRESET is the same as PCUNSET. + * proc-events.c (sys/syscall.h, sys/fault.h): Include conditionally. + * procfs.c (sys/fault.h, sys/syscall.h): Include conditionally. + (gdb_sigset_t, gdb_sigaction_t, gdb_siginfo_t, gdb_premptysysset) + (gdb_praddsysset, gdb_prdelsysset, gdb_pr_issyssetmember): + Conditionally define as appropriate for AIX/non-AIX systems. Use + these defines/typedefs as appropriate elsewhere in file. + (struct procinfo): Change type of saved_sigset and saved_sighold + from sigset_t to gdb_sigset_t. Make saved_exitset and + saved_entryset pointer variables. Add two new fields, num_syscalls + and syscall_names. + (DYNAMIC_SYSCALLS): Define when HAVE_PRSYSENT_T is defined. + (sysset_t_size, sysset_t_alloc): New functions. + (load_syscalls, free_syscalls, find_syscall): New functions for + platforms which define DYNAMIC_SYSCALLS. + (create_procinfo): Call load_syscalls. + (destroy_one_procinfo): Call free_syscalls. + (GDBRESET): Don't define twice. + (proc_modify_flag): Change type of operation code array `arg' + from long to procfs_ctl_t. + (proc_stop_process, proc_wait_for_stop, proc_run_process) + (proc_set_traced_signals, proc_set_traced_faults) + (proc_set_traced_sysentry, proc_set_traced_sysexit) + (proc_set_held_signals, proc_clear_current_fault) + (proc_set_current_signal, proc_clear_current_signal, proc_set_gregs) + (proc_set_fpregs, proc_kill, proc_set_watchpoint): Likewise for `cmd'. + (proc_set_traced_sysentry): Dynamically allocate variable sized + struct gdb_proc_ctl_pcsentry. Also, free it at function exit. + (proc_set_traced_sysexit): Dynamically allocate variable + sized struct gdb_proc_ctl_pcsexit. Also, free it at + function exit. + (proc_get_traced_sysentry, proc_get_traced_sysexit): Add new code + for reading the sysset_t struct on AIX5. + (procfs_debug_inferior): Don't assume that SYS_exit will be + defined. Add new code for finding certain syscalls on AIX5. + (syscall_is_lwp_exit, syscall_is_exit, syscall_is_exec) + (syscall_is_lwp_create): New functions. + (procfs_wait): Restructured code which checks for certain + system calls to use the new syscall_is_... functions. + (procfs_notice_signals): Account for the fact that saved_entryset + and saved_exitset in struct procinfo are now pointers. + +2001-03-26 Kevin Buettner <kevinb@redhat.com> + * symtab.c (find_pc_sect_line): Revise method used for finding the ending pc. diff --git a/gdb/proc-api.c b/gdb/proc-api.c index c7da71f..d881edc 100644 --- a/gdb/proc-api.c +++ b/gdb/proc-api.c @@ -446,12 +446,12 @@ write_with_trace (int fd, void *varg, size_t len, char *file, int line) { int i; int ret; - long *arg = (long *) varg; + procfs_ctl_t *arg = (procfs_ctl_t *) varg; prepare_to_trace (); if (procfs_trace) { - long opcode = arg[0]; + procfs_ctl_t opcode = arg[0]; for (i = 0; rw_table[i].name != NULL; i++) if (rw_table[i].value == opcode) break; @@ -475,8 +475,10 @@ write_with_trace (int fd, void *varg, size_t len, char *file, int line) case PCUNSET: #endif #ifdef PCRESET +#if PCRESET != PCUNSET case PCRESET: #endif +#endif fprintf (procfs_file ? procfs_file : stdout, "write (PCRESET, %s) %s\n", arg[1] == PR_FORK ? "PR_FORK" : @@ -551,6 +553,7 @@ write_with_trace (int fd, void *varg, size_t len, char *file, int line) break; default: { +#ifdef BREAKPOINT static unsigned char break_insn[] = BREAKPOINT; if (len == sizeof (break_insn) && @@ -558,7 +561,9 @@ write_with_trace (int fd, void *varg, size_t len, char *file, int line) fprintf (procfs_file ? procfs_file : stdout, "write (<breakpoint at 0x%08lx>) \n", (unsigned long) lseek_offset); - else if (rw_table[i].name) + else +#endif + if (rw_table[i].name) fprintf (procfs_file ? procfs_file : stdout, "write (%s) %s\n", rw_table[i].name, diff --git a/gdb/proc-events.c b/gdb/proc-events.c index 1e7ab93..5365fef 100644 --- a/gdb/proc-events.c +++ b/gdb/proc-events.c @@ -40,8 +40,12 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <stdio.h> #include <sys/types.h> #include <sys/procfs.h> +#ifdef HAVE_SYS_SYSCALL_H #include <sys/syscall.h> +#endif +#ifdef HAVE_SYS_FAULT_H #include <sys/fault.h> +#endif /* Much of the information used in the /proc interface, particularly for printing status information, is kept as tables of structures of the diff --git a/gdb/proc-utils.h b/gdb/proc-utils.h index 06c1efd..1c41964 100644 --- a/gdb/proc-utils.h +++ b/gdb/proc-utils.h @@ -92,3 +92,11 @@ extern void procfs_note (char *, char *, int); #define PROCFS_NOTE(X) procfs_note (X, __FILE__, __LINE__) #define PROC_PRETTYFPRINT_STATUS(X,Y,Z,T) \ proc_prettyfprint_status (X, Y, Z, T) + +/* Define the type (and more importantly the width) of the control + word used to write to the /proc/PID/ctl file. */ +#if defined (PROC_CTL_WORD_TYPE) +typedef PROC_CTL_WORD_TYPE procfs_ctl_t; +#else +typedef long procfs_ctl_t; +#endif diff --git a/gdb/procfs.c b/gdb/procfs.c index 94439e3..a899dac 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -31,8 +31,12 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #endif #include <sys/procfs.h> +#ifdef HAVE_SYS_FAULT_H #include <sys/fault.h> +#endif +#ifdef HAVE_SYS_SYSCALL_H #include <sys/syscall.h> +#endif #include <sys/errno.h> #include <sys/wait.h> #include <signal.h> @@ -49,6 +53,7 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ * Solaris * OSF * Unixware + * AIX5 * * /proc works by immitating a file system: you open a simulated file * that represents the process you wish to interact with, and @@ -180,7 +185,7 @@ init_procfs_ops (void) */ #ifdef NEW_PROC_API /* Solaris 7 && 8 method for watchpoints */ -#ifndef UNIXWARE +#ifdef WA_READ enum { READ_WATCHFLAG = WA_READ, WRITE_WATCHFLAG = WA_WRITE, EXEC_WATCHFLAG = WA_EXEC, @@ -195,6 +200,69 @@ init_procfs_ops (void) }; #endif +/* gdb_sigset_t */ +#ifdef HAVE_PR_SIGSET_T +typedef pr_sigset_t gdb_sigset_t; +#else +typedef sigset_t gdb_sigset_t; +#endif + +/* sigaction */ +#ifdef HAVE_PR_SIGACTION64_T +typedef pr_sigaction64_t gdb_sigaction_t; +#else +typedef struct sigaction gdb_sigaction_t; +#endif + +/* siginfo */ +#ifdef HAVE_PR_SIGINFO64_T +typedef pr_siginfo64_t gdb_siginfo_t; +#else +typedef struct siginfo gdb_siginfo_t; +#endif + +/* gdb_premptysysset */ +#ifdef premptysysset +#define gdb_premptysysset premptysysset +#else +#define gdb_premptysysset premptyset +#endif + +/* praddsysset */ +#ifdef praddsysset +#define gdb_praddsysset praddsysset +#else +#define gdb_praddsysset praddset +#endif + +/* prdelsysset */ +#ifdef prdelsysset +#define gdb_prdelsysset prdelsysset +#else +#define gdb_prdelsysset prdelset +#endif + +/* prissyssetmember */ +#ifdef prissyssetmember +#define gdb_pr_issyssetmember prissyssetmember +#else +#define gdb_pr_issyssetmember prismember +#endif + +/* As a feature test, saying ``#if HAVE_PRSYSENT_T'' everywhere isn't + as intuitively descriptive as it could be, so we'll define + DYNAMIC_SYSCALLS to mean the same thing. Anyway, at the time of + this writing, this feature is only found on AIX5 systems and + basically means that the set of syscalls is not fixed. I.e, + there's no nice table that one can #include to get all of the + syscall numbers. Instead, they're stored in /proc/PID/sysent + for each process. We are at least guaranteed that they won't + change over the lifetime of the process. But each process could + (in theory) have different syscall numbers. +*/ +#ifdef HAVE_PRSYSENT_T +#define DYNAMIC_SYSCALLS +#endif @@ -247,6 +315,7 @@ typedef prstatus_t gdb_prstatus_t; typedef prstatus_t gdb_lwpstatus_t; #endif /* NEW_PROC_API */ + /* Provide default composite pid manipulation macros for systems that don't have threads. */ @@ -285,16 +354,21 @@ typedef struct procinfo { char pathname[MAX_PROC_NAME_SIZE]; /* Pathname to /proc entry */ fltset_t saved_fltset; /* Saved traced hardware fault set */ - sigset_t saved_sigset; /* Saved traced signal set */ - sigset_t saved_sighold; /* Saved held signal set */ - sysset_t saved_exitset; /* Saved traced system call exit set */ - sysset_t saved_entryset; /* Saved traced system call entry set */ + gdb_sigset_t saved_sigset; /* Saved traced signal set */ + gdb_sigset_t saved_sighold; /* Saved held signal set */ + sysset_t *saved_exitset; /* Saved traced system call exit set */ + sysset_t *saved_entryset; /* Saved traced system call entry set */ gdb_prstatus_t prstatus; /* Current process status info */ #ifndef NEW_PROC_API gdb_fpregset_t fpregset; /* Current floating point registers */ #endif + +#ifdef DYNAMIC_SYSCALLS + int num_syscalls; /* Total number of syscalls */ + char **syscall_names; /* Syscall number to name map */ +#endif struct procinfo *thread_list; @@ -316,6 +390,13 @@ static void do_destroy_procinfo_cleanup (void *); static void dead_procinfo (procinfo * p, char *msg, int killp); static int open_procinfo_files (procinfo * p, int which); static void close_procinfo_files (procinfo * p); +static int sysset_t_size (procinfo *p); +static sysset_t *sysset_t_alloc (procinfo * pi); +#ifdef DYNAMIC_SYSCALLS +static void load_syscalls (procinfo *pi); +static void free_syscalls (procinfo *pi); +static int find_syscall (procinfo *pi, char *name); +#endif /* DYNAMIC_SYSCALLS */ /* The head of the procinfo list: */ static procinfo * procinfo_list; @@ -566,6 +647,10 @@ create_procinfo (int pid, int tid) pi->pid = pid; pi->tid = tid; +#ifdef DYNAMIC_SYSCALLS + load_syscalls (pi); +#endif + /* Chain into list. */ if (tid == 0) { @@ -632,6 +717,9 @@ destroy_one_procinfo (procinfo **list, procinfo *pi) close_procinfo_files (pi); /* Step three: free the memory. */ +#ifdef DYNAMIC_SYSCALLS + free_syscalls (pi); +#endif xfree (pi); } @@ -692,6 +780,190 @@ dead_procinfo (procinfo *pi, char *msg, int kill_p) error (msg); } +/* + * Function: sysset_t_size + * + * Returns the (complete) size of a sysset_t struct. Normally, this + * is just sizeof (syset_t), but in the case of Monterey/64, the actual + * size of sysset_t isn't known until runtime. + */ + +static int +sysset_t_size (procinfo * pi) +{ +#ifndef DYNAMIC_SYSCALLS + return sizeof (sysset_t); +#else + return sizeof (sysset_t) - sizeof (uint64_t) + + sizeof (uint64_t) * ((pi->num_syscalls + (8 * sizeof (uint64_t) - 1)) + / (8 * sizeof (uint64_t))); +#endif +} + +/* Function: sysset_t_alloc + + Allocate and (partially) initialize a sysset_t struct. */ + +static sysset_t * +sysset_t_alloc (procinfo * pi) +{ + sysset_t *ret; + int size = sysset_t_size (pi); + ret = xmalloc (size); +#ifdef DYNAMIC_SYSCALLS + ret->pr_size = (pi->num_syscalls + (8 * sizeof (uint64_t) - 1)) + / (8 * sizeof (uint64_t)); +#endif + return ret; +} + +#ifdef DYNAMIC_SYSCALLS + +/* Function: load_syscalls + + Extract syscall numbers and names from /proc/<pid>/sysent. Initialize + pi->num_syscalls with the number of syscalls and pi->syscall_names + with the names. (Certain numbers may be skipped in which case the + names for these numbers will be left as NULL.) */ + +#define MAX_SYSCALL_NAME_LENGTH 256 +#define MAX_SYSCALLS 65536 + +static void +load_syscalls (procinfo *pi) +{ + char pathname[MAX_PROC_NAME_SIZE]; + int sysent_fd; + prsysent_t header; + prsyscall_t *syscalls; + int i, size, maxcall; + + pi->num_syscalls = 0; + pi->syscall_names = 0; + + /* Open the file descriptor for the sysent file */ + sprintf (pathname, "/proc/%d/sysent", pi->pid); + sysent_fd = open (pathname, O_RDONLY); + if (sysent_fd < 0) + { + error ("load_syscalls: Can't open /proc/%d/sysent", pi->pid); + } + + size = sizeof header - sizeof (prsyscall_t); + if (read (sysent_fd, &header, size) != size) + { + error ("load_syscalls: Error reading /proc/%d/sysent", pi->pid); + } + + if (header.pr_nsyscalls == 0) + { + error ("load_syscalls: /proc/%d/sysent contains no syscalls!", pi->pid); + } + + size = header.pr_nsyscalls * sizeof (prsyscall_t); + syscalls = xmalloc (size); + + if (read (sysent_fd, syscalls, size) != size) + { + xfree (syscalls); + error ("load_syscalls: Error reading /proc/%d/sysent", pi->pid); + } + + /* Find maximum syscall number. This may not be the same as + pr_nsyscalls since that value refers to the number of entries + in the table. (Also, the docs indicate that some system + call numbers may be skipped.) */ + + maxcall = syscalls[0].pr_number; + + for (i = 1; i < header.pr_nsyscalls; i++) + if (syscalls[i].pr_number > maxcall + && syscalls[i].pr_nameoff > 0 + && syscalls[i].pr_number < MAX_SYSCALLS) + maxcall = syscalls[i].pr_number; + + pi->num_syscalls = maxcall+1; + pi->syscall_names = xmalloc (pi->num_syscalls * sizeof (char *)); + + for (i = 0; i < pi->num_syscalls; i++) + pi->syscall_names[i] = NULL; + + /* Read the syscall names in */ + for (i = 0; i < header.pr_nsyscalls; i++) + { + char namebuf[MAX_SYSCALL_NAME_LENGTH]; + int nread; + int callnum; + + if (syscalls[i].pr_number >= MAX_SYSCALLS + || syscalls[i].pr_number < 0 + || syscalls[i].pr_nameoff <= 0 + || (lseek (sysent_fd, (off_t) syscalls[i].pr_nameoff, SEEK_SET) + != (off_t) syscalls[i].pr_nameoff)) + continue; + + nread = read (sysent_fd, namebuf, sizeof namebuf); + if (nread <= 0) + continue; + + callnum = syscalls[i].pr_number; + + if (pi->syscall_names[callnum] != NULL) + { + /* FIXME: Generate warning */ + continue; + } + + namebuf[nread-1] = '\0'; + size = strlen (namebuf) + 1; + pi->syscall_names[callnum] = xmalloc (size); + strncpy (pi->syscall_names[callnum], namebuf, size-1); + pi->syscall_names[callnum][size-1] = '\0'; + } + + close (sysent_fd); + xfree (syscalls); +} + +/* Function: free_syscalls + + Free the space allocated for the syscall names from the procinfo + structure. */ + +static void +free_syscalls (procinfo *pi) +{ + if (pi->syscall_names) + { + int i; + + for (i = 0; i < pi->num_syscalls; i++) + if (pi->syscall_names[i] != NULL) + xfree (pi->syscall_names[i]); + + xfree (pi->syscall_names); + pi->syscall_names = 0; + } +} + +/* Function: find_syscall + + Given a name, look up (and return) the corresponding syscall number. + If no match is found, return -1. */ + +static int +find_syscall (procinfo *pi, char *name) +{ + int i; + for (i = 0; i < pi->num_syscalls; i++) + { + if (pi->syscall_names[i] && strcmp (name, pi->syscall_names[i]) == 0) + return i; + } + return -1; +} +#endif + /* =================== END, STRUCT PROCINFO "MODULE" =================== */ /* =================== /proc "MODULE" =================== */ @@ -732,11 +1004,11 @@ int proc_kill (procinfo * pi, int signo); int proc_parent_pid (procinfo * pi); int proc_get_nthreads (procinfo * pi); int proc_get_current_thread (procinfo * pi); -int proc_set_held_signals (procinfo * pi, sigset_t * sighold); +int proc_set_held_signals (procinfo * pi, gdb_sigset_t * sighold); int proc_set_traced_sysexit (procinfo * pi, sysset_t * sysset); int proc_set_traced_sysentry (procinfo * pi, sysset_t * sysset); int proc_set_traced_faults (procinfo * pi, fltset_t * fltset); -int proc_set_traced_signals (procinfo * pi, sigset_t * sigset); +int proc_set_traced_signals (procinfo * pi, gdb_sigset_t * sigset); int proc_update_threads (procinfo * pi); int proc_iterate_over_threads (procinfo * pi, @@ -748,11 +1020,10 @@ gdb_fpregset_t *proc_get_fpregs (procinfo * pi); sysset_t *proc_get_traced_sysexit (procinfo * pi, sysset_t * save); sysset_t *proc_get_traced_sysentry (procinfo * pi, sysset_t * save); fltset_t *proc_get_traced_faults (procinfo * pi, fltset_t * save); -sigset_t *proc_get_traced_signals (procinfo * pi, sigset_t * save); -sigset_t *proc_get_held_signals (procinfo * pi, sigset_t * save); -sigset_t *proc_get_pending_signals (procinfo * pi, sigset_t * save); -struct sigaction *proc_get_signal_actions (procinfo * pi, - struct sigaction *save); +gdb_sigset_t *proc_get_traced_signals (procinfo * pi, gdb_sigset_t * save); +gdb_sigset_t *proc_get_held_signals (procinfo * pi, gdb_sigset_t * save); +gdb_sigset_t *proc_get_pending_signals (procinfo * pi, gdb_sigset_t * save); +gdb_sigaction_t *proc_get_signal_actions (procinfo * pi, gdb_sigaction_t *save); void proc_warn (procinfo * pi, char *func, int line); void proc_error (procinfo * pi, char *func, int line); @@ -1082,12 +1353,13 @@ proc_modify_flag (procinfo *pi, long flag, long mode) from one operating system to the next...) */ #ifdef PCUNSET #define GDBRESET PCUNSET -#endif +#else #ifdef PCRESET #define GDBRESET PCRESET #endif +#endif { - long arg[2]; + procfs_ctl_t arg[2]; if (mode == FLAG_SET) /* Set the flag (RLC, FORK, or ASYNC) */ arg[0] = PCSET; @@ -1313,7 +1585,7 @@ proc_stop_process (procinfo *pi) else { #ifdef NEW_PROC_API - long cmd = PCSTOP; + procfs_ctl_t cmd = PCSTOP; win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd)); #else /* ioctl method */ win = (ioctl (pi->ctl_fd, PIOCSTOP, &pi->prstatus) >= 0); @@ -1356,7 +1628,7 @@ proc_wait_for_stop (procinfo *pi) #ifdef NEW_PROC_API { - long cmd = PCWSTOP; + procfs_ctl_t cmd = PCWSTOP; win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd)); /* We been runnin' and we stopped -- need to update status. */ pi->status_valid = 0; @@ -1430,7 +1702,7 @@ proc_run_process (procinfo *pi, int step, int signo) #ifdef NEW_PROC_API { - long cmd[2]; + procfs_ctl_t cmd[2]; cmd[0] = PCRUN; cmd[1] = runflags; @@ -1457,7 +1729,7 @@ proc_run_process (procinfo *pi, int step, int signo) */ int -proc_set_traced_signals (procinfo *pi, sigset_t *sigset) +proc_set_traced_signals (procinfo *pi, gdb_sigset_t *sigset) { int win; @@ -1474,13 +1746,13 @@ proc_set_traced_signals (procinfo *pi, sigset_t *sigset) #ifdef NEW_PROC_API { struct { - long cmd; + procfs_ctl_t cmd; /* Use char array to avoid alignment issues. */ - char sigset[sizeof (sigset_t)]; + char sigset[sizeof (gdb_sigset_t)]; } arg; arg.cmd = PCSTRACE; - memcpy (&arg.sigset, sigset, sizeof (sigset_t)); + memcpy (&arg.sigset, sigset, sizeof (gdb_sigset_t)); win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg)); } @@ -1520,7 +1792,7 @@ proc_set_traced_faults (procinfo *pi, fltset_t *fltset) #ifdef NEW_PROC_API { struct { - long cmd; + procfs_ctl_t cmd; /* Use char array to avoid alignment issues. */ char fltset[sizeof (fltset_t)]; } arg; @@ -1563,16 +1835,22 @@ proc_set_traced_sysentry (procinfo *pi, sysset_t *sysset) #ifdef NEW_PROC_API { - struct { - long cmd; + struct gdb_proc_ctl_pcsentry { + procfs_ctl_t cmd; /* Use char array to avoid alignment issues. */ char sysset[sizeof (sysset_t)]; - } arg; + } *argp; + int argp_size = sizeof (struct gdb_proc_ctl_pcsentry) + - sizeof (sysset_t) + + sysset_t_size (pi); - arg.cmd = PCSENTRY; - memcpy (&arg.sysset, sysset, sizeof (sysset_t)); + argp = xmalloc (argp_size); - win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg)); + argp->cmd = PCSENTRY; + memcpy (&argp->sysset, sysset, sysset_t_size (pi)); + + win = (write (pi->ctl_fd, (char *) argp, argp_size) == argp_size); + xfree (argp); } #else /* ioctl method */ win = (ioctl (pi->ctl_fd, PIOCSENTRY, sysset) >= 0); @@ -1607,16 +1885,22 @@ proc_set_traced_sysexit (procinfo *pi, sysset_t *sysset) #ifdef NEW_PROC_API { - struct { - long cmd; + struct gdb_proc_ctl_pcsexit { + procfs_ctl_t cmd; /* Use char array to avoid alignment issues. */ char sysset[sizeof (sysset_t)]; - } arg; + } *argp; + int argp_size = sizeof (struct gdb_proc_ctl_pcsexit) + - sizeof (sysset_t) + + sysset_t_size (pi); - arg.cmd = PCSEXIT; - memcpy (&arg.sysset, sysset, sizeof (sysset_t)); + argp = xmalloc (argp_size); - win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg)); + argp->cmd = PCSEXIT; + memcpy (&argp->sysset, sysset, sysset_t_size (pi)); + + win = (write (pi->ctl_fd, (char *) argp, argp_size) == argp_size); + xfree (argp); } #else /* ioctl method */ win = (ioctl (pi->ctl_fd, PIOCSEXIT, sysset) >= 0); @@ -1635,7 +1919,7 @@ proc_set_traced_sysexit (procinfo *pi, sysset_t *sysset) */ int -proc_set_held_signals (procinfo *pi, sigset_t *sighold) +proc_set_held_signals (procinfo *pi, gdb_sigset_t *sighold) { int win; @@ -1652,13 +1936,13 @@ proc_set_held_signals (procinfo *pi, sigset_t *sighold) #ifdef NEW_PROC_API { struct { - long cmd; + procfs_ctl_t cmd; /* Use char array to avoid alignment issues. */ - char hold[sizeof (sigset_t)]; + char hold[sizeof (gdb_sigset_t)]; } arg; arg.cmd = PCSHOLD; - memcpy (&arg.hold, sighold, sizeof (sigset_t)); + memcpy (&arg.hold, sighold, sizeof (gdb_sigset_t)); win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg)); } #else @@ -1677,10 +1961,10 @@ proc_set_held_signals (procinfo *pi, sigset_t *sighold) * Will also copy the sigset if 'save' is non-zero. */ -sigset_t * -proc_get_pending_signals (procinfo *pi, sigset_t *save) +gdb_sigset_t * +proc_get_pending_signals (procinfo *pi, gdb_sigset_t *save) { - sigset_t *ret = NULL; + gdb_sigset_t *ret = NULL; /* * We should never have to apply this operation to any procinfo @@ -1702,7 +1986,7 @@ proc_get_pending_signals (procinfo *pi, sigset_t *save) ret = &pi->prstatus.pr_sigpend; #endif if (save && ret) - memcpy (save, ret, sizeof (sigset_t)); + memcpy (save, ret, sizeof (gdb_sigset_t)); return ret; } @@ -1714,10 +1998,10 @@ proc_get_pending_signals (procinfo *pi, sigset_t *save) * Will also copy the sigactionset if 'save' is non-zero. */ -struct sigaction * -proc_get_signal_actions (procinfo *pi, struct sigaction *save) +gdb_sigaction_t * +proc_get_signal_actions (procinfo *pi, gdb_sigaction_t *save) { - struct sigaction *ret = NULL; + gdb_sigaction_t *ret = NULL; /* * We should never have to apply this operation to any procinfo @@ -1739,7 +2023,7 @@ proc_get_signal_actions (procinfo *pi, struct sigaction *save) ret = &pi->prstatus.pr_action; #endif if (save && ret) - memcpy (save, ret, sizeof (struct sigaction)); + memcpy (save, ret, sizeof (gdb_sigaction_t)); return ret; } @@ -1751,10 +2035,10 @@ proc_get_signal_actions (procinfo *pi, struct sigaction *save) * Will also copy the sigset if 'save' is non-zero. */ -sigset_t * -proc_get_held_signals (procinfo *pi, sigset_t *save) +gdb_sigset_t * +proc_get_held_signals (procinfo *pi, gdb_sigset_t *save) { - sigset_t *ret = NULL; + gdb_sigset_t *ret = NULL; /* * We should never have to apply this operation to any procinfo @@ -1778,14 +2062,14 @@ proc_get_held_signals (procinfo *pi, sigset_t *save) #endif /* UNIXWARE */ #else /* not NEW_PROC_API */ { - static sigset_t sigheld; + static gdb_sigset_t sigheld; if (ioctl (pi->ctl_fd, PIOCGHOLD, &sigheld) >= 0) ret = &sigheld; } #endif /* NEW_PROC_API */ if (save && ret) - memcpy (save, ret, sizeof (sigset_t)); + memcpy (save, ret, sizeof (gdb_sigset_t)); return ret; } @@ -1797,10 +2081,10 @@ proc_get_held_signals (procinfo *pi, sigset_t *save) * Will also copy the sigset if 'save' is non-zero. */ -sigset_t * -proc_get_traced_signals (procinfo *pi, sigset_t *save) +gdb_sigset_t * +proc_get_traced_signals (procinfo *pi, gdb_sigset_t *save) { - sigset_t *ret = NULL; + gdb_sigset_t *ret = NULL; /* * We should never have to apply this operation to any procinfo @@ -1820,14 +2104,14 @@ proc_get_traced_signals (procinfo *pi, sigset_t *save) ret = &pi->prstatus.pr_sigtrace; #else { - static sigset_t sigtrace; + static gdb_sigset_t sigtrace; if (ioctl (pi->ctl_fd, PIOCGTRACE, &sigtrace) >= 0) ret = &sigtrace; } #endif if (save && ret) - memcpy (save, ret, sizeof (sigset_t)); + memcpy (save, ret, sizeof (gdb_sigset_t)); return ret; } @@ -1842,7 +2126,7 @@ proc_get_traced_signals (procinfo *pi, sigset_t *save) int proc_trace_signal (procinfo *pi, int signo) { - sigset_t temp; + gdb_sigset_t temp; /* * We should never have to apply this operation to any procinfo @@ -1876,7 +2160,7 @@ proc_trace_signal (procinfo *pi, int signo) int proc_ignore_signal (procinfo *pi, int signo) { - sigset_t temp; + gdb_sigset_t temp; /* * We should never have to apply this operation to any procinfo @@ -1969,17 +2253,48 @@ proc_get_traced_sysentry (procinfo *pi, sysset_t *save) if (!proc_get_status (pi)) return NULL; +#ifndef DYNAMIC_SYSCALLS ret = &pi->prstatus.pr_sysentry; -#else +#else /* DYNAMIC_SYSCALLS */ + { + static sysset_t *sysentry; + size_t size; + + if (!sysentry) + sysentry = sysset_t_alloc (pi); + ret = sysentry; + if (pi->status_fd == 0 && open_procinfo_files (pi, FD_STATUS) == 0) + return NULL; + if (pi->prstatus.pr_sysentry_offset == 0) + { + gdb_premptysysset (sysentry); + } + else + { + int rsize; + + if (lseek (pi->status_fd, (off_t) pi->prstatus.pr_sysentry_offset, + SEEK_SET) + != (off_t) pi->prstatus.pr_sysentry_offset) + return NULL; + size = sysset_t_size (pi); + gdb_premptysysset (sysentry); + rsize = read (pi->status_fd, sysentry, size); + if (rsize < 0) + return NULL; + } + } +#endif /* DYNAMIC_SYSCALLS */ +#else /* !NEW_PROC_API */ { static sysset_t sysentry; if (ioctl (pi->ctl_fd, PIOCGENTRY, &sysentry) >= 0) ret = &sysentry; } -#endif +#endif /* NEW_PROC_API */ if (save && ret) - memcpy (save, ret, sizeof (sysset_t)); + memcpy (save, ret, sysset_t_size (pi)); return ret; } @@ -2011,7 +2326,37 @@ proc_get_traced_sysexit (procinfo *pi, sysset_t *save) if (!proc_get_status (pi)) return NULL; +#ifndef DYNAMIC_SYSCALLS ret = &pi->prstatus.pr_sysexit; +#else /* DYNAMIC_SYSCALLS */ + { + static sysset_t *sysexit; + size_t size; + + if (!sysexit) + sysexit = sysset_t_alloc (pi); + ret = sysexit; + if (pi->status_fd == 0 && open_procinfo_files (pi, FD_STATUS) == 0) + return NULL; + if (pi->prstatus.pr_sysexit_offset == 0) + { + gdb_premptysysset (sysexit); + } + else + { + int rsize; + + if (lseek (pi->status_fd, (off_t) pi->prstatus.pr_sysexit_offset, SEEK_SET) + != (off_t) pi->prstatus.pr_sysexit_offset) + return NULL; + size = sysset_t_size (pi); + gdb_premptysysset (sysexit); + rsize = read (pi->status_fd, sysexit, size); + if (rsize < 0) + return NULL; + } + } +#endif /* DYNAMIC_SYSCALLS */ #else { static sysset_t sysexit; @@ -2021,7 +2366,7 @@ proc_get_traced_sysexit (procinfo *pi, sysset_t *save) } #endif if (save && ret) - memcpy (save, ret, sizeof (sysset_t)); + memcpy (save, ret, sysset_t_size (pi)); return ret; } @@ -2051,7 +2396,7 @@ proc_clear_current_fault (procinfo *pi) #ifdef NEW_PROC_API { - long cmd = PCCFAULT; + procfs_ctl_t cmd = PCCFAULT; win = (write (pi->ctl_fd, (void *) &cmd, sizeof (cmd)) == sizeof (cmd)); } #else @@ -2079,11 +2424,11 @@ proc_set_current_signal (procinfo *pi, int signo) { int win; struct { - long cmd; + procfs_ctl_t cmd; /* Use char array to avoid alignment issues. */ - char sinfo[sizeof (struct siginfo)]; + char sinfo[sizeof (gdb_siginfo_t)]; } arg; - struct siginfo *mysinfo; + gdb_siginfo_t *mysinfo; /* * We should never have to apply this operation to any procinfo @@ -2106,7 +2451,7 @@ proc_set_current_signal (procinfo *pi, int signo) #endif /* The pointer is just a type alias. */ - mysinfo = (struct siginfo *) &arg.sinfo; + mysinfo = (gdb_siginfo_t *) &arg.sinfo; mysinfo->si_signo = signo; mysinfo->si_code = 0; mysinfo->si_pid = getpid (); /* ?why? */ @@ -2148,15 +2493,15 @@ proc_clear_current_signal (procinfo *pi) #ifdef NEW_PROC_API { struct { - long cmd; + procfs_ctl_t cmd; /* Use char array to avoid alignment issues. */ - char sinfo[sizeof (struct siginfo)]; + char sinfo[sizeof (gdb_siginfo_t)]; } arg; - struct siginfo *mysinfo; + gdb_siginfo_t *mysinfo; arg.cmd = PCSSIG; /* The pointer is just a type alias. */ - mysinfo = (struct siginfo *) &arg.sinfo; + mysinfo = (gdb_siginfo_t *) &arg.sinfo; mysinfo->si_signo = 0; mysinfo->si_code = 0; mysinfo->si_errno = 0; @@ -2305,7 +2650,7 @@ proc_set_gregs (procinfo *pi) { #ifdef NEW_PROC_API struct { - long cmd; + procfs_ctl_t cmd; /* Use char array to avoid alignment issues. */ char gregs[sizeof (gdb_gregset_t)]; } arg; @@ -2348,7 +2693,7 @@ proc_set_fpregs (procinfo *pi) { #ifdef NEW_PROC_API struct { - long cmd; + procfs_ctl_t cmd; /* Use char array to avoid alignment issues. */ char fpregs[sizeof (gdb_fpregset_t)]; } arg; @@ -2410,7 +2755,7 @@ proc_kill (procinfo *pi, int signo) else { #ifdef NEW_PROC_API - long cmd[2]; + procfs_ctl_t cmd[2]; cmd[0] = PCKILL; cmd[1] = signo; @@ -2469,7 +2814,7 @@ proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags) return 0; #else struct { - long cmd; + procfs_ctl_t cmd; char watch[sizeof (prwatch_t)]; } arg; prwatch_t *pwatch; @@ -3072,7 +3417,7 @@ proc_iterate_over_threads (procinfo *pi, static int do_attach (int pid); static void do_detach (int signo); -static int register_gdb_signals (procinfo *, sigset_t *); +static int register_gdb_signals (procinfo *, gdb_sigset_t *); /* * Function: procfs_debug_inferior @@ -3089,9 +3434,10 @@ static int procfs_debug_inferior (procinfo *pi) { fltset_t traced_faults; - sigset_t traced_signals; - sysset_t traced_syscall_entries; - sysset_t traced_syscall_exits; + gdb_sigset_t traced_signals; + sysset_t *traced_syscall_entries; + sysset_t *traced_syscall_exits; + int status; #ifdef PROCFS_DONT_TRACE_FAULTS /* On some systems (OSF), we don't trace hardware faults. @@ -3111,17 +3457,30 @@ procfs_debug_inferior (procinfo *pi) if (!register_gdb_signals (pi, &traced_signals)) return __LINE__; + /* Register to trace the 'exit' system call (on entry). */ - premptyset (&traced_syscall_entries); - praddset (&traced_syscall_entries, SYS_exit); + traced_syscall_entries = sysset_t_alloc (pi); + gdb_premptysysset (traced_syscall_entries); +#ifdef SYS_exit + gdb_praddsysset (traced_syscall_entries, SYS_exit); +#endif #ifdef SYS_lwpexit - praddset (&traced_syscall_entries, SYS_lwpexit); /* And _lwp_exit... */ + gdb_praddsysset (traced_syscall_entries, SYS_lwpexit); /* And _lwp_exit... */ #endif #ifdef SYS_lwp_exit - praddset (&traced_syscall_entries, SYS_lwp_exit); + gdb_praddsysset (traced_syscall_entries, SYS_lwp_exit); +#endif +#ifdef DYNAMIC_SYSCALLS + { + int callnum = find_syscall (pi, "_exit"); + if (callnum >= 0) + gdb_praddsysset (traced_syscall_entries, callnum); + } #endif - if (!proc_set_traced_sysentry (pi, &traced_syscall_entries)) + status = proc_set_traced_sysentry (pi, traced_syscall_entries); + xfree (traced_syscall_entries); + if (!status) return __LINE__; #ifdef PRFS_STOPEXEC /* defined on OSF */ @@ -3147,29 +3506,42 @@ procfs_debug_inferior (procinfo *pi) names. On the SGI, for example, there is no SYS_exec, but there *is* a SYS_execv. So, we try to account for that. */ - premptyset (&traced_syscall_exits); + traced_syscall_exits = sysset_t_alloc (pi); + gdb_premptysysset (traced_syscall_exits); #ifdef SYS_exec - praddset (&traced_syscall_exits, SYS_exec); + gdb_praddsysset (traced_syscall_exits, SYS_exec); #endif #ifdef SYS_execve - praddset (&traced_syscall_exits, SYS_execve); + gdb_praddsysset (traced_syscall_exits, SYS_execve); #endif #ifdef SYS_execv - praddset (&traced_syscall_exits, SYS_execv); + gdb_praddsysset (traced_syscall_exits, SYS_execv); #endif #ifdef SYS_lwpcreate - praddset (&traced_syscall_exits, SYS_lwpcreate); - praddset (&traced_syscall_exits, SYS_lwpexit); + gdb_praddsysset (traced_syscall_exits, SYS_lwpcreate); + gdb_praddsysset (traced_syscall_exits, SYS_lwpexit); #endif #ifdef SYS_lwp_create /* FIXME: once only, please */ - praddset (&traced_syscall_exits, SYS_lwp_create); - praddset (&traced_syscall_exits, SYS_lwp_exit); + gdb_praddsysset (traced_syscall_exits, SYS_lwp_create); + gdb_praddsysset (traced_syscall_exits, SYS_lwp_exit); #endif +#ifdef DYNAMIC_SYSCALLS + { + int callnum = find_syscall (pi, "execve"); + if (callnum >= 0) + gdb_praddsysset (traced_syscall_exits, callnum); + callnum = find_syscall (pi, "ra_execve"); + if (callnum >= 0) + gdb_praddsysset (traced_syscall_exits, callnum); + } +#endif - if (!proc_set_traced_sysexit (pi, &traced_syscall_exits)) + status = proc_set_traced_sysexit (pi, traced_syscall_exits); + xfree (traced_syscall_exits); + if (!status) return __LINE__; #endif /* PRFS_STOPEXEC */ @@ -3268,10 +3640,10 @@ do_attach (int pid) dead_procinfo (pi, "do_attach: couldn't save traced faults.", NOKILL); if (!proc_get_traced_signals (pi, &pi->saved_sigset)) dead_procinfo (pi, "do_attach: couldn't save traced signals.", NOKILL); - if (!proc_get_traced_sysentry (pi, &pi->saved_entryset)) + if (!proc_get_traced_sysentry (pi, pi->saved_entryset)) dead_procinfo (pi, "do_attach: couldn't save traced syscall entries.", NOKILL); - if (!proc_get_traced_sysexit (pi, &pi->saved_exitset)) + if (!proc_get_traced_sysexit (pi, pi->saved_exitset)) dead_procinfo (pi, "do_attach: couldn't save traced syscall exits.", NOKILL); if (!proc_get_held_signals (pi, &pi->saved_sighold)) @@ -3302,10 +3674,10 @@ do_detach (int signo) if (!proc_set_traced_faults (pi, &pi->saved_fltset)) proc_warn (pi, "do_detach, set_traced_faults", __LINE__); - if (!proc_set_traced_sysentry (pi, &pi->saved_entryset)) + if (!proc_set_traced_sysentry (pi, pi->saved_entryset)) proc_warn (pi, "do_detach, set_traced_sysentry", __LINE__); - if (!proc_set_traced_sysexit (pi, &pi->saved_exitset)) + if (!proc_set_traced_sysexit (pi, pi->saved_exitset)) proc_warn (pi, "do_detach, set_traced_sysexit", __LINE__); if (!proc_set_held_signals (pi, &pi->saved_sighold)) @@ -3461,6 +3833,73 @@ procfs_store_registers (int regno) } } +static int +syscall_is_lwp_exit (procinfo *pi, int scall) +{ + +#ifdef SYS_lwp_exit + if (scall == SYS_lwp_exit) + return 1; +#endif +#ifdef SYS_lwpexit + if (scall == SYS_lwpexit) + return 1; +#endif + return 0; +} + +static int +syscall_is_exit (procinfo *pi, int scall) +{ +#ifdef SYS_exit + if (scall == SYS_exit) + return 1; +#endif +#ifdef DYNAMIC_SYSCALLS + if (find_syscall (pi, "_exit") == scall) + return 1; +#endif + return 0; +} + +static int +syscall_is_exec (procinfo *pi, int scall) +{ +#ifdef SYS_exec + if (scall == SYS_exec) + return 1; +#endif +#ifdef SYS_execv + if (scall == SYS_execv) + return 1; +#endif +#ifdef SYS_execve + if (scall == SYS_execve) + return 1; +#endif +#ifdef DYNAMIC_SYSCALLS + if (find_syscall (pi, "_execve")) + return 1; + if (find_syscall (pi, "ra_execve")) + return 1; +#endif + return 0; +} + +static int +syscall_is_lwp_create (procinfo *pi, int scall) +{ +#ifdef SYS_lwp_create + if (scall == SYS_lwp_create) + return 1; +#endif +#ifdef SYS_lwpcreate + if (scall == SYS_lwpcreate) + return 1; +#endif + return 0; +} + /* * Function: target_wait * @@ -3564,194 +4003,162 @@ wait_again: wstat = (what << 8) | 0177; break; case PR_SYSENTRY: - switch (what) { -#ifdef SYS_lwp_exit - case SYS_lwp_exit: -#endif -#ifdef SYS_lwpexit - case SYS_lwpexit: -#endif -#if defined (SYS_lwp_exit) || defined (SYS_lwpexit) - printf_filtered ("[%s exited]\n", - target_pid_to_str (retval)); - delete_thread (retval); - status->kind = TARGET_WAITKIND_SPURIOUS; - return retval; -#endif /* _lwp_exit */ - - case SYS_exit: - /* Handle SYS_exit call only */ - /* Stopped at entry to SYS_exit. - Make it runnable, resume it, then use - the wait system call to get its exit code. - Proc_run_process always clears the current - fault and signal. - Then return its exit status. */ - pi->status_valid = 0; - wstat = 0; - /* FIXME: what we should do is return - TARGET_WAITKIND_SPURIOUS. */ - if (!proc_run_process (pi, 0, 0)) - proc_error (pi, "target_wait, run_process", __LINE__); - if (attach_flag) - { - /* Don't call wait: simulate waiting for exit, - return a "success" exit code. Bogus: what if - it returns something else? */ - wstat = 0; - retval = inferior_pid; /* ? ? ? */ - } - else - { - int temp = wait (&wstat); - - /* FIXME: shouldn't I make sure I get the right - event from the right process? If (for - instance) I have killed an earlier inferior - process but failed to clean up after it - somehow, I could get its termination event - here. */ - - /* If wait returns -1, that's what we return to GDB. */ - if (temp < 0) - retval = temp; - } - break; - default: - printf_filtered ("procfs: trapped on entry to "); - proc_prettyprint_syscall (proc_what (pi), 0); - printf_filtered ("\n"); -#ifndef PIOCSSPCACT + if (syscall_is_lwp_exit (pi, what)) { - long i, nsysargs, *sysargs; - - if ((nsysargs = proc_nsysarg (pi)) > 0 && - (sysargs = proc_sysargs (pi)) != NULL) + printf_filtered ("[%s exited]\n", + target_pid_to_str (retval)); + delete_thread (retval); + status->kind = TARGET_WAITKIND_SPURIOUS; + return retval; + } + else if (syscall_is_exit (pi, what)) + { + /* Handle SYS_exit call only */ + /* Stopped at entry to SYS_exit. + Make it runnable, resume it, then use + the wait system call to get its exit code. + Proc_run_process always clears the current + fault and signal. + Then return its exit status. */ + pi->status_valid = 0; + wstat = 0; + /* FIXME: what we should do is return + TARGET_WAITKIND_SPURIOUS. */ + if (!proc_run_process (pi, 0, 0)) + proc_error (pi, "target_wait, run_process", __LINE__); + if (attach_flag) { - printf_filtered ("%ld syscall arguments:\n", nsysargs); - for (i = 0; i < nsysargs; i++) - printf_filtered ("#%ld: 0x%08lx\n", - i, sysargs[i]); + /* Don't call wait: simulate waiting for exit, + return a "success" exit code. Bogus: what if + it returns something else? */ + wstat = 0; + retval = inferior_pid; /* ? ? ? */ + } + else + { + int temp = wait (&wstat); + + /* FIXME: shouldn't I make sure I get the right + event from the right process? If (for + instance) I have killed an earlier inferior + process but failed to clean up after it + somehow, I could get its termination event + here. */ + + /* If wait returns -1, that's what we return to GDB. */ + if (temp < 0) + retval = temp; } - } -#endif - if (status) - { - /* How to exit gracefully, returning "unknown event" */ - status->kind = TARGET_WAITKIND_SPURIOUS; - return inferior_pid; - } - else + else + { + printf_filtered ("procfs: trapped on entry to "); + proc_prettyprint_syscall (proc_what (pi), 0); + printf_filtered ("\n"); +#ifndef PIOCSSPCACT { - /* How to keep going without returning to wfi: */ - target_resume (pid, 0, TARGET_SIGNAL_0); - goto wait_again; - } - break; - } - break; - case PR_SYSEXIT: - switch (what) { -#ifdef SYS_exec - case SYS_exec: -#endif -#ifdef SYS_execv - case SYS_execv: -#endif -#ifdef SYS_execve - case SYS_execve: -#endif - /* Hopefully this is our own "fork-child" execing - the real child. Hoax this event into a trap, and - GDB will see the child about to execute its start - address. */ - wstat = (SIGTRAP << 8) | 0177; - break; -#ifdef SYS_lwp_create - case SYS_lwp_create: -#endif -#ifdef SYS_lwpcreate - case SYS_lwpcreate: -#endif -#if defined(SYS_lwp_create) || defined(SYS_lwpcreate) - /* - * This syscall is somewhat like fork/exec. - * We will get the event twice: once for the parent LWP, - * and once for the child. We should already know about - * the parent LWP, but the child will be new to us. So, - * whenever we get this event, if it represents a new - * thread, simply add the thread to the list. - */ + long i, nsysargs, *sysargs; - /* If not in procinfo list, add it. */ - temp = proc_get_current_thread (pi); - if (!find_procinfo (pi->pid, temp)) - create_procinfo (pi->pid, temp); + if ((nsysargs = proc_nsysarg (pi)) > 0 && + (sysargs = proc_sysargs (pi)) != NULL) + { + printf_filtered ("%ld syscall arguments:\n", nsysargs); + for (i = 0; i < nsysargs; i++) + printf_filtered ("#%ld: 0x%08lx\n", + i, sysargs[i]); + } - temp = MERGEPID (pi->pid, temp); - /* If not in GDB's thread list, add it. */ - if (!in_thread_list (temp)) - { - printf_filtered ("[New %s]\n", target_pid_to_str (temp)); - add_thread (temp); } - /* Return to WFI, but tell it to immediately resume. */ - status->kind = TARGET_WAITKIND_SPURIOUS; - return inferior_pid; -#endif /* _lwp_create */ - -#ifdef SYS_lwp_exit - case SYS_lwp_exit: #endif -#ifdef SYS_lwpexit - case SYS_lwpexit: -#endif -#if defined (SYS_lwp_exit) || defined (SYS_lwpexit) - printf_filtered ("[%s exited]\n", - target_pid_to_str (retval)); - delete_thread (retval); - status->kind = TARGET_WAITKIND_SPURIOUS; - return retval; -#endif /* _lwp_exit */ - -#ifdef SYS_sproc - case SYS_sproc: - /* Nothing to do here for now. The old procfs - seemed to use this event to handle threads on - older (non-LWP) systems, where I'm assuming that - threads were actually separate processes. Irix, - maybe? Anyway, low priority for now. */ -#endif -#ifdef SYS_fork - case SYS_fork: - /* FIXME: do we need to handle this? Investigate. */ -#endif -#ifdef SYS_vfork - case SYS_vfork: - /* FIXME: see above. */ -#endif - default: - printf_filtered ("procfs: trapped on exit from "); - proc_prettyprint_syscall (proc_what (pi), 0); - printf_filtered ("\n"); -#ifndef PIOCSSPCACT + if (status) + { + /* How to exit gracefully, returning "unknown event" */ + status->kind = TARGET_WAITKIND_SPURIOUS; + return inferior_pid; + } + else + { + /* How to keep going without returning to wfi: */ + target_resume (pid, 0, TARGET_SIGNAL_0); + goto wait_again; + } + } + break; + case PR_SYSEXIT: + if (syscall_is_exec (pi, what)) { - long i, nsysargs, *sysargs; + /* Hopefully this is our own "fork-child" execing + the real child. Hoax this event into a trap, and + GDB will see the child about to execute its start + address. */ + wstat = (SIGTRAP << 8) | 0177; + } + else if (syscall_is_lwp_create (pi, what)) + { + /* + * This syscall is somewhat like fork/exec. + * We will get the event twice: once for the parent LWP, + * and once for the child. We should already know about + * the parent LWP, but the child will be new to us. So, + * whenever we get this event, if it represents a new + * thread, simply add the thread to the list. + */ - if ((nsysargs = proc_nsysarg (pi)) > 0 && - (sysargs = proc_sysargs (pi)) != NULL) + /* If not in procinfo list, add it. */ + temp = proc_get_current_thread (pi); + if (!find_procinfo (pi->pid, temp)) + create_procinfo (pi->pid, temp); + + temp = MERGEPID (pi->pid, temp); + /* If not in GDB's thread list, add it. */ + if (!in_thread_list (temp)) { - printf_filtered ("%ld syscall arguments:\n", nsysargs); - for (i = 0; i < nsysargs; i++) - printf_filtered ("#%ld: 0x%08lx\n", - i, sysargs[i]); + printf_filtered ("[New %s]\n", target_pid_to_str (temp)); + add_thread (temp); } + /* Return to WFI, but tell it to immediately resume. */ + status->kind = TARGET_WAITKIND_SPURIOUS; + return inferior_pid; + } + else if (syscall_is_lwp_exit (pi, what)) + { + printf_filtered ("[%s exited]\n", + target_pid_to_str (retval)); + delete_thread (retval); + status->kind = TARGET_WAITKIND_SPURIOUS; + return retval; } + else if (0) + { + /* FIXME: Do we need to handle SYS_sproc, + SYS_fork, or SYS_vfork here? The old procfs + seemed to use this event to handle threads on + older (non-LWP) systems, where I'm assuming + that threads were actually separate processes. + Irix, maybe? Anyway, low priority for now. */ + } + else + { + printf_filtered ("procfs: trapped on exit from "); + proc_prettyprint_syscall (proc_what (pi), 0); + printf_filtered ("\n"); +#ifndef PIOCSSPCACT + { + long i, nsysargs, *sysargs; + + if ((nsysargs = proc_nsysarg (pi)) > 0 && + (sysargs = proc_sysargs (pi)) != NULL) + { + printf_filtered ("%ld syscall arguments:\n", nsysargs); + for (i = 0; i < nsysargs; i++) + printf_filtered ("#%ld: 0x%08lx\n", + i, sysargs[i]); + } + } #endif - status->kind = TARGET_WAITKIND_SPURIOUS; - return inferior_pid; - } + status->kind = TARGET_WAITKIND_SPURIOUS; + return inferior_pid; + } break; case PR_REQUESTED: #if 0 /* FIXME */ @@ -3907,8 +4314,7 @@ wait_again: static int procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite, - struct mem_attrib *attrib, - struct target_ops *target) + struct mem_attrib *attrib, struct target_ops *target) { procinfo *pi; int nbytes = 0; @@ -4142,7 +4548,7 @@ procfs_resume (int pid, int step, enum target_signal signo) */ static int -register_gdb_signals (procinfo *pi, sigset_t *signals) +register_gdb_signals (procinfo *pi, gdb_sigset_t *signals) { int signo; @@ -4166,7 +4572,7 @@ register_gdb_signals (procinfo *pi, sigset_t *signals) static void procfs_notice_signals (int pid) { - sigset_t signals; + gdb_sigset_t signals; procinfo *pi = find_procinfo_or_die (PIDGET (pid), 0); if (proc_get_traced_signals (pi, &signals) && @@ -4277,7 +4683,7 @@ unconditionally_kill_inferior (procinfo *pi) We do not check the result of the PIOCSSIG, the inferior might have died already. */ { - struct siginfo newsiginfo; + gdb_siginfo_t newsiginfo; memset ((char *) &newsiginfo, 0, sizeof (newsiginfo)); newsiginfo.si_signo = SIGKILL; @@ -4365,7 +4771,7 @@ static void procfs_init_inferior (int pid) { procinfo *pi; - sigset_t signals; + gdb_sigset_t signals; int fail; /* This routine called on the parent side (GDB side) @@ -4405,9 +4811,9 @@ procfs_init_inferior (int pid) proc_error (pi, "init_inferior, get_held_signals", __LINE__); if (!proc_get_traced_faults (pi, &pi->saved_fltset)) proc_error (pi, "init_inferior, get_traced_faults", __LINE__); - if (!proc_get_traced_sysentry (pi, &pi->saved_entryset)) + if (!proc_get_traced_sysentry (pi, pi->saved_entryset)) proc_error (pi, "init_inferior, get_traced_sysentry", __LINE__); - if (!proc_get_traced_sysexit (pi, &pi->saved_exitset)) + if (!proc_get_traced_sysexit (pi, pi->saved_exitset)) proc_error (pi, "init_inferior, get_traced_sysexit", __LINE__); /* Register to trace selected signals in the child. */ @@ -4459,7 +4865,7 @@ procfs_set_exec_trap (void) because it may be sharing data space with its parent. */ procinfo *pi; - sysset_t exitset; + sysset_t *exitset; if ((pi = create_procinfo (getpid (), 0)) == NULL) perror_with_name ("procfs: create_procinfo failed in child."); @@ -4502,18 +4908,31 @@ procfs_set_exec_trap (void) names. On the SGI, for example, there is no SYS_exec, but there *is* a SYS_execv. So, we try to account for that. */ - premptyset (&exitset); + exitset = sysset_t_alloc (pi); + gdb_premptysysset (exitset); #ifdef SYS_exec - praddset (&exitset, SYS_exec); + gdb_praddsysset (exitset, SYS_exec); #endif #ifdef SYS_execve - praddset (&exitset, SYS_execve); + gdb_praddsysset (exitset, SYS_execve); #endif #ifdef SYS_execv - praddset (&exitset, SYS_execv); + gdb_praddsysset (exitset, SYS_execv); #endif +#ifdef DYNAMIC_SYSCALLS + { + int callnum = find_syscall (pi, "execve"); + + if (callnum >= 0) + gdb_praddsysset (exitset, callnum); - if (!proc_set_traced_sysexit (pi, &exitset)) + callnum = find_syscall (pi, "ra_execve"); + if (callnum >= 0) + gdb_praddsysset (exitset, callnum); + } +#endif /* DYNAMIC_SYSCALLS */ + + if (!proc_set_traced_sysexit (pi, exitset)) { proc_warn (pi, "set_exec_trap, set_traced_sysexit", __LINE__); gdb_flush (gdb_stderr); @@ -4737,6 +5156,7 @@ int procfs_set_watchpoint (int pid, CORE_ADDR addr, int len, int rwflag, int after) { #ifndef UNIXWARE +#ifndef AIX5 int pflags = 0; procinfo *pi; @@ -4776,7 +5196,8 @@ procfs_set_watchpoint (int pid, CORE_ADDR addr, int len, int rwflag, int after) return 0; /* ignore */ proc_error (pi, "set_watchpoint", __LINE__); } -#endif +#endif /* AIX5 */ +#endif /* UNIXWARE */ return 0; } @@ -4963,9 +5384,9 @@ proc_trace_syscalls (char *args, int from_tty, int entry_or_exit, int mode) proc_error (pi, "proc-trace, get_traced_sysset", __LINE__); if (mode == FLAG_SET) - praddset (sysset, syscallnum); + gdb_praddsysset (sysset, syscallnum); else - prdelset (sysset, syscallnum); + gdb_prdelsysset (sysset, syscallnum); if (entry_or_exit == PR_SYSENTRY) { |