X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fprocfs.c;h=2a21526f55766382d3dbb6ec5f0c76662b4438b3;hb=2455069d930b37918b92281be109444d1e38dc6d;hp=a92b849706004e906096cc083c6ef54174f03359;hpb=deafb06122053cb1d49e0599e76fa9b7e52537dc;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/procfs.c b/gdb/procfs.c index a92b849706..2a21526f55 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -1,26 +1,25 @@ /* Machine independent support for SVR4 /proc (process file system) for GDB. - Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, - Inc. + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010, + 2011 Free Software Foundation, Inc. Written by Michael Snyder at Cygnus Solutions. Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others. -This file is part of GDB. + 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 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 3 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. + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include "defs.h" #include "inferior.h" @@ -29,9 +28,11 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "elf-bfd.h" /* for elfcore_write_* */ #include "gdbcmd.h" #include "gdbthread.h" +#include "regcache.h" +#include "inf-child.h" #if defined (NEW_PROC_API) -#define _STRUCTURED_PROC 1 /* Should be done by configure script. */ +#define _STRUCTURED_PROC 1 /* Should be done by configure script. */ #endif #include @@ -45,45 +46,47 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gdb_wait.h" #include #include +#include "gdb_string.h" #include "gdb_assert.h" #include "inflow.h" +#include "auxv.h" +#include "procfs.h" +#include "observer.h" -/* - * PROCFS.C - * - * This module provides the interface between GDB and the - * /proc file system, which is used on many versions of Unix - * as a means for debuggers to control other processes. - * Examples of the systems that use this interface are: - * Irix - * Solaris - * OSF - * Unixware - * AIX5 - * - * /proc works by imitating a file system: you open a simulated file - * that represents the process you wish to interact with, and - * perform operations on that "file" in order to examine or change - * the state of the other process. - * - * The most important thing to know about /proc and this module - * is that there are two very different interfaces to /proc: - * One that uses the ioctl system call, and - * another that uses read and write system calls. - * This module has to support both /proc interfaces. This means - * that there are two different ways of doing every basic operation. - * - * In order to keep most of the code simple and clean, I have - * defined an interface "layer" which hides all these system calls. - * An ifdef (NEW_PROC_API) determines which interface we are using, - * and most or all occurrances of this ifdef should be confined to - * this interface layer. - */ - - -/* Determine which /proc API we are using: - The ioctl API defines PIOCSTATUS, while - the read/write (multiple fd) API never does. */ +/* This module provides the interface between GDB and the + /proc file system, which is used on many versions of Unix + as a means for debuggers to control other processes. + + Examples of the systems that use this interface are: + + Irix + Solaris + OSF + Unixware + AIX5 + + /proc works by imitating a file system: you open a simulated file + that represents the process you wish to interact with, and perform + operations on that "file" in order to examine or change the state + of the other process. + + The most important thing to know about /proc and this module is + that there are two very different interfaces to /proc: + + One that uses the ioctl system call, and another that uses read + and write system calls. + + This module has to support both /proc interfaces. This means that + there are two different ways of doing every basic operation. + + In order to keep most of the code simple and clean, I have defined + an interface "layer" which hides all these system calls. An ifdef + (NEW_PROC_API) determines which interface we are using, and most or + all occurrances of this ifdef should be confined to this interface + layer. */ + +/* Determine which /proc API we are using: The ioctl API defines + PIOCSTATUS, while the read/write (multiple fd) API never does. */ #ifdef NEW_PROC_API #include @@ -100,120 +103,142 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "proc-utils.h" -/* Prototypes for supply_gregset etc. */ +/* Prototypes for supply_gregset etc. */ #include "gregset.h" /* =================== TARGET_OPS "MODULE" =================== */ -/* - * This module defines the GDB target vector and its methods. - */ +/* This module defines the GDB target vector and its methods. */ -static void procfs_open (char *, int); -static void procfs_attach (char *, int); -static void procfs_detach (char *, int); -static void procfs_resume (ptid_t, int, enum target_signal); -static int procfs_can_run (void); -static void procfs_stop (void); +static void procfs_attach (struct target_ops *, char *, int); +static void procfs_detach (struct target_ops *, char *, int); +static void procfs_resume (struct target_ops *, + ptid_t, int, enum target_signal); +static void procfs_stop (ptid_t); static void procfs_files_info (struct target_ops *); -static void procfs_fetch_registers (int); -static void procfs_store_registers (int); -static void procfs_notice_signals (ptid_t); -static void procfs_prepare_to_store (void); -static void procfs_kill_inferior (void); -static void procfs_mourn_inferior (void); -static void procfs_create_inferior (char *, char *, char **); -static ptid_t procfs_wait (ptid_t, struct target_waitstatus *); -static int procfs_xfer_memory (CORE_ADDR, char *, int, int, +static void procfs_fetch_registers (struct target_ops *, + struct regcache *, int); +static void procfs_store_registers (struct target_ops *, + struct regcache *, int); +static void procfs_pass_signals (ptid_t, int, unsigned char *); +static void procfs_kill_inferior (struct target_ops *ops); +static void procfs_mourn_inferior (struct target_ops *ops); +static void procfs_create_inferior (struct target_ops *, char *, + char *, char **, int); +static ptid_t procfs_wait (struct target_ops *, + ptid_t, struct target_waitstatus *, int); +static int procfs_xfer_memory (CORE_ADDR, gdb_byte *, int, int, struct mem_attrib *attrib, struct target_ops *); - -static int procfs_thread_alive (ptid_t); - -void procfs_find_new_threads (void); -char *procfs_pid_to_str (ptid_t); - -static int proc_find_memory_regions (int (*) (CORE_ADDR, - unsigned long, - int, int, int, - void *), +static LONGEST procfs_xfer_partial (struct target_ops *ops, + enum target_object object, + const char *annex, + gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, LONGEST len); + +static int procfs_thread_alive (struct target_ops *ops, ptid_t); + +void procfs_find_new_threads (struct target_ops *ops); +char *procfs_pid_to_str (struct target_ops *, ptid_t); + +static int proc_find_memory_regions (int (*) (CORE_ADDR, + unsigned long, + int, int, int, + void *), void *); static char * procfs_make_note_section (bfd *, int *); static int procfs_can_use_hw_breakpoint (int, int, int); -struct target_ops procfs_ops; /* the target vector */ +#if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64) +/* When GDB is built as 64-bit application on Solaris, the auxv data + is presented in 64-bit format. We need to provide a custom parser + to handle that. */ +static int +procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr, + gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp) +{ + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); + gdb_byte *ptr = *readptr; + + if (endptr == ptr) + return 0; -static void -init_procfs_ops (void) + if (endptr - ptr < 8 * 2) + return -1; + + *typep = extract_unsigned_integer (ptr, 4, byte_order); + ptr += 8; + /* The size of data is always 64-bit. If the application is 32-bit, + it will be zero extended, as expected. */ + *valp = extract_unsigned_integer (ptr, 8, byte_order); + ptr += 8; + + *readptr = ptr; + return 1; +} +#endif + +struct target_ops * +procfs_target (void) { - procfs_ops.to_shortname = "procfs"; - procfs_ops.to_longname = "Unix /proc child process"; - procfs_ops.to_doc = + struct target_ops *t = inf_child_target (); + + t->to_shortname = "procfs"; + t->to_longname = "Unix /proc child process"; + t->to_doc = "Unix /proc child process (started by the \"run\" command)."; - procfs_ops.to_open = procfs_open; - procfs_ops.to_can_run = procfs_can_run; - procfs_ops.to_create_inferior = procfs_create_inferior; - procfs_ops.to_kill = procfs_kill_inferior; - procfs_ops.to_mourn_inferior = procfs_mourn_inferior; - procfs_ops.to_attach = procfs_attach; - procfs_ops.to_detach = procfs_detach; - procfs_ops.to_wait = procfs_wait; - procfs_ops.to_resume = procfs_resume; - procfs_ops.to_prepare_to_store = procfs_prepare_to_store; - procfs_ops.to_fetch_registers = procfs_fetch_registers; - procfs_ops.to_store_registers = procfs_store_registers; - procfs_ops.to_xfer_memory = procfs_xfer_memory; - procfs_ops.to_insert_breakpoint = memory_insert_breakpoint; - procfs_ops.to_remove_breakpoint = memory_remove_breakpoint; - procfs_ops.to_notice_signals = procfs_notice_signals; - procfs_ops.to_files_info = procfs_files_info; - procfs_ops.to_stop = procfs_stop; - - procfs_ops.to_terminal_init = terminal_init_inferior; - procfs_ops.to_terminal_inferior = terminal_inferior; - procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output; - procfs_ops.to_terminal_ours = terminal_ours; - procfs_ops.to_terminal_save_ours = terminal_save_ours; - procfs_ops.to_terminal_info = child_terminal_info; - - procfs_ops.to_find_new_threads = procfs_find_new_threads; - procfs_ops.to_thread_alive = procfs_thread_alive; - procfs_ops.to_pid_to_str = procfs_pid_to_str; - - procfs_ops.to_has_all_memory = 1; - procfs_ops.to_has_memory = 1; - procfs_ops.to_has_execution = 1; - procfs_ops.to_has_stack = 1; - procfs_ops.to_has_registers = 1; - procfs_ops.to_stratum = process_stratum; - procfs_ops.to_has_thread_control = tc_schedlock; - procfs_ops.to_find_memory_regions = proc_find_memory_regions; - procfs_ops.to_make_corefile_notes = procfs_make_note_section; - procfs_ops.to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint; - procfs_ops.to_magic = OPS_MAGIC; + t->to_create_inferior = procfs_create_inferior; + t->to_kill = procfs_kill_inferior; + t->to_mourn_inferior = procfs_mourn_inferior; + t->to_attach = procfs_attach; + t->to_detach = procfs_detach; + t->to_wait = procfs_wait; + t->to_resume = procfs_resume; + t->to_fetch_registers = procfs_fetch_registers; + t->to_store_registers = procfs_store_registers; + t->to_xfer_partial = procfs_xfer_partial; + t->deprecated_xfer_memory = procfs_xfer_memory; + t->to_pass_signals = procfs_pass_signals; + t->to_files_info = procfs_files_info; + t->to_stop = procfs_stop; + + t->to_find_new_threads = procfs_find_new_threads; + t->to_thread_alive = procfs_thread_alive; + t->to_pid_to_str = procfs_pid_to_str; + + t->to_has_thread_control = tc_schedlock; + t->to_find_memory_regions = proc_find_memory_regions; + t->to_make_corefile_notes = procfs_make_note_section; + +#if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64) + t->to_auxv_parse = procfs_auxv_parse; +#endif + + t->to_magic = OPS_MAGIC; + + return t; } /* =================== END, TARGET_OPS "MODULE" =================== */ -/* - * World Unification: - * - * Put any typedefs, defines etc. here that are required for - * the unification of code that handles different versions of /proc. - */ +/* World Unification: + + Put any typedefs, defines etc. here that are required for the + unification of code that handles different versions of /proc. */ #ifdef NEW_PROC_API /* Solaris 7 && 8 method for watchpoints */ #ifdef WA_READ - enum { READ_WATCHFLAG = WA_READ, + enum { READ_WATCHFLAG = WA_READ, WRITE_WATCHFLAG = WA_WRITE, EXEC_WATCHFLAG = WA_EXEC, AFTER_WATCHFLAG = WA_TRAPAFTER }; #endif #else /* Irix method for watchpoints */ - enum { READ_WATCHFLAG = MA_READ, + enum { READ_WATCHFLAG = MA_READ, WRITE_WATCHFLAG = MA_WRITE, EXEC_WATCHFLAG = MA_EXEC, AFTER_WATCHFLAG = 0 /* trapafter not implemented */ @@ -241,6 +266,15 @@ typedef pr_siginfo64_t gdb_siginfo_t; typedef struct siginfo gdb_siginfo_t; #endif +/* On mips-irix, praddset and prdelset are defined in such a way that + they return a value, which causes GCC to emit a -Wunused error + because the returned value is not used. Prevent this warning + by casting the return value to void. On sparc-solaris, this issue + does not exist because the definition of these macros already include + that cast to void. */ +#define gdb_praddset(sp, flag) ((void) praddset (sp, flag)) +#define gdb_prdelset(sp, flag) ((void) prdelset (sp, flag)) + /* gdb_premptysysset */ #ifdef premptysysset #define gdb_premptysysset premptysysset @@ -252,14 +286,14 @@ typedef struct siginfo gdb_siginfo_t; #ifdef praddsysset #define gdb_praddsysset praddsysset #else -#define gdb_praddsysset praddset +#define gdb_praddsysset gdb_praddset #endif /* prdelsysset */ #ifdef prdelsysset #define gdb_prdelsysset prdelsysset #else -#define gdb_prdelsysset prdelset +#define gdb_prdelsysset gdb_prdelset #endif /* prissyssetmember */ @@ -278,8 +312,7 @@ typedef struct siginfo gdb_siginfo_t; 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. -*/ + (in theory) have different syscall numbers. */ #ifdef HAVE_PRSYSENT_T #define DYNAMIC_SYSCALLS #endif @@ -305,7 +338,7 @@ typedef struct siginfo gdb_siginfo_t; There will be a separate procinfo structure for use by the (not yet implemented) "info proc" command, so that we can print useful information about any random process without interfering with the - inferior's procinfo information. */ + inferior's procinfo information. */ #ifdef NEW_PROC_API /* format strings for /proc paths */ @@ -330,7 +363,7 @@ typedef lwpstatus_t gdb_lwpstatus_t; # define STATUS_PROC_NAME_FMT "/proc/%05d" # define MAX_PROC_NAME_SIZE sizeof("/proc/ttttppppp") # endif -/* the name of the proc status struct depends on the implementation */ +/* The name of the proc status struct depends on the implementation. */ typedef prstatus_t gdb_prstatus_t; typedef prstatus_t gdb_lwpstatus_t; #endif /* NEW_PROC_API */ @@ -344,18 +377,18 @@ typedef struct procinfo { int was_stopped; int ignore_next_sigstop; - /* The following four fd fields may be identical, or may contain + /* The following four fd fields may be identical, or may contain several different fd's, depending on the version of /proc (old ioctl or new read/write). */ int ctl_fd; /* File descriptor for /proc control file */ - /* - * The next three file descriptors are actually only needed in the - * read/write, multiple-file-descriptor implemenation (NEW_PROC_API). - * However, to avoid a bunch of #ifdefs in the code, we will use - * them uniformly by (in the case of the ioctl single-file-descriptor - * implementation) filling them with copies of the control fd. - */ + + /* The next three file descriptors are actually only needed in the + read/write, multiple-file-descriptor implemenation + (NEW_PROC_API). However, to avoid a bunch of #ifdefs in the + code, we will use them uniformly by (in the case of the ioctl + single-file-descriptor implementation) filling them with copies + of the control fd. */ int status_fd; /* File descriptor for /proc status file */ int as_fd; /* File descriptor for /proc as file */ @@ -377,7 +410,7 @@ typedef struct procinfo { int num_syscalls; /* Total number of syscalls */ char **syscall_names; /* Syscall number to name map */ #endif - + struct procinfo *thread_list; int status_valid : 1; @@ -406,18 +439,18 @@ static void free_syscalls (procinfo *pi); static int find_syscall (procinfo *pi, char *name); #endif /* DYNAMIC_SYSCALLS */ +static int iterate_over_mappings + (procinfo *pi, find_memory_region_ftype child_func, void *data, + int (*func) (struct prmap *map, find_memory_region_ftype child_func, + void *data)); + /* The head of the procinfo list: */ static procinfo * procinfo_list; -/* - * Function: find_procinfo - * - * Search the procinfo list. - * - * Returns: pointer to procinfo, or NULL if not found. - */ +/* Search the procinfo list. Return a pointer to procinfo, or NULL if + not found. */ -static procinfo * +static procinfo * find_procinfo (int pid, int tid) { procinfo *pi; @@ -434,7 +467,7 @@ find_procinfo (int pid, int tid) here. This means that in general it is the caller's responsibility to check threads_valid and update before calling find_procinfo, if the caller wants to find a new - thread. */ + thread. */ for (pi = pi->thread_list; pi; pi = pi->next) if (pi->tid == tid) @@ -444,11 +477,7 @@ find_procinfo (int pid, int tid) return pi; } -/* - * Function: find_procinfo_or_die - * - * Calls find_procinfo, but errors on failure. - */ +/* Calls find_procinfo, but errors on failure. */ static procinfo * find_procinfo_or_die (int pid, int tid) @@ -458,25 +487,25 @@ find_procinfo_or_die (int pid, int tid) if (pi == NULL) { if (tid) - error ("procfs: couldn't find pid %d (kernel thread %d) in procinfo list.", + error (_("procfs: couldn't find pid %d " + "(kernel thread %d) in procinfo list."), pid, tid); else - error ("procfs: couldn't find pid %d in procinfo list.", pid); + error (_("procfs: couldn't find pid %d in procinfo list."), pid); } return pi; } -/* open_with_retry() is a wrapper for open(). The appropriate - open() call is attempted; if unsuccessful, it will be retried as - many times as needed for the EAGAIN and EINTR conditions. - - For other conditions, open_with_retry() will retry the open() a - limited number of times. In addition, a short sleep is imposed - prior to retrying the open(). The reason for this sleep is to give - the kernel a chance to catch up and create the file in question in - the event that GDB "wins" the race to open a file before the kernel - has created it. */ - +/* Wrapper for `open'. The appropriate open call is attempted; if + unsuccessful, it will be retried as many times as needed for the + EAGAIN and EINTR conditions. + + For other conditions, retry the open a limited number of times. In + addition, a short sleep is imposed prior to retrying the open. The + reason for this sleep is to give the kernel a chance to catch up + and create the file in question in the event that GDB "wins" the + race to open a file before the kernel has created it. */ + static int open_with_retry (const char *pathname, int flags) { @@ -500,18 +529,12 @@ open_with_retry (const char *pathname, int flags) return status; } -/* - * Function: open_procinfo_files - * - * Open the file descriptor for the process or LWP. - * ifdef NEW_PROC_API, we only open the control file descriptor; - * the others are opened lazily as needed. - * else (if not NEW_PROC_API), there is only one real - * file descriptor, but we keep multiple copies of it so that - * the code that uses them does not have to be #ifdef'd. - * - * Return: file descriptor, or zero for failure. - */ +/* Open the file descriptor for the process or LWP. If NEW_PROC_API + is defined, we only open the control file descriptor; the others + are opened lazily as needed. Otherwise (if not NEW_PROC_API), + there is only one real file descriptor, but we keep multiple copies + of it so that the code that uses them does not have to be #ifdef'd. + Returns the file descriptor, or zero for failure. */ enum { FD_CTL, FD_STATUS, FD_AS }; @@ -523,63 +546,59 @@ open_procinfo_files (procinfo *pi, int which) #endif int fd; - /* - * This function is getting ALMOST long enough to break up into several. - * Here is some rationale: - * - * NEW_PROC_API (Solaris 2.6, Solaris 2.7, Unixware): - * There are several file descriptors that may need to be open - * for any given process or LWP. The ones we're intereted in are: - * - control (ctl) write-only change the state - * - status (status) read-only query the state - * - address space (as) read/write access memory - * - map (map) read-only virtual addr map - * Most of these are opened lazily as they are needed. - * The pathnames for the 'files' for an LWP look slightly - * different from those of a first-class process: - * Pathnames for a process (): - * /proc//ctl - * /proc//status - * /proc//as - * /proc//map - * Pathnames for an LWP (lwp-id): - * /proc//lwp//lwpctl - * /proc//lwp//lwpstatus - * An LWP has no map or address space file descriptor, since - * the memory map and address space are shared by all LWPs. - * - * Everyone else (Solaris 2.5, Irix, OSF) - * There is only one file descriptor for each process or LWP. - * For convenience, we copy the same file descriptor into all - * three fields of the procinfo struct (ctl_fd, status_fd, and - * as_fd, see NEW_PROC_API above) so that code that uses them - * doesn't need any #ifdef's. - * Pathname for all: - * /proc/ - * - * Solaris 2.5 LWP's: - * Each LWP has an independent file descriptor, but these - * are not obtained via the 'open' system call like the rest: - * instead, they're obtained thru an ioctl call (PIOCOPENLWP) - * to the file descriptor of the parent process. - * - * OSF threads: - * These do not even have their own independent file descriptor. - * All operations are carried out on the file descriptor of the - * parent process. Therefore we just call open again for each - * thread, getting a new handle for the same 'file'. - */ + /* This function is getting ALMOST long enough to break up into + several. Here is some rationale: + + NEW_PROC_API (Solaris 2.6, Solaris 2.7, Unixware): + There are several file descriptors that may need to be open + for any given process or LWP. The ones we're intereted in are: + - control (ctl) write-only change the state + - status (status) read-only query the state + - address space (as) read/write access memory + - map (map) read-only virtual addr map + Most of these are opened lazily as they are needed. + The pathnames for the 'files' for an LWP look slightly + different from those of a first-class process: + Pathnames for a process (): + /proc//ctl + /proc//status + /proc//as + /proc//map + Pathnames for an LWP (lwp-id): + /proc//lwp//lwpctl + /proc//lwp//lwpstatus + An LWP has no map or address space file descriptor, since + the memory map and address space are shared by all LWPs. + + Everyone else (Solaris 2.5, Irix, OSF) + There is only one file descriptor for each process or LWP. + For convenience, we copy the same file descriptor into all + three fields of the procinfo struct (ctl_fd, status_fd, and + as_fd, see NEW_PROC_API above) so that code that uses them + doesn't need any #ifdef's. + Pathname for all: + /proc/ + + Solaris 2.5 LWP's: + Each LWP has an independent file descriptor, but these + are not obtained via the 'open' system call like the rest: + instead, they're obtained thru an ioctl call (PIOCOPENLWP) + to the file descriptor of the parent process. + + OSF threads: + These do not even have their own independent file descriptor. + All operations are carried out on the file descriptor of the + parent process. Therefore we just call open again for each + thread, getting a new handle for the same 'file'. */ #ifdef NEW_PROC_API - /* - * In this case, there are several different file descriptors that - * we might be asked to open. The control file descriptor will be - * opened early, but the others will be opened lazily as they are - * needed. - */ + /* In this case, there are several different file descriptors that + we might be asked to open. The control file descriptor will be + opened early, but the others will be opened lazily as they are + needed. */ strcpy (tmp, pi->pathname); - switch (which) { /* which file descriptor to open? */ + switch (which) { /* Which file descriptor to open? */ case FD_CTL: if (pi->tid) strcat (tmp, "/lwpctl"); @@ -592,7 +611,7 @@ open_procinfo_files (procinfo *pi, int which) break; case FD_AS: if (pi->tid) - return 0; /* there is no 'as' file descriptor for an lwp */ + return 0; /* There is no 'as' file descriptor for an lwp. */ strcat (tmp, "/as"); fd = open_with_retry (tmp, O_RDWR); if (fd <= 0) @@ -613,25 +632,23 @@ open_procinfo_files (procinfo *pi, int which) return 0; /* unknown file descriptor */ } #else /* not NEW_PROC_API */ - /* - * In this case, there is only one file descriptor for each procinfo - * (ie. each process or LWP). In fact, only the file descriptor for - * the process can actually be opened by an 'open' system call. - * The ones for the LWPs have to be obtained thru an IOCTL call - * on the process's file descriptor. - * - * For convenience, we copy each procinfo's single file descriptor - * into all of the fields occupied by the several file descriptors - * of the NEW_PROC_API implementation. That way, the code that uses - * them can be written without ifdefs. - */ + /* In this case, there is only one file descriptor for each procinfo + (ie. each process or LWP). In fact, only the file descriptor for + the process can actually be opened by an 'open' system call. The + ones for the LWPs have to be obtained thru an IOCTL call on the + process's file descriptor. + + For convenience, we copy each procinfo's single file descriptor + into all of the fields occupied by the several file descriptors + of the NEW_PROC_API implementation. That way, the code that uses + them can be written without ifdefs. */ #ifdef PIOCTSTATUS /* OSF */ - /* Only one FD; just open it. */ + /* Only one FD; just open it. */ if ((fd = open_with_retry (pi->pathname, O_RDWR)) == 0) return 0; -#else /* Sol 2.5, Irix, other? */ +#else /* Sol 2.5, Irix, other? */ if (pi->tid == 0) /* Master procinfo for the process */ { fd = open_with_retry (pi->pathname, O_RDWR); @@ -644,15 +661,15 @@ open_procinfo_files (procinfo *pi, int which) procinfo *process; int lwpid = pi->tid; - /* Find the procinfo for the entire process. */ + /* Find the procinfo for the entire process. */ if ((process = find_procinfo (pi->pid, 0)) == NULL) return 0; /* fail */ - /* Now obtain the file descriptor for the LWP. */ + /* Now obtain the file descriptor for the LWP. */ if ((fd = ioctl (process->ctl_fd, PIOCOPENLWP, &lwpid)) <= 0) return 0; /* fail */ -#else /* Irix, other? */ - return 0; /* Don't know how to open threads */ +#else /* Irix, other? */ + return 0; /* Don't know how to open threads. */ #endif /* Sol 2.5 PIOCOPENLWP */ } #endif /* OSF PIOCTSTATUS */ @@ -662,28 +679,23 @@ open_procinfo_files (procinfo *pi, int which) return 1; /* success */ } -/* - * Function: create_procinfo - * - * Allocate a data structure and link it into the procinfo list. - * (First tries to find a pre-existing one (FIXME: why?) - * - * Return: pointer to new procinfo struct. - */ +/* Allocate a data structure and link it into the procinfo list. + First tries to find a pre-existing one (FIXME: why?). Returns the + pointer to new procinfo struct. */ static procinfo * create_procinfo (int pid, int tid) { - procinfo *pi, *parent; + procinfo *pi, *parent = NULL; if ((pi = find_procinfo (pid, tid))) - return pi; /* Already exists, nothing to do. */ + return pi; /* Already exists, nothing to do. */ - /* find parent before doing malloc, to save having to cleanup */ + /* Find parent before doing malloc, to save having to cleanup. */ if (tid != 0) parent = find_procinfo_or_die (pid, 0); /* FIXME: should I create it if it - doesn't exist yet? */ + doesn't exist yet? */ pi = (procinfo *) xmalloc (sizeof (procinfo)); memset (pi, 0, sizeof (procinfo)); @@ -717,11 +729,7 @@ create_procinfo (int pid, int tid) return pi; } -/* - * Function: close_procinfo_files - * - * Close all file descriptors associated with the procinfo - */ +/* Close all file descriptors associated with the procinfo. */ static void close_procinfo_files (procinfo *pi) @@ -737,21 +745,17 @@ close_procinfo_files (procinfo *pi) pi->ctl_fd = pi->as_fd = pi->status_fd = 0; } -/* - * Function: destroy_procinfo - * - * Destructor function. Close, unlink and deallocate the object. - */ +/* Destructor function. Close, unlink and deallocate the object. */ static void destroy_one_procinfo (procinfo **list, procinfo *pi) { procinfo *ptr; - /* Step one: unlink the procinfo from its list */ + /* Step one: unlink the procinfo from its list. */ if (pi == *list) *list = pi->next; - else + else for (ptr = *list; ptr; ptr = ptr->next) if (ptr->next == pi) { @@ -759,10 +763,10 @@ destroy_one_procinfo (procinfo **list, procinfo *pi) break; } - /* Step two: close any open file descriptors */ + /* Step two: close any open file descriptors. */ close_procinfo_files (pi); - /* Step three: free the memory. */ + /* Step three: free the memory. */ #ifdef DYNAMIC_SYSCALLS free_syscalls (pi); #endif @@ -776,12 +780,12 @@ destroy_procinfo (procinfo *pi) { procinfo *tmp; - if (pi->tid != 0) /* destroy a thread procinfo */ + if (pi->tid != 0) /* Destroy a thread procinfo. */ { - tmp = find_procinfo (pi->pid, 0); /* find the parent process */ + tmp = find_procinfo (pi->pid, 0); /* Find the parent process. */ destroy_one_procinfo (&tmp->thread_list, pi); } - else /* destroy a process procinfo and all its threads */ + else /* Destroy a process procinfo and all its threads. */ { /* First destroy the children, if any; */ while (pi->thread_list != NULL) @@ -799,13 +803,9 @@ do_destroy_procinfo_cleanup (void *pi) enum { NOKILL, KILL }; -/* - * Function: dead_procinfo - * - * To be called on a non_recoverable error for a procinfo. - * Prints error messages, optionally sends a SIGKILL to the process, - * then destroys the data structure. - */ +/* To be called on a non_recoverable error for a procinfo. Prints + error messages, optionally sends a SIGKILL to the process, then + destroys the data structure. */ static void dead_procinfo (procinfo *pi, char *msg, int kill_p) @@ -825,16 +825,12 @@ dead_procinfo (procinfo *pi, char *msg, int kill_p) kill (pi->pid, SIGKILL); destroy_procinfo (pi); - error (msg); + error ("%s", 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. - */ +/* Returns the (complete) size of a sysset_t struct. Normally, this + is just sizeof (sysset_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) @@ -848,31 +844,28 @@ sysset_t_size (procinfo * pi) #endif } -/* Function: sysset_t_alloc - - Allocate and (partially) initialize a sysset_t struct. */ +/* 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)); + 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//sysent. Initialize +/* Extract syscall numbers and names from /proc//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.) */ + names for these numbers will be left as NULL.) */ #define MAX_SYSCALL_NAME_LENGTH 256 #define MAX_SYSCALLS 65536 @@ -889,23 +882,24 @@ load_syscalls (procinfo *pi) pi->num_syscalls = 0; pi->syscall_names = 0; - /* Open the file descriptor for the sysent file */ + /* Open the file descriptor for the sysent file. */ sprintf (pathname, "/proc/%d/sysent", pi->pid); sysent_fd = open_with_retry (pathname, O_RDONLY); if (sysent_fd < 0) { - error ("load_syscalls: Can't open /proc/%d/sysent", pi->pid); + 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); + 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); + error (_("load_syscalls: /proc/%d/sysent contains no syscalls!"), + pi->pid); } size = header.pr_nsyscalls * sizeof (prsyscall_t); @@ -914,19 +908,19 @@ load_syscalls (procinfo *pi) if (read (sysent_fd, syscalls, size) != size) { xfree (syscalls); - error ("load_syscalls: Error reading /proc/%d/sysent", pi->pid); + 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.) */ + 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_nameoff > 0 && syscalls[i].pr_number < MAX_SYSCALLS) maxcall = syscalls[i].pr_number; @@ -936,7 +930,7 @@ load_syscalls (procinfo *pi) for (i = 0; i < pi->num_syscalls; i++) pi->syscall_names[i] = NULL; - /* Read the syscall names in */ + /* Read the syscall names in. */ for (i = 0; i < header.pr_nsyscalls; i++) { char namebuf[MAX_SYSCALL_NAME_LENGTH]; @@ -944,10 +938,10 @@ load_syscalls (procinfo *pi) int callnum; if (syscalls[i].pr_number >= MAX_SYSCALLS - || syscalls[i].pr_number < 0 + || 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)) + != (off_t) syscalls[i].pr_nameoff)) continue; nread = read (sysent_fd, namebuf, sizeof namebuf); @@ -958,7 +952,7 @@ load_syscalls (procinfo *pi) if (pi->syscall_names[callnum] != NULL) { - /* FIXME: Generate warning */ + /* FIXME: Generate warning. */ continue; } @@ -968,14 +962,12 @@ load_syscalls (procinfo *pi) 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 +/* Free the space allocated for the syscall names from the procinfo structure. */ static void @@ -994,15 +986,14 @@ free_syscalls (procinfo *pi) } } -/* Function: find_syscall - - Given a name, look up (and return) the corresponding syscall number. +/* 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) @@ -1016,17 +1007,15 @@ find_syscall (procinfo *pi, char *name) /* =================== /proc "MODULE" =================== */ -/* - * This "module" is the interface layer between the /proc system API - * and the gdb target vector functions. This layer consists of - * access functions that encapsulate each of the basic operations - * that we need to use from the /proc API. - * - * The main motivation for this layer is to hide the fact that - * there are two very different implementations of the /proc API. - * Rather than have a bunch of #ifdefs all thru the gdb target vector - * functions, we do our best to hide them all in here. - */ +/* This "module" is the interface layer between the /proc system API + and the gdb target vector functions. This layer consists of access + functions that encapsulate each of the basic operations that we + need to use from the /proc API. + + The main motivation for this layer is to hide the fact that there + are two very different implementations of the /proc API. Rather + than have a bunch of #ifdefs all thru the gdb target vector + functions, we do our best to hide them all in here. */ int proc_get_status (procinfo * pi); long proc_flags (procinfo * pi); @@ -1071,7 +1060,8 @@ fltset_t *proc_get_traced_faults (procinfo * pi, fltset_t * 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); +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); @@ -1090,22 +1080,16 @@ proc_error (procinfo *pi, char *func, int line) perror_with_name (errmsg); } -/* - * Function: proc_get_status - * - * Updates the status struct in the procinfo. - * There is a 'valid' flag, to let other functions know when - * this function needs to be called (so the status is only - * read when it is needed). The status file descriptor is - * also only opened when it is needed. - * - * Return: non-zero for success, zero for failure. - */ +/* Updates the status struct in the procinfo. There is a 'valid' + flag, to let other functions know when this function needs to be + called (so the status is only read when it is needed). The status + file descriptor is also only opened when it is needed. Returns + non-zero for success, zero for failure. */ int proc_get_status (procinfo *pi) { - /* Status file descriptor is opened "lazily" */ + /* Status file descriptor is opened "lazily". */ if (pi->status_fd == 0 && open_procinfo_files (pi, FD_STATUS) == 0) { @@ -1118,16 +1102,16 @@ proc_get_status (procinfo *pi) pi->status_valid = 0; /* fail */ else { - /* Sigh... I have to read a different data structure, - depending on whether this is a main process or an LWP. */ + /* Sigh... I have to read a different data structure, + depending on whether this is a main process or an LWP. */ if (pi->tid) - pi->status_valid = (read (pi->status_fd, - (char *) &pi->prstatus.pr_lwp, + pi->status_valid = (read (pi->status_fd, + (char *) &pi->prstatus.pr_lwp, sizeof (lwpstatus_t)) == sizeof (lwpstatus_t)); else { - pi->status_valid = (read (pi->status_fd, + pi->status_valid = (read (pi->status_fd, (char *) &pi->prstatus, sizeof (gdb_prstatus_t)) == sizeof (gdb_prstatus_t)); @@ -1135,8 +1119,8 @@ proc_get_status (procinfo *pi) if (pi->status_valid && (pi->prstatus.pr_lwp.pr_flags & PR_ISTOP) && pi->prstatus.pr_lwp.pr_why == PR_REQUESTED) - /* Unixware peculiarity -- read the damn thing again! */ - pi->status_valid = (read (pi->status_fd, + /* Unixware peculiarity -- read the damn thing again! */ + pi->status_valid = (read (pi->status_fd, (char *) &pi->prstatus, sizeof (gdb_prstatus_t)) == sizeof (gdb_prstatus_t)); @@ -1147,8 +1131,8 @@ proc_get_status (procinfo *pi) #ifdef PIOCTSTATUS /* osf */ if (pi->tid == 0) /* main process */ { - /* Just read the danged status. Now isn't that simple? */ - pi->status_valid = + /* Just read the danged status. Now isn't that simple? */ + pi->status_valid = (ioctl (pi->status_fd, PIOCSTATUS, &pi->prstatus) >= 0); } else @@ -1165,53 +1149,49 @@ proc_get_status (procinfo *pi) win = (ioctl (pi->status_fd, PIOCTSTATUS, &thread_status) >= 0); if (win) { - memcpy (&pi->prstatus, &thread_status.status, + memcpy (&pi->prstatus, &thread_status.status, sizeof (pi->prstatus)); pi->status_valid = 1; } } #else - /* Just read the danged status. Now isn't that simple? */ + /* Just read the danged status. Now isn't that simple? */ pi->status_valid = (ioctl (pi->status_fd, PIOCSTATUS, &pi->prstatus) >= 0); #endif #endif if (pi->status_valid) { - PROC_PRETTYFPRINT_STATUS (proc_flags (pi), + PROC_PRETTYFPRINT_STATUS (proc_flags (pi), proc_why (pi), - proc_what (pi), + proc_what (pi), proc_get_current_thread (pi)); } - /* The status struct includes general regs, so mark them valid too */ + /* The status struct includes general regs, so mark them valid too. */ pi->gregs_valid = pi->status_valid; #ifdef NEW_PROC_API - /* In the read/write multiple-fd model, - the status struct includes the fp regs too, so mark them valid too */ + /* In the read/write multiple-fd model, the status struct includes + the fp regs too, so mark them valid too. */ pi->fpregs_valid = pi->status_valid; #endif - return pi->status_valid; /* True if success, false if failure. */ + return pi->status_valid; /* True if success, false if failure. */ } -/* - * Function: proc_flags - * - * returns the process flags (pr_flags field). - */ +/* Returns the process flags (pr_flags field). */ long proc_flags (procinfo *pi) { if (!pi->status_valid) if (!proc_get_status (pi)) - return 0; /* FIXME: not a good failure value (but what is?) */ + return 0; /* FIXME: not a good failure value (but what is?) */ #ifdef NEW_PROC_API # ifdef UNIXWARE /* UnixWare 7.1 puts process status flags, e.g. PR_ASYNC, in pstatus_t and LWP status flags, e.g. PR_STOPPED, in lwpstatus_t. - The two sets of flags don't overlap. */ + The two sets of flags don't overlap. */ return pi->prstatus.pr_flags | pi->prstatus.pr_lwp.pr_flags; # else return pi->prstatus.pr_lwp.pr_flags; @@ -1221,18 +1201,14 @@ proc_flags (procinfo *pi) #endif } -/* - * Function: proc_why - * - * returns the pr_why field (why the process stopped). - */ +/* Returns the pr_why field (why the process stopped). */ int proc_why (procinfo *pi) { if (!pi->status_valid) if (!proc_get_status (pi)) - return 0; /* FIXME: not a good failure value (but what is?) */ + return 0; /* FIXME: not a good failure value (but what is?) */ #ifdef NEW_PROC_API return pi->prstatus.pr_lwp.pr_why; @@ -1241,18 +1217,14 @@ proc_why (procinfo *pi) #endif } -/* - * Function: proc_what - * - * returns the pr_what field (details of why the process stopped). - */ +/* Returns the pr_what field (details of why the process stopped). */ int proc_what (procinfo *pi) { if (!pi->status_valid) if (!proc_get_status (pi)) - return 0; /* FIXME: not a good failure value (but what is?) */ + return 0; /* FIXME: not a good failure value (but what is?) */ #ifdef NEW_PROC_API return pi->prstatus.pr_lwp.pr_what; @@ -1261,12 +1233,34 @@ proc_what (procinfo *pi) #endif } +/* This function is only called when PI is stopped by a watchpoint. + Assuming the OS supports it, write to *ADDR the data address which + triggered it and return 1. Return 0 if it is not possible to know + the address. */ + +static int +proc_watchpoint_address (procinfo *pi, CORE_ADDR *addr) +{ + if (!pi->status_valid) + if (!proc_get_status (pi)) + return 0; + +#ifdef NEW_PROC_API + *addr = (CORE_ADDR) gdbarch_pointer_to_address (target_gdbarch, + builtin_type (target_gdbarch)->builtin_data_ptr, + (gdb_byte *) &pi->prstatus.pr_lwp.pr_info.si_addr); +#else + *addr = (CORE_ADDR) gdbarch_pointer_to_address (target_gdbarch, + builtin_type (target_gdbarch)->builtin_data_ptr, + (gdb_byte *) &pi->prstatus.pr_info.si_addr); +#endif + return 1; +} + #ifndef PIOCSSPCACT /* The following is not supported on OSF. */ -/* - * Function: proc_nsysarg - * - * returns the pr_nsysarg field (number of args to the current syscall). - */ + +/* Returns the pr_nsysarg field (number of args to the current + syscall). */ int proc_nsysarg (procinfo *pi) @@ -1274,7 +1268,7 @@ proc_nsysarg (procinfo *pi) if (!pi->status_valid) if (!proc_get_status (pi)) return 0; - + #ifdef NEW_PROC_API return pi->prstatus.pr_lwp.pr_nsysarg; #else @@ -1282,11 +1276,8 @@ proc_nsysarg (procinfo *pi) #endif } -/* - * Function: proc_sysargs - * - * returns the pr_sysarg field (pointer to the arguments of current syscall). - */ +/* Returns the pr_sysarg field (pointer to the arguments of current + syscall). */ long * proc_sysargs (procinfo *pi) @@ -1294,7 +1285,7 @@ proc_sysargs (procinfo *pi) if (!pi->status_valid) if (!proc_get_status (pi)) return NULL; - + #ifdef NEW_PROC_API return (long *) &pi->prstatus.pr_lwp.pr_sysarg; #else @@ -1302,11 +1293,8 @@ proc_sysargs (procinfo *pi) #endif } -/* - * Function: proc_syscall - * - * returns the pr_syscall field (id of current syscall if we are in one). - */ +/* Returns the pr_syscall field (id of current syscall if we are in + one). */ int proc_syscall (procinfo *pi) @@ -1314,7 +1302,7 @@ proc_syscall (procinfo *pi) if (!pi->status_valid) if (!proc_get_status (pi)) return 0; - + #ifdef NEW_PROC_API return pi->prstatus.pr_lwp.pr_syscall; #else @@ -1323,18 +1311,14 @@ proc_syscall (procinfo *pi) } #endif /* PIOCSSPCACT */ -/* - * Function: proc_cursig: - * - * returns the pr_cursig field (current signal). - */ +/* Returns the pr_cursig field (current signal). */ long proc_cursig (struct procinfo *pi) { if (!pi->status_valid) if (!proc_get_status (pi)) - return 0; /* FIXME: not a good failure value (but what is?) */ + return 0; /* FIXME: not a good failure value (but what is?) */ #ifdef NEW_PROC_API return pi->prstatus.pr_lwp.pr_cursig; @@ -1343,38 +1327,34 @@ proc_cursig (struct procinfo *pi) #endif } -/* - * Function: proc_modify_flag - * - * === I appologize for the messiness of this function. - * === This is an area where the different versions of - * === /proc are more inconsistent than usual. MVS - * - * Set or reset any of the following process flags: - * PR_FORK -- forked child will inherit trace flags - * PR_RLC -- traced process runs when last /proc file closed. - * PR_KLC -- traced process is killed when last /proc file closed. - * PR_ASYNC -- LWP's get to run/stop independently. - * - * There are three methods for doing this function: - * 1) Newest: read/write [PCSET/PCRESET/PCUNSET] - * [Sol6, Sol7, UW] - * 2) Middle: PIOCSET/PIOCRESET - * [Irix, Sol5] - * 3) Oldest: PIOCSFORK/PIOCRFORK/PIOCSRLC/PIOCRRLC - * [OSF, Sol5] - * - * Note: Irix does not define PR_ASYNC. - * Note: OSF does not define PR_KLC. - * Note: OSF is the only one that can ONLY use the oldest method. - * - * Arguments: - * pi -- the procinfo - * flag -- one of PR_FORK, PR_RLC, or PR_ASYNC - * mode -- 1 for set, 0 for reset. - * - * Returns non-zero for success, zero for failure. - */ +/* === I appologize for the messiness of this function. + === This is an area where the different versions of + === /proc are more inconsistent than usual. + + Set or reset any of the following process flags: + PR_FORK -- forked child will inherit trace flags + PR_RLC -- traced process runs when last /proc file closed. + PR_KLC -- traced process is killed when last /proc file closed. + PR_ASYNC -- LWP's get to run/stop independently. + + There are three methods for doing this function: + 1) Newest: read/write [PCSET/PCRESET/PCUNSET] + [Sol6, Sol7, UW] + 2) Middle: PIOCSET/PIOCRESET + [Irix, Sol5] + 3) Oldest: PIOCSFORK/PIOCRFORK/PIOCSRLC/PIOCRRLC + [OSF, Sol5] + + Note: Irix does not define PR_ASYNC. + Note: OSF does not define PR_KLC. + Note: OSF is the only one that can ONLY use the oldest method. + + Arguments: + pi -- the procinfo + flag -- one of PR_FORK, PR_RLC, or PR_ASYNC + mode -- 1 for set, 0 for reset. + + Returns non-zero for success, zero for failure. */ enum { FLAG_RESET, FLAG_SET }; @@ -1383,20 +1363,17 @@ proc_modify_flag (procinfo *pi, long flag, long mode) { long win = 0; /* default to fail */ - /* - * These operations affect the process as a whole, and applying - * them to an individual LWP has the same meaning as applying them - * to the main process. Therefore, if we're ever called with a - * pointer to an LWP's procinfo, let's substitute the process's - * procinfo and avoid opening the LWP's file descriptor - * unnecessarily. - */ + /* These operations affect the process as a whole, and applying them + to an individual LWP has the same meaning as applying them to the + main process. Therefore, if we're ever called with a pointer to + an LWP's procinfo, let's substitute the process's procinfo and + avoid opening the LWP's file descriptor unnecessarily. */ if (pi->pid != 0) pi = find_procinfo_or_die (pi->pid, 0); -#ifdef NEW_PROC_API /* Newest method: UnixWare and newer Solarii */ - /* First normalize the PCUNSET/PCRESET command opcode +#ifdef NEW_PROC_API /* Newest method: UnixWare and newer Solarii. */ + /* First normalize the PCUNSET/PCRESET command opcode (which for no obvious reason has a different definition from one operating system to the next...) */ #ifdef PCUNSET @@ -1409,9 +1386,9 @@ proc_modify_flag (procinfo *pi, long flag, long mode) { procfs_ctl_t arg[2]; - if (mode == FLAG_SET) /* Set the flag (RLC, FORK, or ASYNC) */ + if (mode == FLAG_SET) /* Set the flag (RLC, FORK, or ASYNC). */ arg[0] = PCSET; - else /* Reset the flag */ + else /* Reset the flag. */ arg[0] = GDBRESET; arg[1] = flag; @@ -1419,11 +1396,11 @@ proc_modify_flag (procinfo *pi, long flag, long mode) } #else #ifdef PIOCSET /* Irix/Sol5 method */ - if (mode == FLAG_SET) /* Set the flag (hopefully RLC, FORK, or ASYNC) */ + if (mode == FLAG_SET) /* Set the flag (hopefully RLC, FORK, or ASYNC). */ { win = (ioctl (pi->ctl_fd, PIOCSET, &flag) >= 0); } - else /* Reset the flag */ + else /* Reset the flag. */ { win = (ioctl (pi->ctl_fd, PIOCRESET, &flag) >= 0); } @@ -1452,18 +1429,19 @@ proc_modify_flag (procinfo *pi, long flag, long mode) } break; default: - win = 0; /* fail -- unknown flag (can't do PR_ASYNC) */ + win = 0; /* Fail -- unknown flag (can't do PR_ASYNC). */ break; } #endif #endif #endif #undef GDBRESET - /* The above operation renders the procinfo's cached pstatus obsolete. */ + /* The above operation renders the procinfo's cached pstatus + obsolete. */ pi->status_valid = 0; if (!win) - warning ("procfs: modify_flag failed to turn %s %s", + warning (_("procfs: modify_flag failed to turn %s %s"), flag == PR_FORK ? "PR_FORK" : flag == PR_RLC ? "PR_RLC" : #ifdef PR_ASYNC @@ -1478,15 +1456,9 @@ proc_modify_flag (procinfo *pi, long flag, long mode) return win; } -/* - * Function: proc_set_run_on_last_close - * - * Set the run_on_last_close flag. - * Process with all threads will become runnable - * when debugger closes all /proc fds. - * - * Returns non-zero for success, zero for failure. - */ +/* Set the run_on_last_close flag. Process with all threads will + become runnable when debugger closes all /proc fds. Returns + non-zero for success, zero for failure. */ int proc_set_run_on_last_close (procinfo *pi) @@ -1494,15 +1466,9 @@ proc_set_run_on_last_close (procinfo *pi) return proc_modify_flag (pi, PR_RLC, FLAG_SET); } -/* - * Function: proc_unset_run_on_last_close - * - * Reset the run_on_last_close flag. - * Process will NOT become runnable - * when debugger closes its file handles. - * - * Returns non-zero for success, zero for failure. - */ +/* Reset the run_on_last_close flag. The process will NOT become + runnable when debugger closes its file handles. Returns non-zero + for success, zero for failure. */ int proc_unset_run_on_last_close (procinfo *pi) @@ -1511,15 +1477,9 @@ proc_unset_run_on_last_close (procinfo *pi) } #ifdef PR_KLC -/* - * Function: proc_set_kill_on_last_close - * - * Set the kill_on_last_close flag. - * Process with all threads will be killed when debugger - * closes all /proc fds (or debugger exits or dies). - * - * Returns non-zero for success, zero for failure. - */ +/* Set the kill_on_last_close flag. Process with all threads will be + killed when debugger closes all /proc fds (or debugger exits or + dies). Returns non-zero for success, zero for failure. */ int proc_set_kill_on_last_close (procinfo *pi) @@ -1527,15 +1487,9 @@ proc_set_kill_on_last_close (procinfo *pi) return proc_modify_flag (pi, PR_KLC, FLAG_SET); } -/* - * Function: proc_unset_kill_on_last_close - * - * Reset the kill_on_last_close flag. - * Process will NOT be killed when debugger - * closes its file handles (or exits or dies). - * - * Returns non-zero for success, zero for failure. - */ +/* Reset the kill_on_last_close flag. Process will NOT be killed when + debugger closes its file handles (or exits or dies). Returns + non-zero for success, zero for failure. */ int proc_unset_kill_on_last_close (procinfo *pi) @@ -1544,15 +1498,10 @@ proc_unset_kill_on_last_close (procinfo *pi) } #endif /* PR_KLC */ -/* - * Function: proc_set_inherit_on_fork - * - * Set inherit_on_fork flag. - * If the process forks a child while we are registered for events - * in the parent, then we will also recieve events from the child. - * - * Returns non-zero for success, zero for failure. - */ +/* Set inherit_on_fork flag. If the process forks a child while we + are registered for events in the parent, then we will also recieve + events from the child. Returns non-zero for success, zero for + failure. */ int proc_set_inherit_on_fork (procinfo *pi) @@ -1560,15 +1509,10 @@ proc_set_inherit_on_fork (procinfo *pi) return proc_modify_flag (pi, PR_FORK, FLAG_SET); } -/* - * Function: proc_unset_inherit_on_fork - * - * Reset inherit_on_fork flag. - * If the process forks a child while we are registered for events - * in the parent, then we will NOT recieve events from the child. - * - * Returns non-zero for success, zero for failure. - */ +/* Reset inherit_on_fork flag. If the process forks a child while we + are registered for events in the parent, then we will NOT recieve + events from the child. Returns non-zero for success, zero for + failure. */ int proc_unset_inherit_on_fork (procinfo *pi) @@ -1577,15 +1521,9 @@ proc_unset_inherit_on_fork (procinfo *pi) } #ifdef PR_ASYNC -/* - * Function: proc_set_async - * - * Set PR_ASYNC flag. - * If one LWP stops because of a debug event (signal etc.), - * the remaining LWPs will continue to run. - * - * Returns non-zero for success, zero for failure. - */ +/* Set PR_ASYNC flag. If one LWP stops because of a debug event + (signal etc.), the remaining LWPs will continue to run. Returns + non-zero for success, zero for failure. */ int proc_set_async (procinfo *pi) @@ -1593,15 +1531,9 @@ proc_set_async (procinfo *pi) return proc_modify_flag (pi, PR_ASYNC, FLAG_SET); } -/* - * Function: proc_unset_async - * - * Reset PR_ASYNC flag. - * If one LWP stops because of a debug event (signal etc.), - * then all other LWPs will stop as well. - * - * Returns non-zero for success, zero for failure. - */ +/* Reset PR_ASYNC flag. If one LWP stops because of a debug event + (signal etc.), then all other LWPs will stop as well. Returns + non-zero for success, zero for failure. */ int proc_unset_async (procinfo *pi) @@ -1610,22 +1542,16 @@ proc_unset_async (procinfo *pi) } #endif /* PR_ASYNC */ -/* - * Function: proc_stop_process - * - * Request the process/LWP to stop. Does not wait. - * Returns non-zero for success, zero for failure. - */ +/* Request the process/LWP to stop. Does not wait. Returns non-zero + for success, zero for failure. */ int proc_stop_process (procinfo *pi) { int win; - /* - * We might conceivably apply this operation to an LWP, and - * the LWP's ctl file descriptor might not be open. - */ + /* We might conceivably apply this operation to an LWP, and the + LWP's ctl file descriptor might not be open. */ if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0) @@ -1634,6 +1560,7 @@ proc_stop_process (procinfo *pi) { #ifdef NEW_PROC_API 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); @@ -1641,9 +1568,9 @@ proc_stop_process (procinfo *pi) if (win) { pi->status_valid = 1; - PROC_PRETTYFPRINT_STATUS (proc_flags (pi), + PROC_PRETTYFPRINT_STATUS (proc_flags (pi), proc_why (pi), - proc_what (pi), + proc_what (pi), proc_get_current_thread (pi)); } #endif @@ -1652,31 +1579,26 @@ proc_stop_process (procinfo *pi) return win; } -/* - * Function: proc_wait_for_stop - * - * Wait for the process or LWP to stop (block until it does). - * Returns non-zero for success, zero for failure. - */ +/* Wait for the process or LWP to stop (block until it does). Returns + non-zero for success, zero for failure. */ int proc_wait_for_stop (procinfo *pi) { int win; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); #ifdef NEW_PROC_API { 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; @@ -1687,9 +1609,9 @@ proc_wait_for_stop (procinfo *pi) if (win) { pi->status_valid = 1; - PROC_PRETTYFPRINT_STATUS (proc_flags (pi), + PROC_PRETTYFPRINT_STATUS (proc_flags (pi), proc_why (pi), - proc_what (pi), + proc_what (pi), proc_get_current_thread (pi)); } #endif @@ -1697,31 +1619,24 @@ proc_wait_for_stop (procinfo *pi) return win; } -/* - * Function: proc_run_process - * - * Make the process or LWP runnable. - * Options (not all are implemented): - * - single-step - * - clear current fault - * - clear current signal - * - abort the current system call - * - stop as soon as finished with system call - * - (ioctl): set traced signal set - * - (ioctl): set held signal set - * - (ioctl): set traced fault set - * - (ioctl): set start pc (vaddr) - * Always clear the current fault. - * Clear the current signal if 'signo' is zero. - * - * Arguments: - * pi the process or LWP to operate on. - * step if true, set the process or LWP to trap after one instr. - * signo if zero, clear the current signal if any. - * if non-zero, set the current signal to this one. - * - * Returns non-zero for success, zero for failure. - */ +/* Make the process or LWP runnable. + + Options (not all are implemented): + - single-step + - clear current fault + - clear current signal + - abort the current system call + - stop as soon as finished with system call + - (ioctl): set traced signal set + - (ioctl): set held signal set + - (ioctl): set traced fault set + - (ioctl): set start pc (vaddr) + + Always clears the current fault. PI is the process or LWP to + operate on. If STEP is true, set the process or LWP to trap after + one instruction. If SIGNO is zero, clear the current signal if + any; if non-zero, set the current signal to this one. Returns + non-zero for success, zero for failure. */ int proc_run_process (procinfo *pi, int step, int signo) @@ -1729,23 +1644,21 @@ proc_run_process (procinfo *pi, int step, int signo) int win; int runflags; - /* - * We will probably have to apply this operation to individual threads, - * so make sure the control file descriptor is open. - */ - + /* We will probably have to apply this operation to individual + threads, so make sure the control file descriptor is open. */ + if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0) { return 0; } - runflags = PRCFAULT; /* always clear current fault */ + runflags = PRCFAULT; /* Always clear current fault. */ if (step) runflags |= PRSTEP; if (signo == 0) runflags |= PRCSIG; - else if (signo != -1) /* -1 means do nothing W.R.T. signals */ + else if (signo != -1) /* -1 means do nothing W.R.T. signals. */ proc_set_current_signal (pi, signo); #ifdef NEW_PROC_API @@ -1769,25 +1682,19 @@ proc_run_process (procinfo *pi, int step, int signo) return win; } -/* - * Function: proc_set_traced_signals - * - * Register to trace signals in the process or LWP. - * Returns non-zero for success, zero for failure. - */ +/* Register to trace signals in the process or LWP. Returns non-zero + for success, zero for failure. */ int proc_set_traced_signals (procinfo *pi, gdb_sigset_t *sigset) { int win; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -1807,33 +1714,27 @@ proc_set_traced_signals (procinfo *pi, gdb_sigset_t *sigset) #else /* ioctl method */ win = (ioctl (pi->ctl_fd, PIOCSTRACE, sigset) >= 0); #endif - /* The above operation renders the procinfo's cached pstatus obsolete. */ + /* The above operation renders the procinfo's cached pstatus obsolete. */ pi->status_valid = 0; if (!win) - warning ("procfs: set_traced_signals failed"); + warning (_("procfs: set_traced_signals failed")); return win; } -/* - * Function: proc_set_traced_faults - * - * Register to trace hardware faults in the process or LWP. - * Returns non-zero for success, zero for failure. - */ +/* Register to trace hardware faults in the process or LWP. Returns + non-zero for success, zero for failure. */ int proc_set_traced_faults (procinfo *pi, fltset_t *fltset) { int win; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -1853,31 +1754,25 @@ proc_set_traced_faults (procinfo *pi, fltset_t *fltset) #else /* ioctl method */ win = (ioctl (pi->ctl_fd, PIOCSFAULT, fltset) >= 0); #endif - /* The above operation renders the procinfo's cached pstatus obsolete. */ + /* The above operation renders the procinfo's cached pstatus obsolete. */ pi->status_valid = 0; return win; } -/* - * Function: proc_set_traced_sysentry - * - * Register to trace entry to system calls in the process or LWP. - * Returns non-zero for success, zero for failure. - */ +/* Register to trace entry to system calls in the process or LWP. + Returns non-zero for success, zero for failure. */ int proc_set_traced_sysentry (procinfo *pi, sysset_t *sysset) { int win; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -1889,7 +1784,7 @@ proc_set_traced_sysentry (procinfo *pi, sysset_t *sysset) char sysset[sizeof (sysset_t)]; } *argp; int argp_size = sizeof (struct gdb_proc_ctl_pcsentry) - - sizeof (sysset_t) + - sizeof (sysset_t) + sysset_t_size (pi); argp = xmalloc (argp_size); @@ -1903,31 +1798,26 @@ proc_set_traced_sysentry (procinfo *pi, sysset_t *sysset) #else /* ioctl method */ win = (ioctl (pi->ctl_fd, PIOCSENTRY, sysset) >= 0); #endif - /* The above operation renders the procinfo's cached pstatus obsolete. */ + /* The above operation renders the procinfo's cached pstatus + obsolete. */ pi->status_valid = 0; - + return win; } -/* - * Function: proc_set_traced_sysexit - * - * Register to trace exit from system calls in the process or LWP. - * Returns non-zero for success, zero for failure. - */ +/* Register to trace exit from system calls in the process or LWP. + Returns non-zero for success, zero for failure. */ int proc_set_traced_sysexit (procinfo *pi, sysset_t *sysset) { int win; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -1939,7 +1829,7 @@ proc_set_traced_sysexit (procinfo *pi, sysset_t *sysset) char sysset[sizeof (sysset_t)]; } *argp; int argp_size = sizeof (struct gdb_proc_ctl_pcsexit) - - sizeof (sysset_t) + - sizeof (sysset_t) + sysset_t_size (pi); argp = xmalloc (argp_size); @@ -1953,31 +1843,26 @@ proc_set_traced_sysexit (procinfo *pi, sysset_t *sysset) #else /* ioctl method */ win = (ioctl (pi->ctl_fd, PIOCSEXIT, sysset) >= 0); #endif - /* The above operation renders the procinfo's cached pstatus obsolete. */ + /* The above operation renders the procinfo's cached pstatus + obsolete. */ pi->status_valid = 0; return win; } -/* - * Function: proc_set_held_signals - * - * Specify the set of blocked / held signals in the process or LWP. - * Returns non-zero for success, zero for failure. - */ +/* Specify the set of blocked / held signals in the process or LWP. + Returns non-zero for success, zero for failure. */ int proc_set_held_signals (procinfo *pi, gdb_sigset_t *sighold) { int win; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -1996,31 +1881,26 @@ proc_set_held_signals (procinfo *pi, gdb_sigset_t *sighold) #else win = (ioctl (pi->ctl_fd, PIOCSHOLD, sighold) >= 0); #endif - /* The above operation renders the procinfo's cached pstatus obsolete. */ + /* The above operation renders the procinfo's cached pstatus + obsolete. */ pi->status_valid = 0; return win; } -/* - * Function: proc_get_pending_signals - * - * returns the set of signals that are pending in the process or LWP. - * Will also copy the sigset if 'save' is non-zero. - */ +/* Returns the set of signals that are pending in the process or LWP. + Will also copy the sigset if SAVE is non-zero. */ gdb_sigset_t * proc_get_pending_signals (procinfo *pi, gdb_sigset_t *save) { gdb_sigset_t *ret = NULL; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -2039,25 +1919,19 @@ proc_get_pending_signals (procinfo *pi, gdb_sigset_t *save) return ret; } -/* - * Function: proc_get_signal_actions - * - * returns the set of signal actions. - * Will also copy the sigactionset if 'save' is non-zero. - */ +/* Returns the set of signal actions. Will also copy the sigactionset + if SAVE is non-zero. */ gdb_sigaction_t * proc_get_signal_actions (procinfo *pi, gdb_sigaction_t *save) { gdb_sigaction_t *ret = NULL; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -2076,25 +1950,19 @@ proc_get_signal_actions (procinfo *pi, gdb_sigaction_t *save) return ret; } -/* - * Function: proc_get_held_signals - * - * returns the set of signals that are held / blocked. - * Will also copy the sigset if 'save' is non-zero. - */ +/* Returns the set of signals that are held / blocked. Will also copy + the sigset if SAVE is non-zero. */ gdb_sigset_t * proc_get_held_signals (procinfo *pi, gdb_sigset_t *save) { gdb_sigset_t *ret = NULL; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -2122,25 +1990,19 @@ proc_get_held_signals (procinfo *pi, gdb_sigset_t *save) return ret; } -/* - * Function: proc_get_traced_signals - * - * returns the set of signals that are traced / debugged. - * Will also copy the sigset if 'save' is non-zero. - */ +/* Returns the set of signals that are traced / debugged. Will also + copy the sigset if SAVE is non-zero. */ gdb_sigset_t * proc_get_traced_signals (procinfo *pi, gdb_sigset_t *save) { gdb_sigset_t *ret = NULL; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -2164,25 +2026,19 @@ proc_get_traced_signals (procinfo *pi, gdb_sigset_t *save) return ret; } -/* - * Function: proc_trace_signal - * - * Add 'signo' to the set of signals that are traced. - * Returns non-zero for success, zero for failure. - */ +/* Add SIGNO to the set of signals that are traced. Returns non-zero + for success, zero for failure. */ int proc_trace_signal (procinfo *pi, int signo) { gdb_sigset_t temp; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -2190,7 +2046,7 @@ proc_trace_signal (procinfo *pi, int signo) { if (proc_get_traced_signals (pi, &temp)) { - praddset (&temp, signo); + gdb_praddset (&temp, signo); return proc_set_traced_signals (pi, &temp); } } @@ -2198,25 +2054,19 @@ proc_trace_signal (procinfo *pi, int signo) return 0; /* failure */ } -/* - * Function: proc_ignore_signal - * - * Remove 'signo' from the set of signals that are traced. - * Returns non-zero for success, zero for failure. - */ +/* Remove SIGNO from the set of signals that are traced. Returns + non-zero for success, zero for failure. */ int proc_ignore_signal (procinfo *pi, int signo) { gdb_sigset_t temp; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -2224,7 +2074,7 @@ proc_ignore_signal (procinfo *pi, int signo) { if (proc_get_traced_signals (pi, &temp)) { - prdelset (&temp, signo); + gdb_prdelset (&temp, signo); return proc_set_traced_signals (pi, &temp); } } @@ -2232,25 +2082,19 @@ proc_ignore_signal (procinfo *pi, int signo) return 0; /* failure */ } -/* - * Function: proc_get_traced_faults - * - * returns the set of hardware faults that are traced /debugged. - * Will also copy the faultset if 'save' is non-zero. - */ +/* Returns the set of hardware faults that are traced /debugged. Will + also copy the faultset if SAVE is non-zero. */ fltset_t * proc_get_traced_faults (procinfo *pi, fltset_t *save) { fltset_t *ret = NULL; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -2274,25 +2118,19 @@ proc_get_traced_faults (procinfo *pi, fltset_t *save) return ret; } -/* - * Function: proc_get_traced_sysentry - * - * returns the set of syscalls that are traced /debugged on entry. - * Will also copy the syscall set if 'save' is non-zero. - */ +/* Returns the set of syscalls that are traced /debugged on entry. + Will also copy the syscall set if SAVE is non-zero. */ sysset_t * proc_get_traced_sysentry (procinfo *pi, sysset_t *save) { sysset_t *ret = NULL; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -2322,7 +2160,7 @@ proc_get_traced_sysentry (procinfo *pi, sysset_t *save) int rsize; if (lseek (pi->status_fd, (off_t) pi->prstatus.pr_sysentry_offset, - SEEK_SET) + SEEK_SET) != (off_t) pi->prstatus.pr_sysentry_offset) return NULL; size = sysset_t_size (pi); @@ -2347,25 +2185,19 @@ proc_get_traced_sysentry (procinfo *pi, sysset_t *save) return ret; } -/* - * Function: proc_get_traced_sysexit - * - * returns the set of syscalls that are traced /debugged on exit. - * Will also copy the syscall set if 'save' is non-zero. - */ +/* Returns the set of syscalls that are traced /debugged on exit. + Will also copy the syscall set if SAVE is non-zero. */ sysset_t * proc_get_traced_sysexit (procinfo *pi, sysset_t *save) { sysset_t * ret = NULL; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -2394,7 +2226,8 @@ proc_get_traced_sysexit (procinfo *pi, sysset_t *save) { int rsize; - if (lseek (pi->status_fd, (off_t) pi->prstatus.pr_sysexit_offset, SEEK_SET) + 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); @@ -2419,32 +2252,27 @@ proc_get_traced_sysexit (procinfo *pi, sysset_t *save) return ret; } -/* - * Function: proc_clear_current_fault - * - * The current fault (if any) is cleared; the associated signal - * will not be sent to the process or LWP when it resumes. - * Returns non-zero for success, zero for failure. - */ +/* The current fault (if any) is cleared; the associated signal will + not be sent to the process or LWP when it resumes. Returns + non-zero for success, zero for failure. */ int proc_clear_current_fault (procinfo *pi) { int win; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); #ifdef NEW_PROC_API { procfs_ctl_t cmd = PCCFAULT; + win = (write (pi->ctl_fd, (void *) &cmd, sizeof (cmd)) == sizeof (cmd)); } #else @@ -2454,18 +2282,13 @@ proc_clear_current_fault (procinfo *pi) return win; } -/* - * Function: proc_set_current_signal - * - * Set the "current signal" that will be delivered next to the process. - * NOTE: semantics are different from those of KILL. - * This signal will be delivered to the process or LWP - * immediately when it is resumed (even if the signal is held/blocked); - * it will NOT immediately cause another event of interest, and will NOT - * first trap back to the debugger. - * - * Returns non-zero for success, zero for failure. - */ +/* Set the "current signal" that will be delivered next to the + process. NOTE: semantics are different from those of KILL. This + signal will be delivered to the process or LWP immediately when it + is resumed (even if the signal is held/blocked); it will NOT + immediately cause another event of interest, and will NOT first + trap back to the debugger. Returns non-zero for success, zero for + failure. */ int proc_set_current_signal (procinfo *pi, int signo) @@ -2476,34 +2299,55 @@ proc_set_current_signal (procinfo *pi, int signo) /* Use char array to avoid alignment issues. */ char sinfo[sizeof (gdb_siginfo_t)]; } arg; - gdb_siginfo_t *mysinfo; + gdb_siginfo_t mysinfo; + ptid_t wait_ptid; + struct target_waitstatus wait_status; + + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); #ifdef PROCFS_DONT_PIOCSSIG_CURSIG /* With Alpha OSF/1 procfs, the kernel gets really confused if it - * receives a PIOCSSIG with a signal identical to the current signal, - * it messes up the current signal. Work around the kernel bug. - */ + receives a PIOCSSIG with a signal identical to the current + signal, it messes up the current signal. Work around the kernel + bug. */ if (signo > 0 && signo == proc_cursig (pi)) - return 1; /* I assume this is a success? */ + return 1; /* I assume this is a success? */ #endif /* The pointer is just a type alias. */ - mysinfo = (gdb_siginfo_t *) &arg.sinfo; - mysinfo->si_signo = signo; - mysinfo->si_code = 0; - mysinfo->si_pid = getpid (); /* ?why? */ - mysinfo->si_uid = getuid (); /* ?why? */ + get_last_target_status (&wait_ptid, &wait_status); + if (ptid_equal (wait_ptid, inferior_ptid) + && wait_status.kind == TARGET_WAITKIND_STOPPED + && wait_status.value.sig == target_signal_from_host (signo) + && proc_get_status (pi) +#ifdef NEW_PROC_API + && pi->prstatus.pr_lwp.pr_info.si_signo == signo +#else + && pi->prstatus.pr_info.si_signo == signo +#endif + ) + /* Use the siginfo associated with the signal being + redelivered. */ +#ifdef NEW_PROC_API + memcpy (arg.sinfo, &pi->prstatus.pr_lwp.pr_info, sizeof (gdb_siginfo_t)); +#else + memcpy (arg.sinfo, &pi->prstatus.pr_info, sizeof (gdb_siginfo_t)); +#endif + else + { + mysinfo.si_signo = signo; + mysinfo.si_code = 0; + mysinfo.si_pid = getpid (); /* ?why? */ + mysinfo.si_uid = getuid (); /* ?why? */ + memcpy (arg.sinfo, &mysinfo, sizeof (gdb_siginfo_t)); + } #ifdef NEW_PROC_API arg.cmd = PCSSIG; @@ -2515,26 +2359,20 @@ proc_set_current_signal (procinfo *pi, int signo) return win; } -/* - * Function: proc_clear_current_signal - * - * The current signal (if any) is cleared, and - * is not sent to the process or LWP when it resumes. - * Returns non-zero for success, zero for failure. - */ +/* The current signal (if any) is cleared, and is not sent to the + process or LWP when it resumes. Returns non-zero for success, zero + for failure. */ int proc_clear_current_signal (procinfo *pi) { int win; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -2545,16 +2383,16 @@ proc_clear_current_signal (procinfo *pi) /* Use char array to avoid alignment issues. */ char sinfo[sizeof (gdb_siginfo_t)]; } arg; - gdb_siginfo_t *mysinfo; + gdb_siginfo_t mysinfo; arg.cmd = PCSSIG; /* The pointer is just a type alias. */ - mysinfo = (gdb_siginfo_t *) &arg.sinfo; - mysinfo->si_signo = 0; - mysinfo->si_code = 0; - mysinfo->si_errno = 0; - mysinfo->si_pid = getpid (); /* ?why? */ - mysinfo->si_uid = getuid (); /* ?why? */ + mysinfo.si_signo = 0; + mysinfo.si_code = 0; + mysinfo.si_errno = 0; + mysinfo.si_pid = getpid (); /* ?why? */ + mysinfo.si_uid = getuid (); /* ?why? */ + memcpy (arg.sinfo, &mysinfo, sizeof (gdb_siginfo_t)); win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg)); } @@ -2565,12 +2403,8 @@ proc_clear_current_signal (procinfo *pi) return win; } -/* - * Function: proc_get_gregs - * - * Get the general registers for the process or LWP. - * Returns non-zero for success, zero for failure. - */ +/* Return the general-purpose registers for the process or LWP + corresponding to PI. Upon failure, return NULL. */ gdb_gregset_t * proc_get_gregs (procinfo *pi) @@ -2579,29 +2413,22 @@ proc_get_gregs (procinfo *pi) if (!proc_get_status (pi)) return NULL; - /* - * OK, sorry about the ifdef's. - * There's three cases instead of two, because - * in this instance Unixware and Solaris/RW differ. - */ + /* OK, sorry about the ifdef's. There's three cases instead of two, + because in this case Unixware and Solaris/RW differ. */ #ifdef NEW_PROC_API -#ifdef UNIXWARE /* ugh, a true architecture dependency */ +# ifdef UNIXWARE /* FIXME: Should be autoconfigured. */ return &pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs; -#else /* not Unixware */ +# else return &pi->prstatus.pr_lwp.pr_reg; -#endif /* Unixware */ -#else /* not NEW_PROC_API */ +# endif +#else return &pi->prstatus.pr_reg; -#endif /* NEW_PROC_API */ +#endif } -/* - * Function: proc_get_fpregs - * - * Get the floating point registers for the process or LWP. - * Returns non-zero for success, zero for failure. - */ +/* Return the general-purpose registers for the process or LWP + corresponding to PI. Upon failure, return NULL. */ gdb_fpregset_t * proc_get_fpregs (procinfo *pi) @@ -2611,25 +2438,24 @@ proc_get_fpregs (procinfo *pi) if (!proc_get_status (pi)) return NULL; -#ifdef UNIXWARE /* a true architecture dependency */ +# ifdef UNIXWARE /* FIXME: Should be autoconfigured. */ return &pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs; -#else +# else return &pi->prstatus.pr_lwp.pr_fpreg; -#endif /* Unixware */ +# endif -#else /* not NEW_PROC_API */ +#else /* not NEW_PROC_API */ if (pi->fpregs_valid) - return &pi->fpregset; /* already got 'em */ + return &pi->fpregset; /* Already got 'em. */ else { - if (pi->ctl_fd == 0 && - open_procinfo_files (pi, FD_CTL) == 0) + if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0) { return NULL; } else { -#ifdef PIOCTGFPREG +# ifdef PIOCTGFPREG struct { long pr_count; tid_t pr_error_thread; @@ -2639,46 +2465,43 @@ proc_get_fpregs (procinfo *pi) thread_fpregs.pr_count = 1; thread_fpregs.thread_1.tid = pi->tid; - if (pi->tid == 0 && - ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset) >= 0) + if (pi->tid == 0 + && ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset) >= 0) { pi->fpregs_valid = 1; - return &pi->fpregset; /* got 'em now! */ + return &pi->fpregset; /* Got 'em now! */ } - else if (pi->tid != 0 && - ioctl (pi->ctl_fd, PIOCTGFPREG, &thread_fpregs) >= 0) + else if (pi->tid != 0 + && ioctl (pi->ctl_fd, PIOCTGFPREG, &thread_fpregs) >= 0) { memcpy (&pi->fpregset, &thread_fpregs.thread_1.pr_fpregs, sizeof (pi->fpregset)); pi->fpregs_valid = 1; - return &pi->fpregset; /* got 'em now! */ + return &pi->fpregset; /* Got 'em now! */ } else { return NULL; } -#else +# else if (ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset) >= 0) { pi->fpregs_valid = 1; - return &pi->fpregset; /* got 'em now! */ + return &pi->fpregset; /* Got 'em now! */ } else { return NULL; } -#endif +# endif } } -#endif +#endif /* NEW_PROC_API */ } -/* - * Function: proc_set_gregs - * - * Write the general registers back to the process or LWP. - * Returns non-zero for success, zero for failure. - */ +/* Write the general-purpose registers back to the process or LWP + corresponding to PI. Return non-zero for success, zero for + failure. */ int proc_set_gregs (procinfo *pi) @@ -2686,11 +2509,11 @@ proc_set_gregs (procinfo *pi) gdb_gregset_t *gregs; int win; - if ((gregs = proc_get_gregs (pi)) == NULL) - return 0; /* get_regs has already warned */ + gregs = proc_get_gregs (pi); + if (gregs == NULL) + return 0; /* proc_get_regs has already warned. */ - if (pi->ctl_fd == 0 && - open_procinfo_files (pi, FD_CTL) == 0) + if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0) { return 0; } @@ -2703,7 +2526,7 @@ proc_set_gregs (procinfo *pi) char gregs[sizeof (gdb_gregset_t)]; } arg; - arg.cmd = PCSREG; + arg.cmd = PCSREG; memcpy (&arg.gregs, gregs, sizeof (arg.gregs)); win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg)); #else @@ -2711,17 +2534,14 @@ proc_set_gregs (procinfo *pi) #endif } - /* Policy: writing the regs invalidates our cache. */ + /* Policy: writing the registers invalidates our cache. */ pi->gregs_valid = 0; return win; } -/* - * Function: proc_set_fpregs - * - * Modify the floating point register set of the process or LWP. - * Returns non-zero for success, zero for failure. - */ +/* Write the floating-pointer registers back to the process or LWP + corresponding to PI. Return non-zero for success, zero for + failure. */ int proc_set_fpregs (procinfo *pi) @@ -2729,11 +2549,11 @@ proc_set_fpregs (procinfo *pi) gdb_fpregset_t *fpregs; int win; - if ((fpregs = proc_get_fpregs (pi)) == NULL) - return 0; /* get_fpregs has already warned */ + fpregs = proc_get_fpregs (pi); + if (fpregs == NULL) + return 0; /* proc_get_fpregs has already warned. */ - if (pi->ctl_fd == 0 && - open_procinfo_files (pi, FD_CTL) == 0) + if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0) { return 0; } @@ -2746,11 +2566,11 @@ proc_set_fpregs (procinfo *pi) char fpregs[sizeof (gdb_fpregset_t)]; } arg; - arg.cmd = PCSFPREG; + arg.cmd = PCSFPREG; memcpy (&arg.fpregs, fpregs, sizeof (arg.fpregs)); win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg)); #else -#ifdef PIOCTSFPREG +# ifdef PIOCTSFPREG if (pi->tid == 0) win = (ioctl (pi->ctl_fd, PIOCSFPREG, fpregs) >= 0); else @@ -2767,33 +2587,27 @@ proc_set_fpregs (procinfo *pi) sizeof (*fpregs)); win = (ioctl (pi->ctl_fd, PIOCTSFPREG, &thread_fpregs) >= 0); } -#else +# else win = (ioctl (pi->ctl_fd, PIOCSFPREG, fpregs) >= 0); -#endif /* osf PIOCTSFPREG */ -#endif /* NEW_PROC_API */ +# endif +#endif /* NEW_PROC_API */ } - /* Policy: writing the regs invalidates our cache. */ + /* Policy: writing the registers invalidates our cache. */ pi->fpregs_valid = 0; return win; } -/* - * Function: proc_kill - * - * Send a signal to the proc or lwp with the semantics of "kill()". - * Returns non-zero for success, zero for failure. - */ +/* Send a signal to the proc or lwp with the semantics of "kill()". + Returns non-zero for success, zero for failure. */ int proc_kill (procinfo *pi, int signo) { int win; - /* - * We might conceivably apply this operation to an LWP, and - * the LWP's ctl file descriptor might not be open. - */ + /* We might conceivably apply this operation to an LWP, and the + LWP's ctl file descriptor might not be open. */ if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0) @@ -2810,7 +2624,7 @@ proc_kill (procinfo *pi, int signo) win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd)); #else /* ioctl method */ /* FIXME: do I need the Alpha OSF fixups present in - procfs.c/unconditionally_kill_inferior? Perhaps only for SIGKILL? */ + procfs.c/unconditionally_kill_inferior? Perhaps only for SIGKILL? */ win = (ioctl (pi->ctl_fd, PIOCKILL, &signo) >= 0); #endif } @@ -2818,23 +2632,17 @@ proc_kill (procinfo *pi, int signo) return win; } -/* - * Function: proc_parent_pid - * - * Find the pid of the process that started this one. - * Returns the parent process pid, or zero. - */ +/* Find the pid of the process that started this one. Returns the + parent process pid, or zero. */ int proc_parent_pid (procinfo *pi) { - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -2845,58 +2653,60 @@ proc_parent_pid (procinfo *pi) return pi->prstatus.pr_ppid; } - /* Convert a target address (a.k.a. CORE_ADDR) into a host address (a.k.a void pointer)! */ +#if (defined (PCWATCH) || defined (PIOCSWATCH)) \ + && !(defined (PIOCOPENLWP) || defined (UNIXWARE)) static void * procfs_address_to_host_pointer (CORE_ADDR addr) { + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; void *ptr; - gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr)); - ADDRESS_TO_POINTER (builtin_type_void_data_ptr, &ptr, addr); + gdb_assert (sizeof (ptr) == TYPE_LENGTH (ptr_type)); + gdbarch_address_to_pointer (target_gdbarch, ptr_type, + (gdb_byte *) &ptr, addr); return ptr; } - -/* - * Function: proc_set_watchpoint - * - */ +#endif int proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags) { -#if !defined (TARGET_HAS_HARDWARE_WATCHPOINTS) +#if !defined (PCWATCH) && !defined (PIOCSWATCH) + /* If neither or these is defined, we can't support watchpoints. + This just avoids possibly failing to compile the below on such + systems. */ return 0; #else -/* Horrible hack! Detect Solaris 2.5, because this doesn't work on 2.5 */ -#if defined (PIOCOPENLWP) || defined (UNIXWARE) /* Solaris 2.5: bail out */ +/* Horrible hack! Detect Solaris 2.5, because this doesn't work on 2.5. */ +#if defined (PIOCOPENLWP) || defined (UNIXWARE) /* Solaris 2.5: bail out. */ return 0; #else struct { procfs_ctl_t cmd; char watch[sizeof (prwatch_t)]; } arg; - prwatch_t *pwatch; + prwatch_t pwatch; - pwatch = (prwatch_t *) &arg.watch; /* NOTE: cagney/2003-02-01: Even more horrible hack. Need to convert a target address into something that can be stored in a native data structure. */ #ifdef PCAGENT /* Horrible hack: only defined on Solaris 2.6+ */ - pwatch->pr_vaddr = (uintptr_t) procfs_address_to_host_pointer (addr); + pwatch.pr_vaddr = (uintptr_t) procfs_address_to_host_pointer (addr); #else - pwatch->pr_vaddr = (caddr_t) procfs_address_to_host_pointer (addr); + pwatch.pr_vaddr = (caddr_t) procfs_address_to_host_pointer (addr); #endif - pwatch->pr_size = len; - pwatch->pr_wflags = wflags; + pwatch.pr_size = len; + pwatch.pr_wflags = wflags; #if defined(NEW_PROC_API) && defined (PCWATCH) arg.cmd = PCWATCH; + memcpy (arg.watch, &pwatch, sizeof (prwatch_t)); return (write (pi->ctl_fd, &arg, sizeof (arg)) == sizeof (arg)); #else #if defined (PIOCSWATCH) - return (ioctl (pi->ctl_fd, PIOCSWATCH, pwatch) >= 0); + return (ioctl (pi->ctl_fd, PIOCSWATCH, &pwatch) >= 0); #else return 0; /* Fail */ #endif @@ -2905,22 +2715,13 @@ proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags) #endif } -#ifdef TM_I386SOL2_H /* Is it hokey to use this? */ +#if (defined(__i386__) || defined(__x86_64__)) && defined (sun) #include -/* - * Function: proc_get_LDT_entry - * - * Inputs: - * procinfo *pi; - * int key; - * - * The 'key' is actually the value of the lower 16 bits of - * the GS register for the LWP that we're interested in. - * - * Return: matching ssh struct (LDT entry). - */ +/* The KEY is actually the value of the lower 16 bits of the GS + register for the LWP that we're interested in. Returns the + matching ssh struct (LDT entry). */ struct ssd * proc_get_LDT_entry (procinfo *pi, int key) @@ -2943,7 +2744,7 @@ proc_get_LDT_entry (procinfo *pi, int key) proc_warn (pi, "proc_get_LDT_entry (open)", __LINE__); return NULL; } - /* Make sure it gets closed again! */ + /* Make sure it gets closed again! */ old_chain = make_cleanup_close (fd); /* Now 'read' thru the table, find a match and return it. */ @@ -2954,11 +2755,11 @@ proc_get_LDT_entry (procinfo *pi, int key) ldt_entry->acc1 == 0 && ldt_entry->acc2 == 0) break; /* end of table */ - /* If key matches, return this entry. */ + /* If key matches, return this entry. */ if (ldt_entry->sel == key) return ldt_entry; } - /* Loop ended, match not found. */ + /* Loop ended, match not found. */ return NULL; #else int nldt, i; @@ -2971,15 +2772,15 @@ proc_get_LDT_entry (procinfo *pi, int key) return NULL; } - /* Allocate space for the number of LDT entries. */ - /* This alloc has to persist, 'cause we return a pointer to it. */ + /* Allocate space for the number of LDT entries. */ + /* This alloc has to persist, 'cause we return a pointer to it. */ if (nldt > nalloc) { - ldt_entry = (struct ssd *) + ldt_entry = (struct ssd *) xrealloc (ldt_entry, (nldt + 1) * sizeof (struct ssd)); nalloc = nldt; } - + /* Read the whole table in one gulp. */ if (ioctl (pi->ctl_fd, PIOCLDT, ldt_entry) < 0) { @@ -2987,17 +2788,47 @@ proc_get_LDT_entry (procinfo *pi, int key) return NULL; } - /* Search the table and return the (first) entry matching 'key'. */ + /* Search the table and return the (first) entry matching 'key'. */ for (i = 0; i < nldt; i++) if (ldt_entry[i].sel == key) return &ldt_entry[i]; - /* Loop ended, match not found. */ + /* Loop ended, match not found. */ return NULL; #endif } -#endif /* TM_I386SOL2_H */ +/* Returns the pointer to the LDT entry of PTID. */ + +struct ssd * +procfs_find_LDT_entry (ptid_t ptid) +{ + gdb_gregset_t *gregs; + int key; + procinfo *pi; + + /* Find procinfo for the lwp. */ + if ((pi = find_procinfo (PIDGET (ptid), TIDGET (ptid))) == NULL) + { + warning (_("procfs_find_LDT_entry: could not find procinfo for %d:%ld."), + PIDGET (ptid), TIDGET (ptid)); + return NULL; + } + /* get its general registers. */ + if ((gregs = proc_get_gregs (pi)) == NULL) + { + warning (_("procfs_find_LDT_entry: could not read gregs for %d:%ld."), + PIDGET (ptid), TIDGET (ptid)); + return NULL; + } + /* Now extract the GS register's lower 16 bits. */ + key = (*gregs)[GS] & 0xffff; + + /* Find the matching entry and return it. */ + return proc_get_LDT_entry (pi, key); +} + +#endif /* =============== END, non-thread part of /proc "MODULE" =============== */ @@ -3006,17 +2837,11 @@ proc_get_LDT_entry (procinfo *pi, int key) /* NOTE: you'll see more ifdefs and duplication of functions here, since there is a different way to do threads on every OS. */ -/* - * Function: proc_get_nthreads - * - * Return the number of threads for the process - */ +/* Returns the number of threads for the process. */ #if defined (PIOCNTHR) && defined (PIOCTLIST) -/* - * OSF version - */ -int +/* OSF version */ +int proc_get_nthreads (procinfo *pi) { int nthreads = 0; @@ -3029,9 +2854,7 @@ proc_get_nthreads (procinfo *pi) #else #if defined (SYS_lwpcreate) || defined (SYS_lwp_create) /* FIXME: multiple */ -/* - * Solaris and Unixware version - */ +/* Solaris and Unixware version */ int proc_get_nthreads (procinfo *pi) { @@ -3039,21 +2862,17 @@ proc_get_nthreads (procinfo *pi) if (!proc_get_status (pi)) return 0; - /* - * NEW_PROC_API: only works for the process procinfo, - * because the LWP procinfos do not get prstatus filled in. - */ -#ifdef NEW_PROC_API - if (pi->tid != 0) /* find the parent process procinfo */ + /* NEW_PROC_API: only works for the process procinfo, because the + LWP procinfos do not get prstatus filled in. */ +#ifdef NEW_PROC_API + if (pi->tid != 0) /* Find the parent process procinfo. */ pi = find_procinfo_or_die (pi->pid, 0); #endif return pi->prstatus.pr_nlwp; } #else -/* - * Default version - */ +/* Default version */ int proc_get_nthreads (procinfo *pi) { @@ -3062,29 +2881,23 @@ proc_get_nthreads (procinfo *pi) #endif #endif -/* - * Function: proc_get_current_thread (LWP version) - * - * Return the ID of the thread that had an event of interest. - * (ie. the one that hit a breakpoint or other traced event). - * All other things being equal, this should be the ID of a - * thread that is currently executing. - */ +/* LWP version. + + Return the ID of the thread that had an event of interest. + (ie. the one that hit a breakpoint or other traced event). All + other things being equal, this should be the ID of a thread that is + currently executing. */ #if defined (SYS_lwpcreate) || defined (SYS_lwp_create) /* FIXME: multiple */ -/* - * Solaris and Unixware version - */ +/* Solaris and Unixware version */ int proc_get_current_thread (procinfo *pi) { - /* - * Note: this should be applied to the root procinfo for the process, - * not to the procinfo for an LWP. If applied to the procinfo for - * an LWP, it will simply return that LWP's ID. In that case, - * find the parent process procinfo. - */ - + /* Note: this should be applied to the root procinfo for the + process, not to the procinfo for an LWP. If applied to the + procinfo for an LWP, it will simply return that LWP's ID. In + that case, find the parent process procinfo. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -3101,13 +2914,11 @@ proc_get_current_thread (procinfo *pi) #else #if defined (PIOCNTHR) && defined (PIOCTLIST) -/* - * OSF version - */ -int +/* OSF version */ +int proc_get_current_thread (procinfo *pi) { -#if 0 /* FIXME: not ready for prime time? */ +#if 0 /* FIXME: not ready for prime time? */ return pi->prstatus.pr_tid; #else return 0; @@ -3115,10 +2926,8 @@ proc_get_current_thread (procinfo *pi) } #else -/* - * Default version - */ -int +/* Default version */ +int proc_get_current_thread (procinfo *pi) { return 0; @@ -3127,16 +2936,10 @@ proc_get_current_thread (procinfo *pi) #endif #endif -/* - * Function: proc_update_threads - * - * Discover the IDs of all the threads within the process, and - * create a procinfo for each of them (chained to the parent). - * - * This unfortunately requires a different method on every OS. - * - * Return: non-zero for success, zero for failure. - */ +/* Discover the IDs of all the threads within the process, and create + a procinfo for each of them (chained to the parent). This + unfortunately requires a different method on every OS. Returns + non-zero for success, zero for failure. */ int proc_delete_dead_threads (procinfo *parent, procinfo *thread, void *ignore) @@ -3151,9 +2954,7 @@ proc_delete_dead_threads (procinfo *parent, procinfo *thread, void *ignore) } #if defined (PIOCLSTATUS) -/* - * Solaris 2.5 (ioctl) version - */ +/* Solaris 2.5 (ioctl) version */ int proc_update_threads (procinfo *pi) { @@ -3162,13 +2963,11 @@ proc_update_threads (procinfo *pi) procinfo *thread; int nlwp, i; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -3183,7 +2982,7 @@ proc_update_threads (procinfo *pi) if (ioctl (pi->ctl_fd, PIOCLSTATUS, prstatus) < 0) proc_error (pi, "update_threads (PIOCLSTATUS)", __LINE__); - /* Skip element zero, which represents the process as a whole. */ + /* Skip element zero, which represents the process as a whole. */ for (i = 1; i < nlwp + 1; i++) { if ((thread = create_procinfo (pi->pid, prstatus[i].pr_who)) == NULL) @@ -3198,9 +2997,7 @@ proc_update_threads (procinfo *pi) } #else #ifdef NEW_PROC_API -/* - * Unixware and Solaris 6 (and later) version - */ +/* Unixware and Solaris 6 (and later) version. */ static void do_closedir_cleanup (void *dir) { @@ -3217,27 +3014,23 @@ proc_update_threads (procinfo *pi) DIR *dirp; int lwpid; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); proc_iterate_over_threads (pi, proc_delete_dead_threads, NULL); - /* - * Unixware - * - * Note: this brute-force method is the only way I know of - * to accomplish this task on Unixware. This method will - * also work on Solaris 2.6 and 2.7. There is a much simpler - * and more elegant way to do this on Solaris, but the margins - * of this manuscript are too small to write it here... ;-) - */ + /* Unixware + + Note: this brute-force method is the only way I know of to + accomplish this task on Unixware. This method will also work on + Solaris 2.6 and 2.7. There is a much simpler and more elegant + way to do this on Solaris, but the margins of this manuscript are + too small to write it here... ;-) */ strcpy (pathname, pi->pathname); strcat (pathname, "/lwp"); @@ -3258,22 +3051,18 @@ proc_update_threads (procinfo *pi) } #else #ifdef PIOCTLIST -/* - * OSF version - */ -int +/* OSF version */ +int proc_update_threads (procinfo *pi) { int nthreads, i; tid_t *threads; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); @@ -3281,10 +3070,10 @@ proc_update_threads (procinfo *pi) nthreads = proc_get_nthreads (pi); if (nthreads < 2) - return 0; /* nothing to do for 1 or fewer threads */ + return 0; /* Nothing to do for 1 or fewer threads. */ threads = xmalloc (nthreads * sizeof (tid_t)); - + if (ioctl (pi->ctl_fd, PIOCTLIST, threads) < 0) proc_error (pi, "procfs: update_threads (PIOCTLIST)", __LINE__); @@ -3298,9 +3087,7 @@ proc_update_threads (procinfo *pi) return 1; } #else -/* - * Default version - */ +/* Default version */ int proc_update_threads (procinfo *pi) { @@ -3310,28 +3097,18 @@ proc_update_threads (procinfo *pi) #endif /* NEW_PROC_API */ #endif /* SOL 2.5 PIOCLSTATUS */ -/* - * Function: proc_iterate_over_threads - * - * Description: - * Given a pointer to a function, call that function once - * for each lwp in the procinfo list, until the function - * returns non-zero, in which event return the value - * returned by the function. - * - * Note: this function does NOT call update_threads. - * If you want to discover new threads first, you must - * call that function explicitly. This function just makes - * a quick pass over the currently-known procinfos. - * - * Arguments: - * pi - parent process procinfo - * func - per-thread function - * ptr - opaque parameter for function. - * - * Return: - * First non-zero return value from the callee, or zero. - */ +/* Given a pointer to a function, call that function once for each lwp + in the procinfo list, until the function returns non-zero, in which + event return the value returned by the function. + + Note: this function does NOT call update_threads. If you want to + discover new threads first, you must call that function explicitly. + This function just makes a quick pass over the currently-known + procinfos. + + PI is the parent process procinfo. FUNC is the per-thread + function. PTR is an opaque parameter for function. Returns the + first non-zero return value from the callee, or zero. */ int proc_iterate_over_threads (procinfo *pi, @@ -3341,19 +3118,17 @@ proc_iterate_over_threads (procinfo *pi, procinfo *thread, *next; int retval = 0; - /* - * We should never have to apply this operation to any procinfo - * except the one for the main process. If that ever changes - * for any reason, then take out the following clause and - * replace it with one that makes sure the ctl_fd is open. - */ - + /* We should never have to apply this operation to any procinfo + except the one for the main process. If that ever changes for + any reason, then take out the following clause and replace it + with one that makes sure the ctl_fd is open. */ + if (pi->tid != 0) pi = find_procinfo_or_die (pi->pid, 0); for (thread = pi->thread_list; thread != NULL; thread = next) { - next = thread->next; /* in case thread is destroyed */ + next = thread->next; /* In case thread is destroyed. */ if ((retval = (*func) (pi, thread, ptr)) != 0) break; } @@ -3367,24 +3142,26 @@ proc_iterate_over_threads (procinfo *pi, /* =================== GDB "MODULE" =================== */ -/* - * Here are all of the gdb target vector functions and their friends. - */ +/* Here are all of the gdb target vector functions and their + friends. */ static ptid_t do_attach (ptid_t ptid); static void do_detach (int signo); -static int register_gdb_signals (procinfo *, gdb_sigset_t *); - -/* - * Function: procfs_debug_inferior - * - * Sets up the inferior to be debugged. - * Registers to trace signals, hardware faults, and syscalls. - * Note: does not set RLC flag: caller may want to customize that. - * - * Returns: zero for success (note! unlike most functions in this module) - * On failure, returns the LINE NUMBER where it failed! - */ +static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum, + int entry_or_exit, int mode, int from_tty); + +/* On mips-irix, we need to insert a breakpoint at __dbx_link during + the startup phase. The following two variables are used to record + the address of the breakpoint, and the code that was replaced by + a breakpoint. */ +static int dbx_link_bpt_addr = 0; +static void *dbx_link_bpt; + +/* Sets up the inferior to be debugged. Registers to trace signals, + hardware faults, and syscalls. Note: does not set RLC flag: caller + may want to customize that. Returns zero for success (note! + unlike most functions in this module); on failure, returns the LINE + NUMBER where it failed! */ static int procfs_debug_inferior (procinfo *pi) @@ -3398,19 +3175,19 @@ procfs_debug_inferior (procinfo *pi) #ifdef PROCFS_DONT_TRACE_FAULTS /* On some systems (OSF), we don't trace hardware faults. Apparently it's enough that we catch them as signals. - Wonder why we don't just do that in general? */ - premptyset (&traced_faults); /* don't trace faults. */ + Wonder why we don't just do that in general? */ + premptyset (&traced_faults); /* don't trace faults. */ #else - /* Register to trace hardware faults in the child. */ - prfillset (&traced_faults); /* trace all faults... */ - prdelset (&traced_faults, FLTPAGE); /* except page fault. */ + /* Register to trace hardware faults in the child. */ + prfillset (&traced_faults); /* trace all faults... */ + gdb_prdelset (&traced_faults, FLTPAGE); /* except page fault. */ #endif if (!proc_set_traced_faults (pi, &traced_faults)) return __LINE__; - /* Register to trace selected signals in the child. */ - premptyset (&traced_signals); - if (!register_gdb_signals (pi, &traced_signals)) + /* Initially, register to trace all signals in the child. */ + prfillset (&traced_signals); + if (!proc_set_traced_signals (pi, &traced_signals)) return __LINE__; @@ -3421,7 +3198,7 @@ procfs_debug_inferior (procinfo *pi) gdb_praddsysset (traced_syscall_entries, SYS_exit); #endif #ifdef SYS_lwpexit - gdb_praddsysset (traced_syscall_entries, SYS_lwpexit); /* And _lwp_exit... */ + gdb_praddsysset (traced_syscall_entries, SYS_lwpexit);/* And _lwp_exit... */ #endif #ifdef SYS_lwp_exit gdb_praddsysset (traced_syscall_entries, SYS_lwp_exit); @@ -3429,6 +3206,7 @@ procfs_debug_inferior (procinfo *pi) #ifdef DYNAMIC_SYSCALLS { int callnum = find_syscall (pi, "_exit"); + if (callnum >= 0) gdb_praddsysset (traced_syscall_entries, callnum); } @@ -3443,7 +3221,7 @@ procfs_debug_inferior (procinfo *pi) /* OSF method for tracing exec syscalls. Quoting: Under Alpha OSF/1 we have to use a PIOCSSPCACT ioctl to trace exits from exec system calls because of the user level loader. */ - /* FIXME: make nice and maybe move into an access function. */ + /* FIXME: make nice and maybe move into an access function. */ { int prfs_flags; @@ -3456,11 +3234,11 @@ procfs_debug_inferior (procinfo *pi) return __LINE__; } #else /* not PRFS_STOPEXEC */ - /* Everyone else's (except OSF) method for tracing exec syscalls */ + /* Everyone else's (except OSF) method for tracing exec syscalls. */ /* GW: Rationale... Not all systems with /proc have all the exec* syscalls with the same names. On the SGI, for example, there is no SYS_exec, but there - *is* a SYS_execv. So, we try to account for that. */ + *is* a SYS_execv. So, we try to account for that. */ traced_syscall_exits = sysset_t_alloc (pi); gdb_premptysysset (traced_syscall_exits); @@ -3479,7 +3257,7 @@ procfs_debug_inferior (procinfo *pi) gdb_praddsysset (traced_syscall_exits, SYS_lwpexit); #endif -#ifdef SYS_lwp_create /* FIXME: once only, please */ +#ifdef SYS_lwp_create /* FIXME: once only, please. */ gdb_praddsysset (traced_syscall_exits, SYS_lwp_create); gdb_praddsysset (traced_syscall_exits, SYS_lwp_exit); #endif @@ -3487,6 +3265,7 @@ procfs_debug_inferior (procinfo *pi) #ifdef DYNAMIC_SYSCALLS { int callnum = find_syscall (pi, "execve"); + if (callnum >= 0) gdb_praddsysset (traced_syscall_exits, callnum); callnum = find_syscall (pi, "ra_execve"); @@ -3504,72 +3283,78 @@ procfs_debug_inferior (procinfo *pi) return 0; } -static void -procfs_attach (char *args, int from_tty) +static void +procfs_attach (struct target_ops *ops, char *args, int from_tty) { char *exec_file; int pid; - if (!args) - error_no_arg ("process-id to attach"); + pid = parse_pid_to_attach (args); - pid = atoi (args); if (pid == getpid ()) - error ("Attaching GDB to itself is not a good idea..."); + error (_("Attaching GDB to itself is not a good idea...")); if (from_tty) { exec_file = get_exec_file (0); if (exec_file) - printf_filtered ("Attaching to program `%s', %s\n", + printf_filtered (_("Attaching to program `%s', %s\n"), exec_file, target_pid_to_str (pid_to_ptid (pid))); else - printf_filtered ("Attaching to %s\n", - target_pid_to_str (pid_to_ptid (pid))); + printf_filtered (_("Attaching to %s\n"), + target_pid_to_str (pid_to_ptid (pid))); fflush (stdout); } inferior_ptid = do_attach (pid_to_ptid (pid)); - push_target (&procfs_ops); + push_target (ops); } -static void -procfs_detach (char *args, int from_tty) +static void +procfs_detach (struct target_ops *ops, char *args, int from_tty) { - char *exec_file; - int signo = 0; + int sig = 0; + int pid = PIDGET (inferior_ptid); + + if (args) + sig = atoi (args); if (from_tty) { + char *exec_file; + exec_file = get_exec_file (0); - if (exec_file == 0) + if (exec_file == NULL) exec_file = ""; - printf_filtered ("Detaching from program: %s %s\n", - exec_file, target_pid_to_str (inferior_ptid)); - fflush (stdout); + + printf_filtered (_("Detaching from program: %s, %s\n"), exec_file, + target_pid_to_str (pid_to_ptid (pid))); + gdb_flush (gdb_stdout); } - if (args) - signo = atoi (args); - - do_detach (signo); + + do_detach (sig); + inferior_ptid = null_ptid; - unpush_target (&procfs_ops); /* Pop out of handling an inferior */ + detach_inferior (pid); + unpush_target (ops); } static ptid_t do_attach (ptid_t ptid) { procinfo *pi; + struct inferior *inf; int fail; + int lwpid; if ((pi = create_procinfo (PIDGET (ptid), 0)) == NULL) - perror ("procfs: out of memory in 'attach'"); + perror (_("procfs: out of memory in 'attach'")); if (!open_procinfo_files (pi, FD_CTL)) { fprintf_filtered (gdb_stderr, "procfs:%d -- ", __LINE__); - sprintf (errmsg, "do_attach: couldn't open /proc file for process %d", + sprintf (errmsg, "do_attach: couldn't open /proc file for process %d", PIDGET (ptid)); dead_procinfo (pi, errmsg, NOKILL); } @@ -3587,7 +3372,7 @@ do_attach (ptid_t ptid) if (!proc_set_run_on_last_close (pi)) dead_procinfo (pi, "do_attach: couldn't set RLC.", NOKILL); - /* Now stop the process. */ + /* Now stop the process. */ if (!proc_stop_process (pi)) dead_procinfo (pi, "do_attach: couldn't stop the process.", NOKILL); pi->ignore_next_sigstop = 1; @@ -3601,7 +3386,7 @@ do_attach (ptid_t ptid) dead_procinfo (pi, "do_attach: couldn't save traced syscall entries.", NOKILL); if (!proc_get_traced_sysexit (pi, pi->saved_exitset)) - dead_procinfo (pi, "do_attach: couldn't save traced syscall exits.", + dead_procinfo (pi, "do_attach: couldn't save traced syscall exits.", NOKILL); if (!proc_get_held_signals (pi, &pi->saved_sighold)) dead_procinfo (pi, "do_attach: couldn't save held signals.", NOKILL); @@ -3609,9 +3394,20 @@ do_attach (ptid_t ptid) if ((fail = procfs_debug_inferior (pi)) != 0) dead_procinfo (pi, "do_attach: failed in procfs_debug_inferior", NOKILL); + inf = current_inferior (); + inferior_appeared (inf, pi->pid); /* Let GDB know that the inferior was attached. */ - attach_flag = 1; - return MERGEPID (pi->pid, proc_get_current_thread (pi)); + inf->attach_flag = 1; + + /* Create a procinfo for the current lwp. */ + lwpid = proc_get_current_thread (pi); + create_procinfo (pi->pid, lwpid); + + /* Add it to gdb's thread list. */ + ptid = MERGEPID (pi->pid, lwpid); + add_thread (ptid); + + return ptid; } static void @@ -3619,7 +3415,7 @@ do_detach (int signo) { procinfo *pi; - /* Find procinfo for the main process */ + /* Find procinfo for the main process. */ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); /* FIXME: threads */ if (signo) if (!proc_set_current_signal (pi, signo)) @@ -3642,7 +3438,7 @@ do_detach (int signo) if (signo || (proc_flags (pi) & (PR_STOPPED | PR_ISTOP))) if (signo || !(pi->was_stopped) || - query ("Was stopped when attached, make it runnable again? ")) + query (_("Was stopped when attached, make it runnable again? "))) { /* Clear any pending signal. */ if (!proc_clear_current_fault (pi)) @@ -3655,139 +3451,110 @@ do_detach (int signo) proc_warn (pi, "do_detach, set_rlc", __LINE__); } - attach_flag = 0; destroy_procinfo (pi); } -/* - * fetch_registers - * - * Since the /proc interface cannot give us individual registers, - * we pay no attention to the (regno) argument, and just fetch them all. - * This results in the possibility that we will do unnecessarily many - * fetches, since we may be called repeatedly for individual registers. - * So we cache the results, and mark the cache invalid when the process - * is resumed. - */ +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. -static void -procfs_fetch_registers (int regno) -{ - gdb_fpregset_t *fpregs; - gdb_gregset_t *gregs; - procinfo *pi; - int pid; - int tid; + ??? Is the following note still relevant? We can't get individual + registers with the PT_GETREGS ptrace(2) request either, yet we + don't bother with caching at all in that case. - pid = PIDGET (inferior_ptid); - tid = TIDGET (inferior_ptid); + NOTE: Since the /proc interface cannot give us individual + registers, we pay no attention to REGNUM, and just fetch them all. + This results in the possibility that we will do unnecessarily many + fetches, since we may be called repeatedly for individual + registers. So we cache the results, and mark the cache invalid + when the process is resumed. */ - /* First look up procinfo for the main process. */ - pi = find_procinfo_or_die (pid, 0); +static void +procfs_fetch_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + gdb_gregset_t *gregs; + procinfo *pi; + int pid = PIDGET (inferior_ptid); + int tid = TIDGET (inferior_ptid); + struct gdbarch *gdbarch = get_regcache_arch (regcache); - /* If the event thread is not the same as GDB's requested thread - (ie. inferior_ptid), then look up procinfo for the requested - thread. */ - if ((tid != 0) && - (tid != proc_get_current_thread (pi))) - pi = find_procinfo_or_die (pid, tid); + pi = find_procinfo_or_die (pid, tid); if (pi == NULL) - error ("procfs: fetch_registers failed to find procinfo for %s", + error (_("procfs: fetch_registers failed to find procinfo for %s"), target_pid_to_str (inferior_ptid)); - if ((gregs = proc_get_gregs (pi)) == NULL) + gregs = proc_get_gregs (pi); + if (gregs == NULL) proc_error (pi, "fetch_registers, get_gregs", __LINE__); - supply_gregset (gregs); + supply_gregset (regcache, (const gdb_gregset_t *) gregs); - if (FP0_REGNUM >= 0) /* need floating point? */ + if (gdbarch_fp0_regnum (gdbarch) >= 0) /* Do we have an FPU? */ { - if ((regno >= 0 && regno < FP0_REGNUM) || - regno == PC_REGNUM || - (DEPRECATED_NPC_REGNUM >= 0 && regno == DEPRECATED_NPC_REGNUM) || - regno == DEPRECATED_FP_REGNUM || - regno == SP_REGNUM) - return; /* not a floating point register */ - - if ((fpregs = proc_get_fpregs (pi)) == NULL) + gdb_fpregset_t *fpregs; + + if ((regnum >= 0 && regnum < gdbarch_fp0_regnum (gdbarch)) + || regnum == gdbarch_pc_regnum (gdbarch) + || regnum == gdbarch_sp_regnum (gdbarch)) + return; /* Not a floating point register. */ + + fpregs = proc_get_fpregs (pi); + if (fpregs == NULL) proc_error (pi, "fetch_registers, get_fpregs", __LINE__); - supply_fpregset (fpregs); + supply_fpregset (regcache, (const gdb_fpregset_t *) fpregs); } } -/* Get ready to modify the registers array. On machines which store - individual registers, this doesn't need to do anything. On - machines which store all the registers in one fell swoop, such as - /proc, this makes sure that registers contains all the registers - from the program being debugged. */ +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. -static void -procfs_prepare_to_store (void) -{ -#ifdef CHILD_PREPARE_TO_STORE - CHILD_PREPARE_TO_STORE (); -#endif -} + NOTE: Since the /proc interface will not read individual registers, + we will cache these requests until the process is resumed, and only + then write them back to the inferior process. -/* - * store_registers - * - * Since the /proc interface will not read individual registers, - * we will cache these requests until the process is resumed, and - * only then write them back to the inferior process. - * - * FIXME: is that a really bad idea? Have to think about cases - * where writing one register might affect the value of others, etc. - */ + FIXME: is that a really bad idea? Have to think about cases where + writing one register might affect the value of others, etc. */ static void -procfs_store_registers (int regno) +procfs_store_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) { - gdb_fpregset_t *fpregs; - gdb_gregset_t *gregs; - procinfo *pi; - int pid; - int tid; - - pid = PIDGET (inferior_ptid); - tid = TIDGET (inferior_ptid); - - /* First find procinfo for main process */ - pi = find_procinfo_or_die (pid, 0); - - /* If current lwp for process is not the same as requested thread - (ie. inferior_ptid), then find procinfo for the requested thread. */ + gdb_gregset_t *gregs; + procinfo *pi; + int pid = PIDGET (inferior_ptid); + int tid = TIDGET (inferior_ptid); + struct gdbarch *gdbarch = get_regcache_arch (regcache); - if ((tid != 0) && - (tid != proc_get_current_thread (pi))) - pi = find_procinfo_or_die (pid, tid); + pi = find_procinfo_or_die (pid, tid); if (pi == NULL) - error ("procfs: store_registers: failed to find procinfo for %s", + error (_("procfs: store_registers: failed to find procinfo for %s"), target_pid_to_str (inferior_ptid)); - if ((gregs = proc_get_gregs (pi)) == NULL) + gregs = proc_get_gregs (pi); + if (gregs == NULL) proc_error (pi, "store_registers, get_gregs", __LINE__); - fill_gregset (gregs, regno); + fill_gregset (regcache, gregs, regnum); if (!proc_set_gregs (pi)) proc_error (pi, "store_registers, set_gregs", __LINE__); - if (FP0_REGNUM >= 0) /* need floating point? */ + if (gdbarch_fp0_regnum (gdbarch) >= 0) /* Do we have an FPU? */ { - if ((regno >= 0 && regno < FP0_REGNUM) || - regno == PC_REGNUM || - (DEPRECATED_NPC_REGNUM >= 0 && regno == DEPRECATED_NPC_REGNUM) || - regno == DEPRECATED_FP_REGNUM || - regno == SP_REGNUM) - return; /* not a floating point register */ - - if ((fpregs = proc_get_fpregs (pi)) == NULL) + gdb_fpregset_t *fpregs; + + if ((regnum >= 0 && regnum < gdbarch_fp0_regnum (gdbarch)) + || regnum == gdbarch_pc_regnum (gdbarch) + || regnum == gdbarch_sp_regnum (gdbarch)) + return; /* Not a floating point register. */ + + fpregs = proc_get_fpregs (pi); + if (fpregs == NULL) proc_error (pi, "store_registers, get_fpregs", __LINE__); - fill_fpregset (fpregs, regno); + fill_fpregset (regcache, fpregs, regnum); if (!proc_set_fpregs (pi)) proc_error (pi, "store_registers, set_fpregs", __LINE__); } @@ -3796,7 +3563,6 @@ 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; @@ -3860,74 +3626,244 @@ syscall_is_lwp_create (procinfo *pi, int scall) return 0; } -/* - * Function: target_wait - * - * Retrieve the next stop event from the child process. - * If child has not stopped yet, wait for it to stop. - * Translate /proc eventcodes (or possibly wait eventcodes) - * into gdb internal event codes. - * - * Return: id of process (and possibly thread) that incurred the event. - * event codes are returned thru a pointer parameter. - */ +/* Remove the breakpoint that we inserted in __dbx_link(). + Does nothing if the breakpoint hasn't been inserted or has already + been removed. */ -static ptid_t -procfs_wait (ptid_t ptid, struct target_waitstatus *status) +static void +remove_dbx_link_breakpoint (void) { - /* First cut: loosely based on original version 2.1 */ - procinfo *pi; - int wstat; - int temp_tid; - ptid_t retval, temp_ptid; - int why, what, flags; - int retry = 0; + if (dbx_link_bpt_addr == 0) + return; -wait_again: + if (deprecated_remove_raw_breakpoint (target_gdbarch, dbx_link_bpt) != 0) + warning (_("Unable to remove __dbx_link breakpoint.")); - retry++; + dbx_link_bpt_addr = 0; + dbx_link_bpt = NULL; +} + +#ifdef SYS_syssgi +/* Return the address of the __dbx_link() function in the file + refernced by ABFD by scanning its symbol table. Return 0 if + the symbol was not found. */ + +static CORE_ADDR +dbx_link_addr (bfd *abfd) +{ + long storage_needed; + asymbol **symbol_table; + long number_of_symbols; + long i; + + storage_needed = bfd_get_symtab_upper_bound (abfd); + if (storage_needed <= 0) + return 0; + + symbol_table = (asymbol **) xmalloc (storage_needed); + make_cleanup (xfree, symbol_table); + + number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); + + for (i = 0; i < number_of_symbols; i++) + { + asymbol *sym = symbol_table[i]; + + if ((sym->flags & BSF_GLOBAL) + && sym->name != NULL && strcmp (sym->name, "__dbx_link") == 0) + return (sym->value + sym->section->vma); + } + + /* Symbol not found, return NULL. */ + return 0; +} + +/* Search the symbol table of the file referenced by FD for a symbol + named __dbx_link(). If found, then insert a breakpoint at this location, + and return nonzero. Return zero otherwise. */ + +static int +insert_dbx_link_bpt_in_file (int fd, CORE_ADDR ignored) +{ + bfd *abfd; + long storage_needed; + CORE_ADDR sym_addr; + + abfd = bfd_fdopenr ("unamed", 0, fd); + if (abfd == NULL) + { + warning (_("Failed to create a bfd: %s."), bfd_errmsg (bfd_get_error ())); + return 0; + } + + if (!bfd_check_format (abfd, bfd_object)) + { + /* Not the correct format, so we can not possibly find the dbx_link + symbol in it. */ + bfd_close (abfd); + return 0; + } + + sym_addr = dbx_link_addr (abfd); + if (sym_addr != 0) + { + /* Insert the breakpoint. */ + dbx_link_bpt_addr = sym_addr; + dbx_link_bpt = deprecated_insert_raw_breakpoint (target_gdbarch, NULL, + sym_addr); + if (dbx_link_bpt == NULL) + { + warning (_("Failed to insert dbx_link breakpoint.")); + bfd_close (abfd); + return 0; + } + bfd_close (abfd); + return 1; + } + + bfd_close (abfd); + return 0; +} + +/* Calls the supplied callback function once for each mapped address + space in the process. The callback function receives an open file + descriptor for the file corresponding to that mapped address space + (if there is one), and the base address of the mapped space. Quit + when the callback function returns a nonzero value, or at teh end + of the mappings. Returns the first non-zero return value of the + callback function, or zero. */ + +static int +solib_mappings_callback (struct prmap *map, int (*func) (int, CORE_ADDR), + void *data) +{ + procinfo *pi = data; + int fd; + +#ifdef NEW_PROC_API + char name[MAX_PROC_NAME_SIZE + sizeof (map->pr_mapname)]; + + if (map->pr_vaddr == 0 && map->pr_size == 0) + return -1; /* sanity */ + + if (map->pr_mapname[0] == 0) + { + fd = -1; /* no map file */ + } + else + { + sprintf (name, "/proc/%d/object/%s", pi->pid, map->pr_mapname); + /* Note: caller's responsibility to close this fd! */ + fd = open_with_retry (name, O_RDONLY); + /* Note: we don't test the above call for failure; + we just pass the FD on as given. Sometimes there is + no file, so the open may return failure, but that's + not a problem. */ + } +#else + fd = ioctl (pi->ctl_fd, PIOCOPENM, &map->pr_vaddr); + /* Note: we don't test the above call for failure; + we just pass the FD on as given. Sometimes there is + no file, so the ioctl may return failure, but that's + not a problem. */ +#endif + return (*func) (fd, (CORE_ADDR) map->pr_vaddr); +} + +/* If the given memory region MAP contains a symbol named __dbx_link, + insert a breakpoint at this location and return nonzero. Return + zero otherwise. */ + +static int +insert_dbx_link_bpt_in_region (struct prmap *map, + find_memory_region_ftype child_func, + void *data) +{ + procinfo *pi = (procinfo *) data; + + /* We know the symbol we're looking for is in a text region, so + only look for it if the region is a text one. */ + if (map->pr_mflags & MA_EXEC) + return solib_mappings_callback (map, insert_dbx_link_bpt_in_file, pi); + + return 0; +} + +/* Search all memory regions for a symbol named __dbx_link. If found, + insert a breakpoint at its location, and return nonzero. Return zero + otherwise. */ + +static int +insert_dbx_link_breakpoint (procinfo *pi) +{ + return iterate_over_mappings (pi, NULL, pi, insert_dbx_link_bpt_in_region); +} +#endif + +/* Retrieve the next stop event from the child process. If child has + not stopped yet, wait for it to stop. Translate /proc eventcodes + (or possibly wait eventcodes) into gdb internal event codes. + Returns the id of process (and possibly thread) that incurred the + event. Event codes are returned through a pointer parameter. */ + +static ptid_t +procfs_wait (struct target_ops *ops, + ptid_t ptid, struct target_waitstatus *status, int options) +{ + /* First cut: loosely based on original version 2.1. */ + procinfo *pi; + int wstat; + int temp_tid; + ptid_t retval, temp_ptid; + int why, what, flags; + int retry = 0; + +wait_again: + + retry++; wstat = 0; retval = pid_to_ptid (-1); - /* Find procinfo for main process */ + /* Find procinfo for main process. */ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); if (pi) { - /* We must assume that the status is stale now... */ + /* We must assume that the status is stale now... */ pi->status_valid = 0; pi->gregs_valid = 0; pi->fpregs_valid = 0; -#if 0 /* just try this out... */ +#if 0 /* just try this out... */ flags = proc_flags (pi); why = proc_why (pi); if ((flags & PR_STOPPED) && (why == PR_REQUESTED)) - pi->status_valid = 0; /* re-read again, IMMEDIATELY... */ + pi->status_valid = 0; /* re-read again, IMMEDIATELY... */ #endif /* If child is not stopped, wait for it to stop. */ if (!(proc_flags (pi) & (PR_STOPPED | PR_ISTOP)) && !proc_wait_for_stop (pi)) { - /* wait_for_stop failed: has the child terminated? */ + /* wait_for_stop failed: has the child terminated? */ if (errno == ENOENT) { int wait_retval; - /* /proc file not found; presumably child has terminated. */ - wait_retval = wait (&wstat); /* "wait" for the child's exit */ + /* /proc file not found; presumably child has terminated. */ + wait_retval = wait (&wstat); /* "wait" for the child's exit. */ - if (wait_retval != PIDGET (inferior_ptid)) /* wrong child? */ - error ("procfs: couldn't stop process %d: wait returned %d\n", + if (wait_retval != PIDGET (inferior_ptid)) /* wrong child? */ + error (_("procfs: couldn't stop " + "process %d: wait returned %d."), PIDGET (inferior_ptid), wait_retval); /* FIXME: might I not just use waitpid? - Or try find_procinfo to see if I know about this child? */ + Or try find_procinfo to see if I know about this child? */ retval = pid_to_ptid (wait_retval); } else if (errno == EINTR) goto wait_again; else { - /* Unknown error from wait_for_stop. */ + /* Unknown error from wait_for_stop. */ proc_error (pi, "target_wait (wait_for_stop)", __LINE__); } } @@ -3940,7 +3876,7 @@ wait_again: into a waitstatus for GDB. If we actually had to call wait because the /proc file - is gone (child terminated), then we skip this block, + is gone (child terminated), then we skip this block, because we already have a waitstatus. */ flags = proc_flags (pi); @@ -3971,30 +3907,35 @@ wait_again: case PR_SYSENTRY: if (syscall_is_lwp_exit (pi, what)) { - printf_filtered ("[%s exited]\n", - target_pid_to_str (retval)); + if (print_thread_events) + printf_unfiltered (_("[%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 */ + struct inferior *inf; + + /* Handle SYS_exit call only. */ /* Stopped at entry to SYS_exit. - Make it runnable, resume it, then use + Make it runnable, resume it, then use the wait system call to get its exit code. - Proc_run_process always clears the current + 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 + /* 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) + + inf = find_inferior_pid (pi->pid); + if (inf->attach_flag) { - /* Don't call wait: simulate waiting for exit, + /* Don't call wait: simulate waiting for exit, return a "success" exit code. Bogus: what if it returns something else? */ wstat = 0; @@ -4011,14 +3952,15 @@ wait_again: somehow, I could get its termination event here. */ - /* If wait returns -1, that's what we return to GDB. */ + /* If wait returns -1, that's what we return + to GDB. */ if (temp < 0) retval = pid_to_ptid (temp); } } else { - printf_filtered ("procfs: trapped on entry to "); + printf_filtered (_("procfs: trapped on entry to ")); proc_prettyprint_syscall (proc_what (pi), 0); printf_filtered ("\n"); #ifndef PIOCSSPCACT @@ -4028,9 +3970,10 @@ wait_again: if ((nsysargs = proc_nsysarg (pi)) > 0 && (sysargs = proc_sysargs (pi)) != NULL) { - printf_filtered ("%ld syscall arguments:\n", nsysargs); + printf_filtered (_("%ld syscall arguments:\n"), + nsysargs); for (i = 0; i < nsysargs; i++) - printf_filtered ("#%ld: 0x%08lx\n", + printf_filtered ("#%ld: 0x%08lx\n", i, sysargs[i]); } @@ -4038,7 +3981,8 @@ wait_again: #endif if (status) { - /* How to exit gracefully, returning "unknown event" */ + /* How to exit gracefully, returning "unknown + event". */ status->kind = TARGET_WAITKIND_SPURIOUS; return inferior_ptid; } @@ -4056,19 +4000,34 @@ wait_again: /* 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. */ + address. */ wstat = (SIGTRAP << 8) | 0177; } +#ifdef SYS_syssgi + else if (what == SYS_syssgi) + { + /* see if we can break on dbx_link(). If yes, then + we no longer need the SYS_syssgi notifications. */ + if (insert_dbx_link_breakpoint (pi)) + proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT, + FLAG_RESET, 0); + + /* This is an internal event and should be transparent + to wfi, so resume the execution and wait again. See + comment in procfs_init_inferior() for more details. */ + target_resume (ptid, 0, TARGET_SIGNAL_0); + goto wait_again; + } +#endif 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. - */ + /* 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 not in procinfo list, add it. */ temp_tid = proc_get_current_thread (pi); @@ -4078,19 +4037,17 @@ wait_again: temp_ptid = MERGEPID (pi->pid, temp_tid); /* If not in GDB's thread list, add it. */ if (!in_thread_list (temp_ptid)) - { - printf_filtered ("[New %s]\n", - target_pid_to_str (temp_ptid)); - add_thread (temp_ptid); - } - /* Return to WFI, but tell it to immediately resume. */ + add_thread (temp_ptid); + + /* Return to WFI, but tell it to immediately resume. */ status->kind = TARGET_WAITKIND_SPURIOUS; return inferior_ptid; } else if (syscall_is_lwp_exit (pi, what)) { - printf_filtered ("[%s exited]\n", - target_pid_to_str (retval)); + if (print_thread_events) + printf_unfiltered (_("[%s exited]\n"), + target_pid_to_str (retval)); delete_thread (retval); status->kind = TARGET_WAITKIND_SPURIOUS; return retval; @@ -4101,12 +4058,12 @@ wait_again: 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. + that threads were actually separate processes. Irix, maybe? Anyway, low priority for now. */ } else { - printf_filtered ("procfs: trapped on exit from "); + printf_filtered (_("procfs: trapped on exit from ")); proc_prettyprint_syscall (proc_what (pi), 0); printf_filtered ("\n"); #ifndef PIOCSSPCACT @@ -4116,9 +4073,10 @@ wait_again: if ((nsysargs = proc_nsysarg (pi)) > 0 && (sysargs = proc_sysargs (pi)) != NULL) { - printf_filtered ("%ld syscall arguments:\n", nsysargs); + printf_filtered (_("%ld syscall arguments:\n"), + nsysargs); for (i = 0; i < nsysargs; i++) - printf_filtered ("#%ld: 0x%08lx\n", + printf_filtered ("#%ld: 0x%08lx\n", i, sysargs[i]); } } @@ -4134,7 +4092,7 @@ wait_again: #else if (retry < 5) { - printf_filtered ("Retry #%d:\n", retry); + printf_filtered (_("Retry #%d:\n"), retry); pi->status_valid = 0; goto wait_again; } @@ -4148,11 +4106,7 @@ wait_again: /* If not in GDB's thread list, add it. */ temp_ptid = MERGEPID (pi->pid, temp_tid); if (!in_thread_list (temp_ptid)) - { - printf_filtered ("[New %s]\n", - target_pid_to_str (temp_ptid)); - add_thread (temp_ptid); - } + add_thread (temp_ptid); status->kind = TARGET_WAITKIND_STOPPED; status->value.sig = 0; @@ -4163,7 +4117,7 @@ wait_again: wstat = (what << 8) | 0177; break; case PR_FAULTED: - switch (what) { /* FIXME: FAULTED_USE_SIGINFO */ + switch (what) { #ifdef FLTWATCH case FLTWATCH: wstat = (SIGTRAP << 8) | 0177; @@ -4174,91 +4128,80 @@ wait_again: wstat = (SIGTRAP << 8) | 0177; break; #endif - /* FIXME: use si_signo where possible. */ + /* FIXME: use si_signo where possible. */ case FLTPRIV: -#if (FLTILL != FLTPRIV) /* avoid "duplicate case" error */ +#if (FLTILL != FLTPRIV) /* Avoid "duplicate case" error. */ case FLTILL: #endif wstat = (SIGILL << 8) | 0177; break; case FLTBPT: -#if (FLTTRACE != FLTBPT) /* avoid "duplicate case" error */ +#if (FLTTRACE != FLTBPT) /* Avoid "duplicate case" error. */ case FLTTRACE: #endif + /* If we hit our __dbx_link() internal breakpoint, + then remove it. See comments in procfs_init_inferior() + for more details. */ + if (dbx_link_bpt_addr != 0 + && dbx_link_bpt_addr + == regcache_read_pc (get_current_regcache ())) + remove_dbx_link_breakpoint (); + wstat = (SIGTRAP << 8) | 0177; break; case FLTSTACK: case FLTACCESS: -#if (FLTBOUNDS != FLTSTACK) /* avoid "duplicate case" error */ +#if (FLTBOUNDS != FLTSTACK) /* Avoid "duplicate case" error. */ case FLTBOUNDS: #endif wstat = (SIGSEGV << 8) | 0177; break; case FLTIOVF: case FLTIZDIV: -#if (FLTFPE != FLTIOVF) /* avoid "duplicate case" error */ +#if (FLTFPE != FLTIOVF) /* Avoid "duplicate case" error. */ case FLTFPE: #endif wstat = (SIGFPE << 8) | 0177; break; - case FLTPAGE: /* Recoverable page fault */ - default: /* FIXME: use si_signo if possible for fault */ + case FLTPAGE: /* Recoverable page fault */ + default: /* FIXME: use si_signo if possible for + fault. */ retval = pid_to_ptid (-1); printf_filtered ("procfs:%d -- ", __LINE__); - printf_filtered ("child stopped for unknown reason:\n"); + printf_filtered (_("child stopped for unknown reason:\n")); proc_prettyprint_why (why, what, 1); - error ("... giving up..."); + error (_("... giving up...")); break; } break; /* case PR_FAULTED: */ default: /* switch (why) unmatched */ printf_filtered ("procfs:%d -- ", __LINE__); - printf_filtered ("child stopped for unknown reason:\n"); + printf_filtered (_("child stopped for unknown reason:\n")); proc_prettyprint_why (why, what, 1); - error ("... giving up..."); + error (_("... giving up...")); break; } - /* - * Got this far without error: - * If retval isn't in the threads database, add it. - */ + /* Got this far without error: If retval isn't in the + threads database, add it. */ if (PIDGET (retval) > 0 && !ptid_equal (retval, inferior_ptid) && !in_thread_list (retval)) { - /* - * We have a new thread. - * We need to add it both to GDB's list and to our own. - * If we don't create a procinfo, resume may be unhappy - * later. - */ - printf_filtered ("[New %s]\n", target_pid_to_str (retval)); + /* We have a new thread. We need to add it both to + GDB's list and to our own. If we don't create a + procinfo, resume may be unhappy later. */ add_thread (retval); if (find_procinfo (PIDGET (retval), TIDGET (retval)) == NULL) create_procinfo (PIDGET (retval), TIDGET (retval)); - - /* In addition, it's possible that this is the first - * new thread we've seen, in which case we may not - * have created entries for inferior_ptid yet. - */ - if (TIDGET (inferior_ptid) != 0) - { - if (!in_thread_list (inferior_ptid)) - add_thread (inferior_ptid); - if (find_procinfo (PIDGET (inferior_ptid), - TIDGET (inferior_ptid)) == NULL) - create_procinfo (PIDGET (inferior_ptid), - TIDGET (inferior_ptid)); - } } } - else /* flags do not indicate STOPPED */ + else /* Flags do not indicate STOPPED. */ { - /* surely this can't happen... */ + /* surely this can't happen... */ printf_filtered ("procfs:%d -- process not stopped.\n", __LINE__); proc_prettyprint_flags (flags, 1); - error ("procfs: ...giving up..."); + error (_("procfs: ...giving up...")); } } @@ -4269,6 +4212,40 @@ wait_again: return retval; } +/* Perform a partial transfer to/from the specified object. For + memory transfers, fall back to the old memory xfer functions. */ + +static LONGEST +procfs_xfer_partial (struct target_ops *ops, enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, ULONGEST offset, LONGEST len) +{ + switch (object) + { + case TARGET_OBJECT_MEMORY: + if (readbuf) + return (*ops->deprecated_xfer_memory) (offset, readbuf, + len, 0/*read*/, NULL, ops); + if (writebuf) + return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf, + len, 1/*write*/, NULL, ops); + return -1; + +#ifdef NEW_PROC_API + case TARGET_OBJECT_AUXV: + return memory_xfer_auxv (ops, object, annex, readbuf, writebuf, + offset, len); +#endif + + default: + if (ops->beneath != NULL) + return ops->beneath->to_xfer_partial (ops->beneath, object, annex, + readbuf, writebuf, offset, len); + return -1; + } +} + + /* Transfer LEN bytes between GDB address MYADDR and target address MEMADDR. If DOWRITE is non-zero, transfer them to the target, otherwise transfer them from the target. TARGET is unused. @@ -4277,16 +4254,16 @@ wait_again: transferred. Otherwise, it will be a positive value which indicates the number of bytes transferred between gdb and the target. (Note that the interface also makes provisions for - negative values, but this capability isn't implemented here.) */ + negative values, but this capability isn't implemented here.) */ static int -procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite, +procfs_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int dowrite, struct mem_attrib *attrib, struct target_ops *target) { procinfo *pi; int nbytes = 0; - /* Find procinfo for main process */ + /* Find procinfo for main process. */ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); if (pi->as_fd == 0 && open_procinfo_files (pi, FD_AS) == 0) @@ -4300,15 +4277,15 @@ procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite, if (dowrite) { #ifdef NEW_PROC_API - PROCFS_NOTE ("write memory: "); + PROCFS_NOTE ("write memory:\n"); #else - PROCFS_NOTE ("write memory: \n"); + PROCFS_NOTE ("write memory:\n"); #endif nbytes = write (pi->as_fd, myaddr, len); } else { - PROCFS_NOTE ("read memory: \n"); + PROCFS_NOTE ("read memory:\n"); nbytes = read (pi->as_fd, myaddr, len); } if (nbytes < 0) @@ -4319,33 +4296,26 @@ procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite, return nbytes; } -/* - * Function: invalidate_cache - * - * Called by target_resume before making child runnable. - * Mark cached registers and status's invalid. - * If there are "dirty" caches that need to be written back - * to the child process, do that. - * - * File descriptors are also cached. - * As they are a limited resource, we cannot hold onto them indefinitely. - * However, as they are expensive to open, we don't want to throw them - * away indescriminately either. As a compromise, we will keep the - * file descriptors for the parent process, but discard any file - * descriptors we may have accumulated for the threads. - * - * Return value: - * As this function is called by iterate_over_threads, it always - * returns zero (so that iterate_over_threads will keep iterating). - */ +/* Called by target_resume before making child runnable. Mark cached + registers and status's invalid. If there are "dirty" caches that + need to be written back to the child process, do that. + File descriptors are also cached. As they are a limited resource, + we cannot hold onto them indefinitely. However, as they are + expensive to open, we don't want to throw them away + indescriminately either. As a compromise, we will keep the file + descriptors for the parent process, but discard any file + descriptors we may have accumulated for the threads. + + As this function is called by iterate_over_threads, it always + returns zero (so that iterate_over_threads will keep + iterating). */ static int invalidate_cache (procinfo *parent, procinfo *pi, void *ptr) { - /* - * About to run the child; invalidate caches and do any other cleanup. - */ + /* About to run the child; invalidate caches and do any other + cleanup. */ #if 0 if (pi->gregs_dirty) @@ -4354,19 +4324,19 @@ invalidate_cache (procinfo *parent, procinfo *pi, void *ptr) if (!proc_set_gregs (pi)) /* flush gregs cache */ proc_warn (pi, "target_resume, set_gregs", __LINE__); - if (FP0_REGNUM >= 0) + if (gdbarch_fp0_regnum (target_gdbarch) >= 0) if (pi->fpregs_dirty) if (parent == NULL || proc_get_current_thread (parent) != pi->tid) if (!proc_set_fpregs (pi)) /* flush fpregs cache */ - proc_warn (pi, "target_resume, set_fpregs", + proc_warn (pi, "target_resume, set_fpregs", __LINE__); #endif if (parent != NULL) { /* The presence of a parent indicates that this is an LWP. - Close any file descriptors that it might have open. + Close any file descriptors that it might have open. We don't do this to the master (parent) procinfo. */ close_procinfo_files (pi); @@ -4384,13 +4354,9 @@ invalidate_cache (procinfo *parent, procinfo *pi, void *ptr) } #if 0 -/* - * Function: make_signal_thread_runnable - * - * A callback function for iterate_over_threads. - * Find the asynchronous signal thread, and make it runnable. - * See if that helps matters any. - */ +/* A callback function for iterate_over_threads. Find the + asynchronous signal thread, and make it runnable. See if that + helps matters any. */ static int make_signal_thread_runnable (procinfo *process, procinfo *pi, void *ptr) @@ -4407,49 +4373,43 @@ make_signal_thread_runnable (procinfo *process, procinfo *pi, void *ptr) } #endif -/* - * Function: target_resume - * - * Make the child process runnable. Normally we will then call - * procfs_wait and wait for it to stop again (unles gdb is async). - * - * Arguments: - * step: if true, then arrange for the child to stop again - * after executing a single instruction. - * signo: if zero, then cancel any pending signal. - * If non-zero, then arrange for the indicated signal - * to be delivered to the child when it runs. - * pid: if -1, then allow any child thread to run. - * if non-zero, then allow only the indicated thread to run. - ******* (not implemented yet) - */ +/* Make the child process runnable. Normally we will then call + procfs_wait and wait for it to stop again (unless gdb is async). + + If STEP is true, then arrange for the child to stop again after + executing a single instruction. If SIGNO is zero, then cancel any + pending signal; if non-zero, then arrange for the indicated signal + to be delivered to the child when it runs. If PID is -1, then + allow any child thread to run; if non-zero, then allow only the + indicated thread to run. (not implemented yet). */ static void -procfs_resume (ptid_t ptid, int step, enum target_signal signo) +procfs_resume (struct target_ops *ops, + ptid_t ptid, int step, enum target_signal signo) { procinfo *pi, *thread; int native_signo; - /* 2.1: + /* 2.1: prrun.prflags |= PRSVADDR; - prrun.pr_vaddr = $PC; set resume address + prrun.pr_vaddr = $PC; set resume address prrun.prflags |= PRSTRACE; trace signals in pr_trace (all) - prrun.prflags |= PRSFAULT; trace faults in pr_fault (all but PAGE) + prrun.prflags |= PRSFAULT; trace faults in pr_fault (all but PAGE) prrun.prflags |= PRCFAULT; clear current fault. PRSTRACE and PRSFAULT can be done by other means - (proc_trace_signals, proc_trace_faults) + (proc_trace_signals, proc_trace_faults) PRSVADDR is unnecessary. PRCFAULT may be replaced by a PIOCCFAULT call (proc_clear_current_fault) This basically leaves PRSTEP and PRCSIG. PRCSIG is like PIOCSSIG (proc_clear_current_signal). So basically PR_STEP is the sole argument that must be passed - to proc_run_process (for use in the prrun struct by ioctl). */ + to proc_run_process (for use in the prrun struct by ioctl). */ - /* Find procinfo for main process */ + /* Find procinfo for main process. */ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); - /* First cut: ignore pid argument */ + /* First cut: ignore pid argument. */ errno = 0; /* Convert signal to host numbering. */ @@ -4461,33 +4421,34 @@ procfs_resume (ptid_t ptid, int step, enum target_signal signo) pi->ignore_next_sigstop = 0; - /* Running the process voids all cached registers and status. */ - /* Void the threads' caches first */ - proc_iterate_over_threads (pi, invalidate_cache, NULL); + /* Running the process voids all cached registers and status. */ + /* Void the threads' caches first. */ + proc_iterate_over_threads (pi, invalidate_cache, NULL); /* Void the process procinfo's caches. */ invalidate_cache (NULL, pi, NULL); if (PIDGET (ptid) != -1) { - /* Resume a specific thread, presumably suppressing the others. */ + /* Resume a specific thread, presumably suppressing the + others. */ thread = find_procinfo (PIDGET (ptid), TIDGET (ptid)); if (thread != NULL) { if (thread->tid != 0) { - /* We're to resume a specific thread, and not the others. - * Set the child process's PR_ASYNC flag. - */ + /* We're to resume a specific thread, and not the + others. Set the child process's PR_ASYNC flag. */ #ifdef PR_ASYNC if (!proc_set_async (pi)) proc_error (pi, "target_resume, set_async", __LINE__); #endif #if 0 - proc_iterate_over_threads (pi, + proc_iterate_over_threads (pi, make_signal_thread_runnable, NULL); #endif - pi = thread; /* substitute the thread's procinfo for run */ + pi = thread; /* Substitute the thread's procinfo + for run. */ } } } @@ -4495,132 +4456,61 @@ procfs_resume (ptid_t ptid, int step, enum target_signal signo) if (!proc_run_process (pi, step, native_signo)) { if (errno == EBUSY) - warning ("resume: target already running. Pretend to resume, and hope for the best!\n"); + warning (_("resume: target already running. " + "Pretend to resume, and hope for the best!")); else proc_error (pi, "target_resume", __LINE__); } } -/* - * Function: register_gdb_signals - * - * Traverse the list of signals that GDB knows about - * (see "handle" command), and arrange for the target - * to be stopped or not, according to these settings. - * - * Returns non-zero for success, zero for failure. - */ - -static int -register_gdb_signals (procinfo *pi, gdb_sigset_t *signals) -{ - int signo; - - for (signo = 0; signo < NSIG; signo ++) - if (signal_stop_state (target_signal_from_host (signo)) == 0 && - signal_print_state (target_signal_from_host (signo)) == 0 && - signal_pass_state (target_signal_from_host (signo)) == 1) - prdelset (signals, signo); - else - praddset (signals, signo); - - return proc_set_traced_signals (pi, signals); -} - -/* - * Function: target_notice_signals - * - * Set up to trace signals in the child process. - */ +/* Set up to trace signals in the child process. */ static void -procfs_notice_signals (ptid_t ptid) +procfs_pass_signals (int numsigs, unsigned char *pass_signals) { gdb_sigset_t signals; - procinfo *pi = find_procinfo_or_die (PIDGET (ptid), 0); + procinfo *pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); + int signo; - if (proc_get_traced_signals (pi, &signals) && - register_gdb_signals (pi, &signals)) - return; - else - proc_error (pi, "notice_signals", __LINE__); -} + prfillset (&signals); -/* - * Function: target_files_info - * - * Print status information about the child process. - */ + for (signo = 0; signo < NSIG; signo++) + { + int target_signo = target_signal_from_host (signo); + if (target_signo < numsigs && pass_signals[target_signo]) + gdb_prdelset (&signals, signo); + } -static void -procfs_files_info (struct target_ops *ignore) -{ - printf_filtered ("\tUsing the running image of %s %s via /proc.\n", - attach_flag? "attached": "child", - target_pid_to_str (inferior_ptid)); + if (!proc_set_traced_signals (pi, &signals)) + proc_error (pi, "pass_signals", __LINE__); } -/* - * Function: target_open - * - * A dummy: you don't open procfs. - */ +/* Print status information about the child process. */ static void -procfs_open (char *args, int from_tty) -{ - error ("Use the \"run\" command to start a Unix child process."); -} - -/* - * Function: target_can_run - * - * This tells GDB that this target vector can be invoked - * for "run" or "attach". - */ - -int procfs_suppress_run = 0; /* Non-zero if procfs should pretend not to - be a runnable target. Used by targets - that can sit atop procfs, such as solaris - thread support. */ - - -static int -procfs_can_run (void) +procfs_files_info (struct target_ops *ignore) { - /* This variable is controlled by modules that sit atop procfs that - may layer their own process structure atop that provided here. - sol-thread.c does this because of the Solaris two-level thread - model. */ - - /* NOTE: possibly obsolete -- use the thread_stratum approach instead. */ + struct inferior *inf = current_inferior (); - return !procfs_suppress_run; + printf_filtered (_("\tUsing the running image of %s %s via /proc.\n"), + inf->attach_flag? "attached": "child", + target_pid_to_str (inferior_ptid)); } -/* - * Function: target_stop - * - * Stop the child process asynchronously, as when the - * gdb user types control-c or presses a "stop" button. - * - * Works by sending kill(SIGINT) to the child's process group. - */ +/* Stop the child process asynchronously, as when the gdb user types + control-c or presses a "stop" button. Works by sending + kill(SIGINT) to the child's process group. */ static void -procfs_stop (void) +procfs_stop (ptid_t ptid) { - kill (-inferior_process_group, SIGINT); + kill (-inferior_process_group (), SIGINT); } -/* - * Function: unconditionally_kill_inferior - * - * Make it die. Wait for it to die. Clean up after it. - * Note: this should only be applied to the real process, - * not to an LWP, because of the check for parent-process. - * If we need this to work for an LWP, it needs some more logic. - */ +/* Make it die. Wait for it to die. Clean up after it. Note: this + should only be applied to the real process, not to an LWP, because + of the check for parent-process. If we need this to work for an + LWP, it needs some more logic. */ static void unconditionally_kill_inferior (procinfo *pi) @@ -4629,7 +4519,7 @@ unconditionally_kill_inferior (procinfo *pi) parent_pid = proc_parent_pid (pi); #ifdef PROCFS_NEED_CLEAR_CURSIG_FOR_KILL - /* FIXME: use access functions */ + /* FIXME: use access functions. */ /* Alpha OSF/1-3.x procfs needs a clear of the current signal before the PIOCKILL, otherwise it might generate a corrupted core file for the inferior. */ @@ -4653,7 +4543,7 @@ unconditionally_kill_inferior (procinfo *pi) newsiginfo.si_errno = 0; newsiginfo.si_pid = getpid (); newsiginfo.si_uid = getuid (); - /* FIXME: use proc_set_current_signal */ + /* FIXME: use proc_set_current_signal. */ ioctl (pi->ctl_fd, PIOCSSIG, &newsiginfo); } #else /* PROCFS_NEED_PIOCSSIG_FOR_KILL */ @@ -4664,7 +4554,7 @@ unconditionally_kill_inferior (procinfo *pi) /* If pi is GDB's child, wait for it to die. */ if (parent_pid == getpid ()) - /* FIXME: should we use waitpid to make sure we get the right event? + /* FIXME: should we use waitpid to make sure we get the right event? Should we check the returned event? */ { #if 0 @@ -4677,19 +4567,15 @@ unconditionally_kill_inferior (procinfo *pi) } } -/* - * Function: target_kill_inferior - * - * We're done debugging it, and we want it to go away. - * Then we want GDB to forget all about it. - */ +/* We're done debugging it, and we want it to go away. Then we want + GDB to forget all about it. */ -static void -procfs_kill_inferior (void) +static void +procfs_kill_inferior (struct target_ops *ops) { if (!ptid_equal (inferior_ptid, null_ptid)) /* ? */ { - /* Find procinfo for main process */ + /* Find procinfo for main process. */ procinfo *pi = find_procinfo (PIDGET (inferior_ptid), 0); if (pi) @@ -4698,51 +4584,51 @@ procfs_kill_inferior (void) } } -/* - * Function: target_mourn_inferior - * - * Forget we ever debugged this thing! - */ +/* Forget we ever debugged this thing! */ -static void -procfs_mourn_inferior (void) +static void +procfs_mourn_inferior (struct target_ops *ops) { procinfo *pi; if (!ptid_equal (inferior_ptid, null_ptid)) { - /* Find procinfo for main process */ + /* Find procinfo for main process. */ pi = find_procinfo (PIDGET (inferior_ptid), 0); if (pi) destroy_procinfo (pi); } - unpush_target (&procfs_ops); + unpush_target (ops); + + if (dbx_link_bpt != NULL) + { + deprecated_remove_raw_breakpoint (target_gdbarch, dbx_link_bpt); + dbx_link_bpt_addr = 0; + dbx_link_bpt = NULL; + } + generic_mourn_inferior (); } -/* - * Function: init_inferior - * - * When GDB forks to create a runnable inferior process, - * this function is called on the parent side of the fork. - * It's job is to do whatever is necessary to make the child - * ready to be debugged, and then wait for the child to synchronize. - */ +/* When GDB forks to create a runnable inferior process, this function + is called on the parent side of the fork. It's job is to do + whatever is necessary to make the child ready to be debugged, and + then wait for the child to synchronize. */ -static void -procfs_init_inferior (int pid) +static void +procfs_init_inferior (struct target_ops *ops, int pid) { procinfo *pi; gdb_sigset_t signals; int fail; + int lwpid; /* This routine called on the parent side (GDB side) after GDB forks the inferior. */ - - push_target (&procfs_ops); + push_target (ops); if ((pi = create_procinfo (pid, 0)) == NULL) - perror ("procfs: out of memory in 'init_inferior'"); + perror (_("procfs: out of memory in 'init_inferior'")); if (!open_procinfo_files (pi, FD_CTL)) proc_error (pi, "init_inferior, open_proc_files", __LINE__); @@ -4759,14 +4645,14 @@ procfs_init_inferior (int pid) PIOCSFAULT */ - /* If not stopped yet, wait for it to stop. */ + /* If not stopped yet, wait for it to stop. */ if (!(proc_flags (pi) & PR_STOPPED) && !(proc_wait_for_stop (pi))) dead_procinfo (pi, "init_inferior: wait_for_stop failed", KILL); /* Save some of the /proc state to be restored if we detach. */ /* FIXME: Why? In case another debugger was debugging it? - We're it's parent, for Ghu's sake! */ + We're it's parent, for Ghu's sake! */ if (!proc_get_traced_signals (pi, &pi->saved_sigset)) proc_error (pi, "init_inferior, get_traced_signals", __LINE__); if (!proc_get_held_signals (pi, &pi->saved_sighold)) @@ -4778,11 +4664,6 @@ procfs_init_inferior (int pid) 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. */ - prfillset (&signals); - if (!register_gdb_signals (pi, &signals)) - proc_error (pi, "init_inferior, register_signals", __LINE__); - if ((fail = procfs_debug_inferior (pi)) != 0) proc_error (pi, "init_inferior (procfs_debug_inferior)", fail); @@ -4795,29 +4676,55 @@ procfs_init_inferior (int pid) if (!proc_set_run_on_last_close (pi)) proc_error (pi, "init_inferior, set_RLC", __LINE__); - /* The 'process ID' we return to GDB is composed of - the actual process ID plus the lwp ID. */ - inferior_ptid = MERGEPID (pi->pid, proc_get_current_thread (pi)); + /* We now have have access to the lwpid of the main thread/lwp. */ + lwpid = proc_get_current_thread (pi); + + /* Create a procinfo for the main lwp. */ + create_procinfo (pid, lwpid); + + /* We already have a main thread registered in the thread table at + this point, but it didn't have any lwp info yet. Notify the core + about it. This changes inferior_ptid as well. */ + thread_change_ptid (pid_to_ptid (pid), + MERGEPID (pid, lwpid)); -#ifdef START_INFERIOR_TRAPS_EXPECTED + /* Typically two, one trap to exec the shell, one to exec the + program being debugged. Defined by "inferior.h". */ startup_inferior (START_INFERIOR_TRAPS_EXPECTED); -#else - /* One trap to exec the shell, one to exec the program being debugged. */ - startup_inferior (2); -#endif /* START_INFERIOR_TRAPS_EXPECTED */ -} - -/* - * Function: set_exec_trap - * - * When GDB forks to create a new process, this function is called - * on the child side of the fork before GDB exec's the user program. - * Its job is to make the child minimally debuggable, so that the - * parent GDB process can connect to the child and take over. - * This function should do only the minimum to make that possible, - * and to synchronize with the parent process. The parent process - * should take care of the details. - */ + +#ifdef SYS_syssgi + /* On mips-irix, we need to stop the inferior early enough during + the startup phase in order to be able to load the shared library + symbols and insert the breakpoints that are located in these shared + libraries. Stopping at the program entry point is not good enough + because the -init code is executed before the execution reaches + that point. + + So what we need to do is to insert a breakpoint in the runtime + loader (rld), more precisely in __dbx_link(). This procedure is + called by rld once all shared libraries have been mapped, but before + the -init code is executed. Unfortuantely, this is not straightforward, + as rld is not part of the executable we are running, and thus we need + the inferior to run until rld itself has been mapped in memory. + + For this, we trace all syssgi() syscall exit events. Each time + we detect such an event, we iterate over each text memory maps, + get its associated fd, and scan the symbol table for __dbx_link(). + When found, we know that rld has been mapped, and that we can insert + the breakpoint at the symbol address. Once the dbx_link() breakpoint + has been inserted, the syssgi() notifications are no longer necessary, + so they should be canceled. */ + proc_trace_syscalls_1 (pi, SYS_syssgi, PR_SYSEXIT, FLAG_SET, 0); +#endif +} + +/* When GDB forks to create a new process, this function is called on + the child side of the fork before GDB exec's the user program. Its + job is to make the child minimally debuggable, so that the parent + GDB process can connect to the child and take over. This function + should do only the minimum to make that possible, and to + synchronize with the parent process. The parent process should + take care of the details. */ static void procfs_set_exec_trap (void) @@ -4830,13 +4737,14 @@ procfs_set_exec_trap (void) sysset_t *exitset; if ((pi = create_procinfo (getpid (), 0)) == NULL) - perror_with_name ("procfs: create_procinfo failed in child."); + perror_with_name (_("procfs: create_procinfo failed in child.")); if (open_procinfo_files (pi, FD_CTL) == 0) { proc_warn (pi, "set_exec_trap, open_proc_files", __LINE__); gdb_flush (gdb_stderr); - /* no need to call "dead_procinfo", because we're going to exit. */ + /* No need to call "dead_procinfo", because we're going to + exit. */ _exit (127); } @@ -4844,7 +4752,7 @@ procfs_set_exec_trap (void) /* OSF method for tracing exec syscalls. Quoting: Under Alpha OSF/1 we have to use a PIOCSSPCACT ioctl to trace exits from exec system calls because of the user level loader. */ - /* FIXME: make nice and maybe move into an access function. */ + /* FIXME: make nice and maybe move into an access function. */ { int prfs_flags; @@ -4864,11 +4772,11 @@ procfs_set_exec_trap (void) } } #else /* not PRFS_STOPEXEC */ - /* Everyone else's (except OSF) method for tracing exec syscalls */ + /* Everyone else's (except OSF) method for tracing exec syscalls. */ /* GW: Rationale... Not all systems with /proc have all the exec* syscalls with the same names. On the SGI, for example, there is no SYS_exec, but there - *is* a SYS_execv. So, we try to account for that. */ + *is* a SYS_execv. So, we try to account for that. */ exitset = sysset_t_alloc (pi); gdb_premptysysset (exitset); @@ -4902,7 +4810,7 @@ procfs_set_exec_trap (void) } #endif /* PRFS_STOPEXEC */ - /* FIXME: should this be done in the parent instead? */ + /* FIXME: should this be done in the parent instead? */ /* Turn off inherit on fork flag so that all grand-children of gdb start with tracing flags cleared. */ if (!proc_unset_inherit_on_fork (pi)) @@ -4914,31 +4822,30 @@ procfs_set_exec_trap (void) if (!proc_unset_run_on_last_close (pi)) proc_warn (pi, "set_exec_trap, unset_RLC", __LINE__); - /* FIXME: No need to destroy the procinfo -- - we have our own address space, and we're about to do an exec! */ + /* FIXME: No need to destroy the procinfo -- + we have our own address space, and we're about to do an exec! */ /*destroy_procinfo (pi);*/ } -/* - * Function: create_inferior - * - * This function is called BEFORE gdb forks the inferior process. - * Its only real responsibility is to set things up for the fork, - * and tell GDB which two functions to call after the fork (one - * for the parent, and one for the child). - * - * This function does a complicated search for a unix shell program, - * which it then uses to parse arguments and environment variables - * to be sent to the child. I wonder whether this code could not - * be abstracted out and shared with other unix targets such as - * infptrace? - */ +/* This function is called BEFORE gdb forks the inferior process. Its + only real responsibility is to set things up for the fork, and tell + GDB which two functions to call after the fork (one for the parent, + and one for the child). + + This function does a complicated search for a unix shell program, + which it then uses to parse arguments and environment variables to + be sent to the child. I wonder whether this code could not be + abstracted out and shared with other unix targets such as + inf-ptrace? */ static void -procfs_create_inferior (char *exec_file, char *allargs, char **env) +procfs_create_inferior (struct target_ops *ops, char *exec_file, + char *allargs, char **env, int from_tty) { char *shell_file = getenv ("SHELL"); char *tryname; + int pid; + if (shell_file != NULL && strchr (shell_file, '/') == NULL) { @@ -5001,75 +4908,82 @@ procfs_create_inferior (char *exec_file, char *allargs, char **env) /* Not found. This must be an error rather than merely passing the file to execlp(), because execlp() would try all the exec()s, causing GDB to get confused. */ - error ("procfs:%d -- Can't find shell %s in PATH", + error (_("procfs:%d -- Can't find shell %s in PATH"), __LINE__, shell_file); shell_file = tryname; } - fork_inferior (exec_file, allargs, env, procfs_set_exec_trap, - procfs_init_inferior, NULL, shell_file); + pid = fork_inferior (exec_file, allargs, env, procfs_set_exec_trap, + NULL, NULL, shell_file); - /* We are at the first instruction we care about. */ - /* Pedal to the metal... */ + procfs_init_inferior (ops, pid); +} - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0); +/* An observer for the "inferior_created" event. */ + +static void +procfs_inferior_created (struct target_ops *ops, int from_tty) +{ +#ifdef SYS_syssgi + /* Make sure to cancel the syssgi() syscall-exit notifications. + They should normally have been removed by now, but they may still + be activated if the inferior doesn't use shared libraries, or if + we didn't locate __dbx_link, or if we never stopped in __dbx_link. + See procfs_init_inferior() for more details. + + Since these notifications are only ever enabled when we spawned + the inferior ourselves, there is nothing to do when the inferior + was created by attaching to an already running process, or when + debugging a core file. */ + if (current_inferior ()->attach_flag || !target_can_run (¤t_target)) + return; + + proc_trace_syscalls_1 (find_procinfo_or_die (PIDGET (inferior_ptid), 0), + SYS_syssgi, PR_SYSEXIT, FLAG_RESET, 0); +#endif } -/* - * Function: notice_thread - * - * Callback for find_new_threads. - * Calls "add_thread". - */ +/* Callback for find_new_threads. Calls "add_thread". */ static int procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr) { ptid_t gdb_threadid = MERGEPID (pi->pid, thread->tid); - if (!in_thread_list (gdb_threadid)) + if (!in_thread_list (gdb_threadid) || is_exited (gdb_threadid)) add_thread (gdb_threadid); return 0; } -/* - * Function: target_find_new_threads - * - * Query all the threads that the target knows about, - * and give them back to GDB to add to its list. - */ +/* Query all the threads that the target knows about, and give them + back to GDB to add to its list. */ void -procfs_find_new_threads (void) +procfs_find_new_threads (struct target_ops *ops) { procinfo *pi; - /* Find procinfo for main process */ + /* Find procinfo for main process. */ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); proc_update_threads (pi); proc_iterate_over_threads (pi, procfs_notice_thread, NULL); } -/* - * Function: target_thread_alive - * - * Return true if the thread is still 'alive'. - * - * This guy doesn't really seem to be doing his job. - * Got to investigate how to tell when a thread is really gone. - */ +/* Return true if the thread is still 'alive'. This guy doesn't + really seem to be doing his job. Got to investigate how to tell + when a thread is really gone. */ static int -procfs_thread_alive (ptid_t ptid) +procfs_thread_alive (struct target_ops *ops, ptid_t ptid) { int proc, thread; procinfo *pi; proc = PIDGET (ptid); thread = TIDGET (ptid); - /* If I don't know it, it ain't alive! */ + /* If I don't know it, it ain't alive! */ if ((pi = find_procinfo (proc, thread)) == NULL) return 0; @@ -5080,56 +4994,45 @@ procfs_thread_alive (ptid_t ptid) destroy_procinfo (pi); return 0; } - /* I couldn't have got its status if it weren't alive, so it's alive. */ + /* I couldn't have got its status if it weren't alive, so it's + alive. */ return 1; } -/* - * Function: target_pid_to_str - * - * Return a string to be used to identify the thread in - * the "info threads" display. - */ +/* Convert PTID to a string. Returns the string in a static + buffer. */ char * -procfs_pid_to_str (ptid_t ptid) +procfs_pid_to_str (struct target_ops *ops, ptid_t ptid) { static char buf[80]; - int proc, thread; - procinfo *pi; - proc = PIDGET (ptid); - thread = TIDGET (ptid); - pi = find_procinfo (proc, thread); - - if (thread == 0) - sprintf (buf, "Process %d", proc); + if (TIDGET (ptid) == 0) + sprintf (buf, "process %d", PIDGET (ptid)); else - sprintf (buf, "LWP %d", thread); - return &buf[0]; + sprintf (buf, "LWP %ld", TIDGET (ptid)); + + return buf; } -/* - * Function: procfs_set_watchpoint - * Insert a watchpoint - */ +/* Insert a watchpoint. */ -int +int procfs_set_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rwflag, - int after) + int after) { #ifndef UNIXWARE #ifndef AIX5 int pflags = 0; - procinfo *pi; + procinfo *pi; - pi = find_procinfo_or_die (PIDGET (ptid) == -1 ? + pi = find_procinfo_or_die (PIDGET (ptid) == -1 ? PIDGET (inferior_ptid) : PIDGET (ptid), 0); - /* Translate from GDB's flags to /proc's */ - if (len > 0) /* len == 0 means delete watchpoint */ + /* Translate from GDB's flags to /proc's. */ + if (len > 0) /* len == 0 means delete watchpoint. */ { - switch (rwflag) { /* FIXME: need an enum! */ + switch (rwflag) { /* FIXME: need an enum! */ case hw_write: /* default watchpoint (write) */ pflags = WRITE_WATCHFLAG; break; @@ -5142,16 +5045,16 @@ procfs_set_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rwflag, case hw_execute: /* execution HW breakpoint */ pflags = EXEC_WATCHFLAG; break; - default: /* Something weird. Return error. */ + default: /* Something weird. Return error. */ return -1; } - if (after) /* Stop after r/w access is completed. */ + if (after) /* Stop after r/w access is completed. */ pflags |= AFTER_WATCHFLAG; } if (!proc_set_watchpoint (pi, addr, len, pflags)) { - if (errno == E2BIG) /* Typical error for no resources */ + if (errno == E2BIG) /* Typical error for no resources. */ return -1; /* fail */ /* GDB may try to remove the same watchpoint twice. If a remove request returns no match, don't error. */ @@ -5168,17 +5071,14 @@ procfs_set_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rwflag, is one of bp_hardware_watchpoint, bp_read_watchpoint, bp_write_watchpoint, or bp_hardware_watchpoint. CNT is the number of watchpoints used so far. - + Note: procfs_can_use_hw_breakpoint() is not yet used by all procfs.c targets due to the fact that some of them still define - TARGET_CAN_USE_HARDWARE_WATCHPOINT. */ + target_can_use_hardware_watchpoint. */ static int procfs_can_use_hw_breakpoint (int type, int cnt, int othertype) { -#ifndef TARGET_HAS_HARDWARE_WATCHPOINTS - return 0; -#else /* Due to the way that proc_set_watchpoint() is implemented, host and target pointers must be of the same size. If they are not, we can't use hardware watchpoints. This limitation is due to the @@ -5187,37 +5087,30 @@ procfs_can_use_hw_breakpoint (int type, int cnt, int othertype) procfs_address_to_host_pointer will reveal that an internal error will be generated when the host and target pointer sizes are different. */ - if (sizeof (void *) != TYPE_LENGTH (builtin_type_void_data_ptr)) + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; + + if (sizeof (void *) != TYPE_LENGTH (ptr_type)) return 0; /* Other tests here??? */ return 1; -#endif } -/* - * Function: stopped_by_watchpoint - * - * Returns non-zero if process is stopped on a hardware watchpoint fault, - * else returns zero. - */ +/* Returns non-zero if process is stopped on a hardware watchpoint + fault, else returns zero. */ -int -procfs_stopped_by_watchpoint (ptid_t ptid) +static int +procfs_stopped_by_watchpoint (void) { procinfo *pi; - pi = find_procinfo_or_die (PIDGET (ptid) == -1 ? - PIDGET (inferior_ptid) : PIDGET (ptid), 0); - - if (!pi) /* If no process, then not stopped by watchpoint! */ - return 0; + pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); if (proc_flags (pi) & (PR_STOPPED | PR_ISTOP)) { if (proc_why (pi) == PR_FAULTED) - { + { #ifdef FLTWATCH if (proc_what (pi) == FLTWATCH) return 1; @@ -5231,72 +5124,91 @@ procfs_stopped_by_watchpoint (ptid_t ptid) return 0; } -#ifdef TM_I386SOL2_H -/* - * Function: procfs_find_LDT_entry - * - * Input: - * ptid_t ptid; // The GDB-style pid-plus-LWP. - * - * Return: - * pointer to the corresponding LDT entry. - */ +/* Returns 1 if the OS knows the position of the triggered watchpoint, + and sets *ADDR to that address. Returns 0 if OS cannot report that + address. This function is only called if + procfs_stopped_by_watchpoint returned 1, thus no further checks are + done. The function also assumes that ADDR is not NULL. */ -struct ssd * -procfs_find_LDT_entry (ptid_t ptid) +static int +procfs_stopped_data_address (struct target_ops *targ, CORE_ADDR *addr) { - gdb_gregset_t *gregs; - int key; - procinfo *pi; + procinfo *pi; - /* Find procinfo for the lwp. */ - if ((pi = find_procinfo (PIDGET (ptid), TIDGET (ptid))) == NULL) + pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); + return proc_watchpoint_address (pi, addr); +} + +static int +procfs_insert_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) +{ + if (!target_have_steppable_watchpoint + && !gdbarch_have_nonsteppable_watchpoint (target_gdbarch)) { - warning ("procfs_find_LDT_entry: could not find procinfo for %d:%d.", - PIDGET (ptid), TIDGET (ptid)); - return NULL; + /* When a hardware watchpoint fires off the PC will be left at + the instruction following the one which caused the + watchpoint. It will *NOT* be necessary for GDB to step over + the watchpoint. */ + return procfs_set_watchpoint (inferior_ptid, addr, len, type, 1); } - /* get its general registers. */ - if ((gregs = proc_get_gregs (pi)) == NULL) + else { - warning ("procfs_find_LDT_entry: could not read gregs for %d:%d.", - PIDGET (ptid), TIDGET (ptid)); - return NULL; + /* When a hardware watchpoint fires off the PC will be left at + the instruction which caused the watchpoint. It will be + necessary for GDB to step over the watchpoint. */ + return procfs_set_watchpoint (inferior_ptid, addr, len, type, 0); } - /* Now extract the GS register's lower 16 bits. */ - key = (*gregs)[GS] & 0xffff; +} - /* Find the matching entry and return it. */ - return proc_get_LDT_entry (pi, key); +static int +procfs_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) +{ + return procfs_set_watchpoint (inferior_ptid, addr, 0, 0, 0); +} + +static int +procfs_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) +{ + /* The man page for proc(4) on Solaris 2.6 and up says that the + system can support "thousands" of hardware watchpoints, but gives + no method for finding out how many; It doesn't say anything about + the allowed size for the watched area either. So we just tell + GDB 'yes'. */ + return 1; +} + +void +procfs_use_watchpoints (struct target_ops *t) +{ + t->to_stopped_by_watchpoint = procfs_stopped_by_watchpoint; + t->to_insert_watchpoint = procfs_insert_watchpoint; + t->to_remove_watchpoint = procfs_remove_watchpoint; + t->to_region_ok_for_hw_watchpoint = procfs_region_ok_for_hw_watchpoint; + t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint; + t->to_stopped_data_address = procfs_stopped_data_address; } -#endif /* TM_I386SOL2_H */ - -/* - * Memory Mappings Functions: - */ - -/* - * Function: iterate_over_mappings - * - * Call a callback function once for each mapping, passing it the mapping, - * an optional secondary callback function, and some optional opaque data. - * Quit and return the first non-zero value returned from the callback. - * - * Arguments: - * pi -- procinfo struct for the process to be mapped. - * func -- callback function to be called by this iterator. - * data -- optional opaque data to be passed to the callback function. - * child_func -- optional secondary function pointer to be passed - * to the child function. - * - * Return: First non-zero return value from the callback function, - * or zero. - */ + +/* Memory Mappings Functions: */ + +/* Call a callback function once for each mapping, passing it the + mapping, an optional secondary callback function, and some optional + opaque data. Quit and return the first non-zero value returned + from the callback. + + PI is the procinfo struct for the process to be mapped. FUNC is + the callback function to be called by this iterator. DATA is the + optional opaque data to be passed to the callback function. + CHILD_FUNC is the optional secondary function pointer to be passed + to the child function. Returns the first non-zero return value + from the callback function, or zero. */ static int -iterate_over_mappings (procinfo *pi, int (*child_func) (), void *data, - int (*func) (struct prmap *map, - int (*child_func) (), +iterate_over_mappings (procinfo *pi, find_memory_region_ftype child_func, + void *data, + int (*func) (struct prmap *map, + find_memory_region_ftype child_func, void *data)) { char pathname[MAX_PROC_NAME_SIZE]; @@ -5309,18 +5221,18 @@ iterate_over_mappings (procinfo *pi, int (*child_func) (), void *data, struct stat sbuf; #endif - /* Get the number of mappings, allocate space, + /* Get the number of mappings, allocate space, and read the mappings into prmaps. */ #ifdef NEW_PROC_API - /* Open map fd. */ + /* Open map fd. */ sprintf (pathname, "/proc/%d/map", pi->pid); if ((map_fd = open (pathname, O_RDONLY)) < 0) proc_error (pi, "iterate_over_mappings (open)", __LINE__); - /* Make sure it gets closed again. */ + /* Make sure it gets closed again. */ make_cleanup_close (map_fd); - /* Use stat to determine the file size, and compute + /* Use stat to determine the file size, and compute the number of prmap_t objects it contains. */ if (fstat (map_fd, &sbuf) != 0) proc_error (pi, "iterate_over_mappings (fstat)", __LINE__); @@ -5347,146 +5259,44 @@ iterate_over_mappings (procinfo *pi, int (*child_func) (), void *data, return 0; } -/* - * Function: solib_mappings_callback - * - * Calls the supplied callback function once for each mapped address - * space in the process. The callback function receives an open - * file descriptor for the file corresponding to that mapped - * address space (if there is one), and the base address of the - * mapped space. Quit when the callback function returns a - * nonzero value, or at teh end of the mappings. - * - * Returns: the first non-zero return value of the callback function, - * or zero. - */ - -int solib_mappings_callback (struct prmap *map, - int (*func) (int, CORE_ADDR), - void *data) -{ - procinfo *pi = data; - int fd; - -#ifdef NEW_PROC_API - char name[MAX_PROC_NAME_SIZE + sizeof (map->pr_mapname)]; - - if (map->pr_vaddr == 0 && map->pr_size == 0) - return -1; /* sanity */ - - if (map->pr_mapname[0] == 0) - { - fd = -1; /* no map file */ - } - else - { - sprintf (name, "/proc/%d/object/%s", pi->pid, map->pr_mapname); - /* Note: caller's responsibility to close this fd! */ - fd = open_with_retry (name, O_RDONLY); - /* Note: we don't test the above call for failure; - we just pass the FD on as given. Sometimes there is - no file, so the open may return failure, but that's - not a problem. */ - } -#else - fd = ioctl (pi->ctl_fd, PIOCOPENM, &map->pr_vaddr); - /* Note: we don't test the above call for failure; - we just pass the FD on as given. Sometimes there is - no file, so the ioctl may return failure, but that's - not a problem. */ -#endif - return (*func) (fd, (CORE_ADDR) map->pr_vaddr); -} - -/* - * Function: proc_iterate_over_mappings - * - * Uses the unified "iterate_over_mappings" function - * to implement the exported interface to solib-svr4.c. - * - * Given a pointer to a function, call that function once for every - * mapped address space in the process. The callback function - * receives an open file descriptor for the file corresponding to - * that mapped address space (if there is one), and the base address - * of the mapped space. Quit when the callback function returns a - * nonzero value, or at teh end of the mappings. - * - * Returns: the first non-zero return value of the callback function, - * or zero. - */ - -int -proc_iterate_over_mappings (int (*func) (int, CORE_ADDR)) -{ - procinfo *pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); - - return iterate_over_mappings (pi, func, pi, solib_mappings_callback); -} - -/* - * Function: find_memory_regions_callback - * - * Implements the to_find_memory_regions method. - * Calls an external function for each memory region. - * External function will have the signiture: - * - * int callback (CORE_ADDR vaddr, - * unsigned long size, - * int read, int write, int execute, - * void *data); - * - * Returns the integer value returned by the callback. - */ +/* Implements the to_find_memory_regions method. Calls an external + function for each memory region. + Returns the integer value returned by the callback. */ static int -find_memory_regions_callback (struct prmap *map, - int (*func) (CORE_ADDR, - unsigned long, - int, int, int, - void *), - void *data) +find_memory_regions_callback (struct prmap *map, + find_memory_region_ftype func, void *data) { return (*func) ((CORE_ADDR) map->pr_vaddr, - map->pr_size, + map->pr_size, (map->pr_mflags & MA_READ) != 0, (map->pr_mflags & MA_WRITE) != 0, - (map->pr_mflags & MA_EXEC) != 0, + (map->pr_mflags & MA_EXEC) != 0, data); } -/* - * Function: proc_find_memory_regions - * - * External interface. Calls a callback function once for each - * mapped memory region in the child process, passing as arguments - * CORE_ADDR virtual_address, - * unsigned long size, - * int read, TRUE if region is readable by the child - * int write, TRUE if region is writable by the child - * int execute TRUE if region is executable by the child. - * - * Stops iterating and returns the first non-zero value - * returned by the callback. - */ +/* External interface. Calls a callback function once for each + mapped memory region in the child process, passing as arguments: + + CORE_ADDR virtual_address, + unsigned long size, + int read, TRUE if region is readable by the child + int write, TRUE if region is writable by the child + int execute TRUE if region is executable by the child. + + Stops iterating and returns the first non-zero value returned by + the callback. */ static int -proc_find_memory_regions (int (*func) (CORE_ADDR, - unsigned long, - int, int, int, - void *), - void *data) +proc_find_memory_regions (find_memory_region_ftype func, void *data) { procinfo *pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); - return iterate_over_mappings (pi, func, data, + return iterate_over_mappings (pi, func, data, find_memory_regions_callback); } -/* - * Function: mappingflags - * - * Returns an ascii representation of a memory mapping's flags. - */ +/* Returns an ascii representation of a memory mapping's flags. */ static char * mappingflags (long flags) @@ -5513,72 +5323,68 @@ mappingflags (long flags) return (asciiflags); } -/* - * Function: info_mappings_callback - * - * Callback function, does the actual work for 'info proc mappings'. - */ +/* Callback function, does the actual work for 'info proc + mappings'. */ static int -info_mappings_callback (struct prmap *map, int (*ignore) (), void *unused) +info_mappings_callback (struct prmap *map, find_memory_region_ftype ignore, + void *unused) { - char *data_fmt_string; - - if (TARGET_ADDR_BIT == 32) - data_fmt_string = "\t%#10lx %#10lx %#10x %#10x %7s\n"; - else - data_fmt_string = " %#18lx %#18lx %#10x %#10x %7s\n"; + unsigned int pr_off; - printf_filtered (data_fmt_string, - (unsigned long) map->pr_vaddr, - (unsigned long) map->pr_vaddr + map->pr_size - 1, - map->pr_size, #ifdef PCAGENT /* Horrible hack: only defined on Solaris 2.6+ */ - (unsigned int) map->pr_offset, + pr_off = (unsigned int) map->pr_offset; #else - map->pr_off, + pr_off = map->pr_off; #endif - mappingflags (map->pr_mflags)); + + if (gdbarch_addr_bit (target_gdbarch) == 32) + printf_filtered ("\t%#10lx %#10lx %#10lx %#10x %7s\n", + (unsigned long) map->pr_vaddr, + (unsigned long) map->pr_vaddr + map->pr_size - 1, + (unsigned long) map->pr_size, + pr_off, + mappingflags (map->pr_mflags)); + else + printf_filtered (" %#18lx %#18lx %#10lx %#10x %7s\n", + (unsigned long) map->pr_vaddr, + (unsigned long) map->pr_vaddr + map->pr_size - 1, + (unsigned long) map->pr_size, + pr_off, + mappingflags (map->pr_mflags)); return 0; } -/* - * Function: info_proc_mappings - * - * Implement the "info proc mappings" subcommand. - */ +/* Implement the "info proc mappings" subcommand. */ static void info_proc_mappings (procinfo *pi, int summary) { - char *header_fmt_string; - - if (TARGET_PTR_BIT == 32) - header_fmt_string = "\t%10s %10s %10s %10s %7s\n"; - else - header_fmt_string = " %18s %18s %10s %10s %7s\n"; - if (summary) - return; /* No output for summary mode. */ - - printf_filtered ("Mapped address spaces:\n\n"); - printf_filtered (header_fmt_string, - "Start Addr", - " End Addr", - " Size", - " Offset", - "Flags"); + return; /* No output for summary mode. */ + + printf_filtered (_("Mapped address spaces:\n\n")); + if (gdbarch_ptr_bit (target_gdbarch) == 32) + printf_filtered ("\t%10s %10s %10s %10s %7s\n", + "Start Addr", + " End Addr", + " Size", + " Offset", + "Flags"); + else + printf_filtered (" %18s %18s %10s %10s %7s\n", + "Start Addr", + " End Addr", + " Size", + " Offset", + "Flags"); iterate_over_mappings (pi, NULL, NULL, info_mappings_callback); printf_filtered ("\n"); } -/* - * Function: info_proc_cmd - * - * Implement the "info proc" command. - */ +/* Implement the "info proc" command. */ static void info_proc_cmd (char *args, int from_tty) @@ -5595,10 +5401,8 @@ info_proc_cmd (char *args, int from_tty) old_chain = make_cleanup (null_cleanup, 0); if (args) { - if ((argv = buildargv (args)) == NULL) - nomem (0); - else - make_cleanup_freeargv (argv); + argv = gdb_buildargv (args); + make_cleanup_freeargv (argv); } while (argv != NULL && *argv != NULL) { @@ -5625,15 +5429,15 @@ info_proc_cmd (char *args, int from_tty) if (pid == 0) pid = PIDGET (inferior_ptid); if (pid == 0) - error ("No current process: you must name one."); + error (_("No current process: you must name one.")); else { /* Have pid, will travel. - First see if it's a process we're already debugging. */ + First see if it's a process we're already debugging. */ process = find_procinfo (pid, 0); if (process == NULL) { - /* No. So open a procinfo for it, but + /* No. So open a procinfo for it, but remember to close it again when finished. */ process = create_procinfo (pid, 0); make_cleanup (do_destroy_procinfo_cleanup, process); @@ -5646,17 +5450,17 @@ info_proc_cmd (char *args, int from_tty) if (process) { - printf_filtered ("process %d flags:\n", process->pid); + printf_filtered (_("process %d flags:\n"), process->pid); proc_prettyprint_flags (proc_flags (process), 1); if (proc_flags (process) & (PR_STOPPED | PR_ISTOP)) proc_prettyprint_why (proc_why (process), proc_what (process), 1); if (proc_get_nthreads (process) > 1) - printf_filtered ("Process has %d threads.\n", + printf_filtered ("Process has %d threads.\n", proc_get_nthreads (process)); } if (thread) { - printf_filtered ("thread %d flags:\n", thread->tid); + printf_filtered (_("thread %d flags:\n"), thread->tid); proc_prettyprint_flags (proc_flags (thread), 1); if (proc_flags (thread) & (PR_STOPPED | PR_ISTOP)) proc_prettyprint_why (proc_why (thread), proc_what (thread), 1); @@ -5670,68 +5474,85 @@ info_proc_cmd (char *args, int from_tty) do_cleanups (old_chain); } +/* Modify the status of the system call identified by SYSCALLNUM in + the set of syscalls that are currently traced/debugged. + + If ENTRY_OR_EXIT is set to PR_SYSENTRY, then the entry syscalls set + will be updated. Otherwise, the exit syscalls set will be updated. + + If MODE is FLAG_SET, then traces will be enabled. Otherwise, they + will be disabled. */ + +static void +proc_trace_syscalls_1 (procinfo *pi, int syscallnum, int entry_or_exit, + int mode, int from_tty) +{ + sysset_t *sysset; + + if (entry_or_exit == PR_SYSENTRY) + sysset = proc_get_traced_sysentry (pi, NULL); + else + sysset = proc_get_traced_sysexit (pi, NULL); + + if (sysset == NULL) + proc_error (pi, "proc-trace, get_traced_sysset", __LINE__); + + if (mode == FLAG_SET) + gdb_praddsysset (sysset, syscallnum); + else + gdb_prdelsysset (sysset, syscallnum); + + if (entry_or_exit == PR_SYSENTRY) + { + if (!proc_set_traced_sysentry (pi, sysset)) + proc_error (pi, "proc-trace, set_traced_sysentry", __LINE__); + } + else + { + if (!proc_set_traced_sysexit (pi, sysset)) + proc_error (pi, "proc-trace, set_traced_sysexit", __LINE__); + } +} + static void proc_trace_syscalls (char *args, int from_tty, int entry_or_exit, int mode) { procinfo *pi; - sysset_t *sysset; - int syscallnum = 0; if (PIDGET (inferior_ptid) <= 0) - error ("you must be debugging a process to use this command."); + error (_("you must be debugging a process to use this command.")); if (args == NULL || args[0] == 0) - error_no_arg ("system call to trace"); + error_no_arg (_("system call to trace")); pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); if (isdigit (args[0])) { - syscallnum = atoi (args); - if (entry_or_exit == PR_SYSENTRY) - sysset = proc_get_traced_sysentry (pi, NULL); - else - sysset = proc_get_traced_sysexit (pi, NULL); - - if (sysset == NULL) - proc_error (pi, "proc-trace, get_traced_sysset", __LINE__); + const int syscallnum = atoi (args); - if (mode == FLAG_SET) - gdb_praddsysset (sysset, syscallnum); - else - gdb_prdelsysset (sysset, syscallnum); - - if (entry_or_exit == PR_SYSENTRY) - { - if (!proc_set_traced_sysentry (pi, sysset)) - proc_error (pi, "proc-trace, set_traced_sysentry", __LINE__); - } - else - { - if (!proc_set_traced_sysexit (pi, sysset)) - proc_error (pi, "proc-trace, set_traced_sysexit", __LINE__); - } + proc_trace_syscalls_1 (pi, syscallnum, entry_or_exit, mode, from_tty); } } -static void +static void proc_trace_sysentry_cmd (char *args, int from_tty) { proc_trace_syscalls (args, from_tty, PR_SYSENTRY, FLAG_SET); } -static void +static void proc_trace_sysexit_cmd (char *args, int from_tty) { proc_trace_syscalls (args, from_tty, PR_SYSEXIT, FLAG_SET); } -static void +static void proc_untrace_sysentry_cmd (char *args, int from_tty) { proc_trace_syscalls (args, from_tty, PR_SYSENTRY, FLAG_RESET); } -static void +static void proc_untrace_sysexit_cmd (char *args, int from_tty) { proc_trace_syscalls (args, from_tty, PR_SYSEXIT, FLAG_RESET); @@ -5741,35 +5562,33 @@ proc_untrace_sysexit_cmd (char *args, int from_tty) void _initialize_procfs (void) { - init_procfs_ops (); - add_target (&procfs_ops); - add_info ("proc", info_proc_cmd, - "Show /proc process information about any running process.\n\ + observer_attach_inferior_created (procfs_inferior_created); + + add_info ("proc", info_proc_cmd, _("\ +Show /proc process information about any running process.\n\ Specify process id, or use the program being debugged by default.\n\ -Specify keyword 'mappings' for detailed info on memory mappings."); - add_com ("proc-trace-entry", no_class, proc_trace_sysentry_cmd, - "Give a trace of entries into the syscall."); - add_com ("proc-trace-exit", no_class, proc_trace_sysexit_cmd, - "Give a trace of exits from the syscall."); - add_com ("proc-untrace-entry", no_class, proc_untrace_sysentry_cmd, - "Cancel a trace of entries into the syscall."); - add_com ("proc-untrace-exit", no_class, proc_untrace_sysexit_cmd, - "Cancel a trace of exits from the syscall."); +Specify keyword 'mappings' for detailed info on memory mappings.")); + add_com ("proc-trace-entry", no_class, proc_trace_sysentry_cmd, + _("Give a trace of entries into the syscall.")); + add_com ("proc-trace-exit", no_class, proc_trace_sysexit_cmd, + _("Give a trace of exits from the syscall.")); + add_com ("proc-untrace-entry", no_class, proc_untrace_sysentry_cmd, + _("Cancel a trace of entries into the syscall.")); + add_com ("proc-untrace-exit", no_class, proc_untrace_sysexit_cmd, + _("Cancel a trace of exits from the syscall.")); } /* =================== END, GDB "MODULE" =================== */ -/* miscellaneous stubs: */ -/* The following satisfy a few random symbols mostly created by */ -/* the solaris threads implementation, which I will chase down */ -/* later. */ +/* miscellaneous stubs: */ + +/* The following satisfy a few random symbols mostly created by the + solaris threads implementation, which I will chase down later. */ -/* - * Return a pid for which we guarantee - * we will be able to find a 'live' procinfo. - */ +/* Return a pid for which we guarantee we will be able to find a + 'live' procinfo. */ ptid_t procfs_first_available (void) @@ -5782,37 +5601,52 @@ procfs_first_available (void) /* gcore only implemented on solaris and unixware (so far) */ static char * -procfs_do_thread_registers (bfd *obfd, ptid_t ptid, - char *note_data, int *note_size) +procfs_do_thread_registers (bfd *obfd, ptid_t ptid, + char *note_data, int *note_size, + enum target_signal stop_signal) { + struct regcache *regcache = get_thread_regcache (ptid); gdb_gregset_t gregs; gdb_fpregset_t fpregs; unsigned long merged_pid; + struct cleanup *old_chain; merged_pid = TIDGET (ptid) << 16 | PIDGET (ptid); - fill_gregset (&gregs, -1); -#if defined (UNIXWARE) + /* This part is the old method for fetching registers. + It should be replaced by the newer one using regsets + once it is implemented in this platform: + gdbarch_regset_from_core_section() and regset->collect_regset(). */ + + old_chain = save_inferior_ptid (); + inferior_ptid = ptid; + target_fetch_registers (regcache, -1); + + fill_gregset (regcache, &gregs, -1); +#if defined (NEW_PROC_API) note_data = (char *) elfcore_write_lwpstatus (obfd, note_data, note_size, - merged_pid, + merged_pid, stop_signal, &gregs); #else note_data = (char *) elfcore_write_prstatus (obfd, note_data, note_size, - merged_pid, + merged_pid, stop_signal, &gregs); #endif - fill_fpregset (&fpregs, -1); + fill_fpregset (regcache, &fpregs, -1); note_data = (char *) elfcore_write_prfpreg (obfd, note_data, note_size, &fpregs, sizeof (fpregs)); + + do_cleanups (old_chain); + return note_data; } @@ -5820,6 +5654,7 @@ struct procfs_corefile_thread_data { bfd *obfd; char *note_data; int *note_size; + enum target_signal stop_signal; }; static int @@ -5827,18 +5662,40 @@ procfs_corefile_thread_callback (procinfo *pi, procinfo *thread, void *data) { struct procfs_corefile_thread_data *args = data; - if (pi != NULL && thread->tid != 0) + if (pi != NULL) { - ptid_t saved_ptid = inferior_ptid; - inferior_ptid = MERGEPID (pi->pid, thread->tid); - args->note_data = procfs_do_thread_registers (args->obfd, inferior_ptid, - args->note_data, - args->note_size); - inferior_ptid = saved_ptid; + ptid_t ptid = MERGEPID (pi->pid, thread->tid); + + args->note_data = procfs_do_thread_registers (args->obfd, ptid, + args->note_data, + args->note_size, + args->stop_signal); } return 0; } +static int +find_signalled_thread (struct thread_info *info, void *data) +{ + if (info->suspend.stop_signal != TARGET_SIGNAL_0 + && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid)) + return 1; + + return 0; +} + +static enum target_signal +find_stop_signal (void) +{ + struct thread_info *info = + iterate_over_threads (find_signalled_thread, NULL); + + if (info) + return info->suspend.stop_signal; + else + return TARGET_SIGNAL_0; +} + static char * procfs_make_note_section (bfd *obfd, int *note_size) { @@ -5851,52 +5708,60 @@ procfs_make_note_section (bfd *obfd, int *note_size) char *note_data = NULL; char *inf_args; struct procfs_corefile_thread_data thread_args; + gdb_byte *auxv; + int auxv_len; + enum target_signal stop_signal; if (get_exec_file (0)) { - strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname)); - strncpy (psargs, get_exec_file (0), + strncpy (fname, lbasename (get_exec_file (0)), sizeof (fname)); + strncpy (psargs, get_exec_file (0), sizeof (psargs)); inf_args = get_inferior_args (); if (inf_args && *inf_args && strlen (inf_args) < ((int) sizeof (psargs) - (int) strlen (psargs))) { - strncat (psargs, " ", + strncat (psargs, " ", sizeof (psargs) - strlen (psargs)); - strncat (psargs, inf_args, + strncat (psargs, inf_args, sizeof (psargs) - strlen (psargs)); } } - note_data = (char *) elfcore_write_prpsinfo (obfd, - note_data, - note_size, - fname, + note_data = (char *) elfcore_write_prpsinfo (obfd, + note_data, + note_size, + fname, psargs); + stop_signal = find_stop_signal (); + #ifdef UNIXWARE - fill_gregset (&gregs, -1); - note_data = elfcore_write_pstatus (obfd, note_data, note_size, - PIDGET (inferior_ptid), + fill_gregset (get_current_regcache (), &gregs, -1); + note_data = elfcore_write_pstatus (obfd, note_data, note_size, + PIDGET (inferior_ptid), stop_signal, &gregs); #endif thread_args.obfd = obfd; thread_args.note_data = note_data; thread_args.note_size = note_size; - proc_iterate_over_threads (pi, procfs_corefile_thread_callback, &thread_args); + thread_args.stop_signal = stop_signal; + proc_iterate_over_threads (pi, procfs_corefile_thread_callback, + &thread_args); - if (thread_args.note_data == note_data) - { - /* iterate_over_threads didn't come up with any threads; - just use inferior_ptid. */ - note_data = procfs_do_thread_registers (obfd, inferior_ptid, - note_data, note_size); - } - else + /* There should be always at least one thread. */ + gdb_assert (thread_args.note_data != note_data); + note_data = thread_args.note_data; + + auxv_len = target_read_alloc (¤t_target, TARGET_OBJECT_AUXV, + NULL, &auxv); + if (auxv_len > 0) { - note_data = thread_args.note_data; + note_data = elfcore_write_note (obfd, note_data, note_size, + "CORE", NT_AUXV, auxv, auxv_len); + xfree (auxv); } make_cleanup (xfree, note_data); @@ -5906,7 +5771,7 @@ procfs_make_note_section (bfd *obfd, int *note_size) static char * procfs_make_note_section (bfd *obfd, int *note_size) { - error ("gcore not implemented for this host."); + error (_("gcore not implemented for this host.")); return NULL; /* lint */ } #endif /* Solaris or Unixware */