/* 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
+ Free Software Foundation, Inc.
Written by Michael Snyder at Cygnus Solutions.
Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
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. */
+along with this program; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "inferior.h"
#include "elf-bfd.h" /* for elfcore_write_* */
#include "gdbcmd.h"
#include "gdbthread.h"
+#include "regcache.h"
#if defined (NEW_PROC_API)
#define _STRUCTURED_PROC 1 /* Should be done by configure script. */
#include "gdb_wait.h"
#include <signal.h>
#include <ctype.h>
+#include "gdb_string.h"
#include "gdb_assert.h"
#include "inflow.h"
+#include "auxv.h"
-/*
+/*
* PROCFS.C
*
* This module provides the interface between GDB and the
* 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
+ * 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
/* Determine which /proc API we are using:
- The ioctl API defines PIOCSTATUS, while
+ The ioctl API defines PIOCSTATUS, while
the read/write (multiple fd) API never does. */
#ifdef NEW_PROC_API
static int procfs_can_run (void);
static void procfs_stop (void);
static void procfs_files_info (struct target_ops *);
-static void procfs_fetch_registers (int);
-static void procfs_store_registers (int);
+static void procfs_fetch_registers (struct regcache *, int);
+static void procfs_store_registers (struct regcache *, int);
static void procfs_notice_signals (ptid_t);
-static void procfs_prepare_to_store (void);
+static void procfs_prepare_to_store (struct regcache *);
static void procfs_kill_inferior (void);
static void procfs_mourn_inferior (void);
-static void procfs_create_inferior (char *, char *, char **);
+static void procfs_create_inferior (char *, char *, char **, int);
static ptid_t procfs_wait (ptid_t, struct target_waitstatus *);
static int procfs_xfer_memory (CORE_ADDR, char *, int, int,
struct mem_attrib *attrib,
struct target_ops *);
+static LONGEST procfs_xfer_partial (struct target_ops *ops,
+ enum target_object object,
+ const char *annex,
+ void *readbuf, const void *writebuf,
+ ULONGEST offset, LONGEST len);
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 int proc_find_memory_regions (int (*) (CORE_ADDR,
+ unsigned long,
+ int, int, int,
+ void *),
void *);
static char * procfs_make_note_section (bfd *, int *);
{
procfs_ops.to_shortname = "procfs";
procfs_ops.to_longname = "Unix /proc child process";
- procfs_ops.to_doc =
+ procfs_ops.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_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_xfer_partial = procfs_xfer_partial;
+ procfs_ops.deprecated_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;
#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 */
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). */
/*
* 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
+ * 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 num_syscalls; /* Total number of syscalls */
char **syscall_names; /* Syscall number to name map */
#endif
-
+
struct procinfo *thread_list;
int status_valid : 1;
* Returns: pointer to procinfo, or NULL if not found.
*/
-static procinfo *
+static procinfo *
find_procinfo (int pid, int tid)
{
procinfo *pi;
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. */
-
+
static int
open_with_retry (const char *pathname, int flags)
{
#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
+ * 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
+ * The pathnames for the 'files' for an LWP look slightly
* different from those of a first-class process:
* Pathnames for a process (<proc-id>):
* /proc/<proc-id>/ctl
* 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.
+ * doesn't need any #ifdef's.
* Pathname for all:
* /proc/<proc-id>
*
* Solaris 2.5 LWP's:
- * Each LWP has an independent file descriptor, but these
+ * 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.
* 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.
+ * 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
+ * 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.
*/
/* 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)
{
kill (pi->pid, SIGKILL);
destroy_procinfo (pi);
- error (msg);
+ error ((msg));
}
/*
}
/* Function: sysset_t_alloc
-
+
Allocate and (partially) initialize a sysset_t struct. */
static sysset_t *
#ifdef DYNAMIC_SYSCALLS
/* Function: load_syscalls
-
+
Extract syscall numbers and names from /proc/<pid>/sysent. Initialize
pi->num_syscalls with the number of syscalls and pi->syscall_names
with the names. (Certain numbers may be skipped in which case the
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);
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
strncpy (pi->syscall_names[callnum], namebuf, size-1);
pi->syscall_names[callnum][size-1] = '\0';
}
-
+
close (sysent_fd);
xfree (syscalls);
}
/* Function: free_syscalls
-
+
Free the space allocated for the syscall names from the procinfo
structure. */
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)
{
/*
* This "module" is the interface layer between the /proc system API
- * and the gdb target vector functions. This layer consists of
+ * 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.
*
pi->status_valid = 0; /* fail */
else
{
- /* Sigh... I have to read a different data structure,
+ /* 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));
(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,
+ pi->status_valid = (read (pi->status_fd,
(char *) &pi->prstatus,
sizeof (gdb_prstatus_t))
== sizeof (gdb_prstatus_t));
if (pi->tid == 0) /* main process */
{
/* Just read the danged status. Now isn't that simple? */
- pi->status_valid =
+ pi->status_valid =
(ioctl (pi->status_fd, PIOCSTATUS, &pi->prstatus) >= 0);
}
else
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;
}
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 */
pi->gregs_valid = pi->status_valid;
#ifdef NEW_PROC_API
- /* In the read/write multiple-fd model,
+ /* 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
* Function: proc_flags
*
* returns the process flags (pr_flags field).
- */
+ */
long
proc_flags (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
if (!pi->status_valid)
if (!proc_get_status (pi))
return NULL;
-
+
#ifdef NEW_PROC_API
return (long *) &pi->prstatus.pr_lwp.pr_sysarg;
#else
if (!pi->status_valid)
if (!proc_get_status (pi))
return 0;
-
+
#ifdef NEW_PROC_API
return pi->prstatus.pr_lwp.pr_syscall;
#else
}
/*
- * Function: proc_modify_flag
+ * Function: proc_modify_flag
*
- * === I appologize for the messiness of this function.
+ * === I appologize for the messiness of this function.
* === This is an area where the different versions of
* === /proc are more inconsistent than usual. MVS
*
* Note: OSF does not define PR_KLC.
* Note: OSF is the only one that can ONLY use the oldest method.
*
- * Arguments:
+ * Arguments:
* pi -- the procinfo
* flag -- one of PR_FORK, PR_RLC, or PR_ASYNC
* mode -- 1 for set, 0 for reset.
{
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
+ /* 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
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
* Function: proc_unset_kill_on_last_close
*
* Reset the kill_on_last_close flag.
- * Process will NOT be killed when debugger
+ * Process will NOT be killed when debugger
* closes its file handles (or exits or dies).
*
* Returns non-zero for success, zero for failure.
* Function: proc_set_async
*
* Set PR_ASYNC flag.
- * If one LWP stops because of a debug event (signal etc.),
+ * 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.
* Function: proc_stop_process
*
* Request the process/LWP to stop. Does not wait.
- * Returns non-zero for success, zero for failure.
+ * Returns non-zero for success, zero for failure.
*/
int
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
* 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.
+ * Returns non-zero for success, zero for failure.
*/
int
/*
* 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
+ * 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);
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
* 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.
+ * Returns non-zero for success, zero for failure.
*/
int
* 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)
{
* Function: proc_set_traced_signals
*
* Register to trace signals in the process or LWP.
- * Returns non-zero for success, zero for failure.
+ * Returns non-zero for success, zero for failure.
*/
int
/*
* 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
+ * 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);
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.
+ * Returns non-zero for success, zero for failure.
*/
int
/*
* 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
+ * 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);
* 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.
+ * Returns non-zero for success, zero for failure.
*/
int
/*
* 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
+ * 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);
#endif
/* 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.
+ * Returns non-zero for success, zero for failure.
*/
int
/*
* 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
+ * 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);
* 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.
+ * Returns non-zero for success, zero for failure.
*/
int
/*
* 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
+ * 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);
/*
* 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
+ * 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);
/*
* 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
+ * 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);
/*
* 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
+ * 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);
/*
* 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
+ * 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);
/*
* 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
+ * 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);
/*
* 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
+ * 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);
/*
* 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
+ * 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);
/*
* 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
+ * 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);
/*
* 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
+ * 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);
/*
* 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
+ * 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);
/*
* 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
+ * 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.
+ * it messes up the current signal. Work around the kernel bug.
*/
if (signo > 0 &&
signo == proc_cursig (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
+ * 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);
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)
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)
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;
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)
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;
}
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
#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)
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;
}
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
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;
}
/*
* 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
+ * 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);
void *ptr;
gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr));
- ADDRESS_TO_POINTER (builtin_type_void_data_ptr, &ptr, addr);
+ gdbarch_address_to_pointer (current_gdbarch, builtin_type_void_data_ptr,
+ &ptr, addr);
return ptr;
}
int
proc_set_watchpoint (procinfo *pi, CORE_ADDR addr, int len, int wflags)
{
-#if !defined (TARGET_HAS_HARDWARE_WATCHPOINTS)
+#if !defined (TARGET_HAS_HARDWARE_WATCHPOINTS)
return 0;
#else
/* Horrible hack! Detect Solaris 2.5, because this doesn't work on 2.5 */
/* 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)
{
since there is a different way to do threads on every OS. */
/*
- * Function: proc_get_nthreads
+ * Function: proc_get_nthreads
*
- * Return the number of threads for the process
+ * Return the number of threads for the process
*/
#if defined (PIOCNTHR) && defined (PIOCTLIST)
/*
* OSF version
*/
-int
+int
proc_get_nthreads (procinfo *pi)
{
int nthreads = 0;
return 0;
/*
- * NEW_PROC_API: only works for the 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
+#ifdef NEW_PROC_API
if (pi->tid != 0) /* find the parent process procinfo */
pi = find_procinfo_or_die (pi->pid, 0);
#endif
/*
* 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,
+ * 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);
/*
* OSF version
*/
-int
+int
proc_get_current_thread (procinfo *pi)
{
#if 0 /* FIXME: not ready for prime time? */
/*
* Default version
*/
-int
+int
proc_get_current_thread (procinfo *pi)
{
return 0;
#endif
/*
- * Function: proc_update_threads
+ * 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).
/*
* 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
+ * 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);
/*
* 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
+ * 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);
/*
* Unixware
*
- * Note: this brute-force method is the only way I know of
- * to accomplish this task on Unixware. This method will
+ * 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... ;-)
/*
* OSF version
*/
-int
+int
proc_update_threads (procinfo *pi)
{
int nthreads, 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
+ * 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);
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__);
* 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.
- *
+ * a quick pass over the currently-known procinfos.
+ *
* Arguments:
* pi - parent process procinfo
* func - per-thread function
/*
* 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
+ * 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);
static ptid_t do_attach (ptid_t ptid);
static void do_detach (int signo);
static int register_gdb_signals (procinfo *, gdb_sigset_t *);
+static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum,
+ int entry_or_exit, int mode, int from_tty);
+static int insert_dbx_link_breakpoint (procinfo *pi);
+static void remove_dbx_link_breakpoint (void);
+
+/* 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;
/*
* Function: procfs_debug_inferior
return 0;
}
-static void
+static void
procfs_attach (char *args, int from_tty)
{
char *exec_file;
int pid;
if (!args)
- error_no_arg ("process-id to attach");
+ error_no_arg (_("process-id to attach"));
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",
+ printf_filtered (_("Attaching to %s\n"),
target_pid_to_str (pid_to_ptid (pid)));
fflush (stdout);
push_target (&procfs_ops);
}
-static void
+static void
procfs_detach (char *args, int from_tty)
{
- char *exec_file;
- int signo = 0;
+ int sig = 0;
+
+ if (args)
+ sig = atoi (args);
if (from_tty)
{
+ int pid = PIDGET (inferior_ptid);
+ 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 */
+ unpush_target (&procfs_ops);
}
static ptid_t
int fail;
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);
}
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);
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))
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.
+
+ ??? 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.
+
+ 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. */
static void
-procfs_fetch_registers (int regno)
+procfs_fetch_registers (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);
+ gdb_gregset_t *gregs;
+ procinfo *pi;
+ int pid = PIDGET (inferior_ptid);
+ int tid = TIDGET (inferior_ptid);
- /* First look up procinfo for the main process. */
- pi = find_procinfo_or_die (pid, 0);
+ /* First look up procinfo for the main process. */
+ pi = find_procinfo_or_die (pid, 0);
- /* If the event thread is not the same as GDB's requested thread
- (ie. inferior_ptid), then look up procinfo for the requested
+ /* 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)))
+ if (tid != 0 && tid != proc_get_current_thread (pi))
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 (current_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 (current_gdbarch))
+ || regnum == gdbarch_pc_regnum (current_gdbarch)
+ || regnum == gdbarch_sp_regnum (current_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);
}
}
from the program being debugged. */
static void
-procfs_prepare_to_store (void)
+procfs_prepare_to_store (struct regcache *regcache)
{
-#ifdef CHILD_PREPARE_TO_STORE
- CHILD_PREPARE_TO_STORE ();
-#endif
}
-/*
- * 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.
- */
+/* Store register REGNUM back into the inferior. If REGNUM is -1, do
+ this for all registers.
+
+ 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.
+
+ 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 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);
+ gdb_gregset_t *gregs;
+ procinfo *pi;
+ int pid = PIDGET (inferior_ptid);
+ int tid = TIDGET (inferior_ptid);
- /* If current lwp for process is not the same as requested thread
- (ie. inferior_ptid), then find procinfo for the requested thread. */
+ /* First find procinfo for main process. */
+ pi = find_procinfo_or_die (pid, 0);
- if ((tid != 0) &&
- (tid != proc_get_current_thread (pi)))
+ /* 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);
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 (current_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 (current_gdbarch))
+ || regnum == gdbarch_pc_regnum (current_gdbarch)
+ || regnum == gdbarch_sp_regnum (current_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__);
}
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",
+ 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? */
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);
case PR_SYSENTRY:
if (syscall_is_lwp_exit (pi, what))
{
- printf_filtered ("[%s exited]\n",
+ printf_filtered (_("[%s exited]\n"),
target_pid_to_str (retval));
delete_thread (retval);
status->kind = TARGET_WAITKIND_SPURIOUS;
{
/* 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)
{
- /* 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;
}
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
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]);
}
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))
{
/*
/* If not in GDB's thread list, add it. */
if (!in_thread_list (temp_ptid))
{
- printf_filtered ("[New %s]\n",
+ printf_filtered (_("[New %s]\n"),
target_pid_to_str (temp_ptid));
add_thread (temp_ptid);
}
}
else if (syscall_is_lwp_exit (pi, what))
{
- printf_filtered ("[%s exited]\n",
+ printf_filtered (_("[%s exited]\n"),
target_pid_to_str (retval));
delete_thread (retval);
status->kind = TARGET_WAITKIND_SPURIOUS;
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
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]);
}
}
#else
if (retry < 5)
{
- printf_filtered ("Retry #%d:\n", retry);
+ printf_filtered (_("Retry #%d:\n"), retry);
pi->status_valid = 0;
goto wait_again;
}
temp_ptid = MERGEPID (pi->pid, temp_tid);
if (!in_thread_list (temp_ptid))
{
- printf_filtered ("[New %s]\n",
+ printf_filtered (_("[New %s]\n"),
target_pid_to_str (temp_ptid));
add_thread (temp_ptid);
}
wstat = (what << 8) | 0177;
break;
case PR_FAULTED:
- switch (what) { /* FIXME: FAULTED_USE_SIGINFO */
+ switch (what) {
#ifdef FLTWATCH
case FLTWATCH:
wstat = (SIGTRAP << 8) | 0177;
#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 == read_pc ())
+ remove_dbx_link_breakpoint ();
+
wstat = (SIGTRAP << 8) | 0177;
break;
case FLTSTACK:
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;
}
/*
!in_thread_list (retval))
{
/*
- * We have a new thread.
+ * 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
+ * If we don't create a procinfo, resume may be unhappy
* later.
*/
- printf_filtered ("[New %s]\n", target_pid_to_str (retval));
+ printf_filtered (_("[New %s]\n"), target_pid_to_str (retval));
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
+ * 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),
+ if (find_procinfo (PIDGET (inferior_ptid),
TIDGET (inferior_ptid)) == NULL)
- create_procinfo (PIDGET (inferior_ptid),
+ create_procinfo (PIDGET (inferior_ptid),
TIDGET (inferior_ptid));
}
}
printf_filtered ("procfs:%d -- process not stopped.\n",
__LINE__);
proc_prettyprint_flags (flags, 1);
- error ("procfs: ...giving up...");
+ error (_("procfs: ...giving up..."));
}
}
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, void *readbuf,
+ const void *writebuf, ULONGEST offset, LONGEST len)
+{
+ switch (object)
+ {
+ case TARGET_OBJECT_MEMORY:
+ if (readbuf)
+ return (*ops->deprecated_xfer_memory) (offset, readbuf, len,
+ 0/*write*/, NULL, ops);
+ if (writebuf)
+ return (*ops->deprecated_xfer_memory) (offset, writebuf, len,
+ 1/*write*/, NULL, ops);
+ return -1;
+
+#ifdef NEW_PROC_API
+ case TARGET_OBJECT_AUXV:
+ return procfs_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.
* If there are "dirty" caches that need to be written back
* to the child process, do that.
*
- * File descriptors are also cached.
+ * 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
* descriptors we may have accumulated for the threads.
*
* Return value:
- * As this function is called by iterate_over_threads, it always
+ * As this function is called by iterate_over_threads, it always
* returns zero (so that iterate_over_threads will keep iterating).
*/
if (!proc_set_gregs (pi)) /* flush gregs cache */
proc_warn (pi, "target_resume, set_gregs",
__LINE__);
- if (FP0_REGNUM >= 0)
+ if (gdbarch_fp0_regnum (current_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);
* 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
+ * 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
+ * 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.
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
/* Running the process voids all cached registers and status. */
/* Void the threads' caches first */
- proc_iterate_over_threads (pi, invalidate_cache, NULL);
+ proc_iterate_over_threads (pi, invalidate_cache, NULL);
/* Void the process procinfo's caches. */
invalidate_cache (NULL, pi, NULL);
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
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
+ * 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.
*
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",
+ printf_filtered (_("\tUsing the running image of %s %s via /proc.\n"),
+ attach_flag? "attached": "child",
target_pid_to_str (inferior_ptid));
}
static void
procfs_open (char *args, int from_tty)
{
- error ("Use the \"run\" command to start a Unix child process.");
+ 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
+ * This tells GDB that this target vector can be invoked
* for "run" or "attach".
*/
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. */
return !procfs_suppress_run;
* 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,
+ * 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.
*/
/* 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
* Then we want GDB to forget all about it.
*/
-static void
+static void
procfs_kill_inferior (void)
{
if (!ptid_equal (inferior_ptid, null_ptid)) /* ? */
* Forget we ever debugged this thing!
*/
-static void
+static void
procfs_mourn_inferior (void)
{
procinfo *pi;
destroy_procinfo (pi);
}
unpush_target (&procfs_ops);
+
+ if (dbx_link_bpt != NULL)
+ {
+ deprecated_remove_raw_breakpoint (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,
+ * 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
+static void
procfs_init_inferior (int pid)
{
procinfo *pi;
the actual process ID plus the lwp ID. */
inferior_ptid = MERGEPID (pi->pid, proc_get_current_thread (pi));
-#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 */
+
+#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
}
/*
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)
{
if (!proc_unset_run_on_last_close (pi))
proc_warn (pi, "set_exec_trap, unset_RLC", __LINE__);
- /* FIXME: No need to destroy the procinfo --
+ /* 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,
+ * 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
*/
static void
-procfs_create_inferior (char *exec_file, char *allargs, char **env)
+procfs_create_inferior (char *exec_file, char *allargs, char **env,
+ int from_tty)
{
char *shell_file = getenv ("SHELL");
char *tryname;
/* 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,
+ fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
procfs_init_inferior, NULL, shell_file);
- /* We are at the first instruction we care about. */
- /* Pedal to the metal... */
-
- proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
+#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. */
+ proc_trace_syscalls_1 (find_procinfo_or_die (PIDGET (inferior_ptid), 0),
+ SYS_syssgi, PR_SYSEXIT, FLAG_RESET, 0);
+#endif
}
/*
/*
* Function: target_find_new_threads
*
- * Query all the threads that the target knows about,
+ * Query all the threads that the target knows about,
* and give them back to GDB to add to its list.
*/
proc_iterate_over_threads (pi, procfs_notice_thread, NULL);
}
-/*
+/*
* Function: target_thread_alive
*
* Return true if the thread is still '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)
{
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;
}
/*
* Insert a watchpoint
*/
-int
+int
procfs_set_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rwflag,
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 */
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. */
{
procinfo *pi;
- pi = find_procinfo_or_die (PIDGET (ptid) == -1 ?
+ pi = find_procinfo_or_die (PIDGET (ptid) == -1 ?
PIDGET (inferior_ptid) : PIDGET (ptid), 0);
if (!pi) /* If no process, then not stopped by watchpoint! */
if (proc_flags (pi) & (PR_STOPPED | PR_ISTOP))
{
if (proc_why (pi) == PR_FAULTED)
- {
+ {
#ifdef FLTWATCH
if (proc_what (pi) == FLTWATCH)
return 1;
#ifdef TM_I386SOL2_H
/*
- * Function: procfs_find_LDT_entry
+ * Function: procfs_find_LDT_entry
*
* Input:
* ptid_t ptid; // The GDB-style pid-plus-LWP.
/* 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:%d.",
+ warning (_("procfs_find_LDT_entry: could not find procinfo for %d:%d."),
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:%d.",
+ warning (_("procfs_find_LDT_entry: could not read gregs for %d:%d."),
PIDGET (ptid), TIDGET (ptid));
return NULL;
}
* Memory Mappings Functions:
*/
-/*
+/*
* Function: iterate_over_mappings
*
* Call a callback function once for each mapping, passing it the mapping,
* child_func -- optional secondary function pointer to be passed
* to the child function.
*
- * Return: First non-zero return value from the callback function,
+ * Return: 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, int (*child_func) (), void *data,
+ int (*func) (struct prmap *map,
+ int (*child_func) (),
void *data))
{
char pathname[MAX_PROC_NAME_SIZE];
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. */
/* 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__);
/*
* 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
+ * 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.
*
* or zero.
*/
-int solib_mappings_callback (struct prmap *map,
+int solib_mappings_callback (struct prmap *map,
int (*func) (int, CORE_ADDR),
void *data)
{
/* 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
+ 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
+ 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
* 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
+ * 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
* 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,
+ * int callback (CORE_ADDR vaddr,
+ * unsigned long size,
+ * int read, int write, int execute,
* void *data);
*
* 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,
+find_memory_regions_callback (struct prmap *map,
+ int (*func) (CORE_ADDR,
+ unsigned long,
+ int, int, int,
void *),
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);
}
* 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,
+ * 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 *),
+proc_find_memory_regions (int (*func) (CORE_ADDR,
+ unsigned long,
+ int, int, int,
+ void *),
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);
}
+/* Remove the breakpoint that we inserted in __dbx_link().
+ Does nothing if the breakpoint hasn't been inserted or has already
+ been removed. */
+
+static void
+remove_dbx_link_breakpoint (void)
+{
+ if (dbx_link_bpt_addr == 0)
+ return;
+
+ if (deprecated_remove_raw_breakpoint (dbx_link_bpt) != 0)
+ warning (_("Unable to remove __dbx_link breakpoint."));
+
+ dbx_link_bpt_addr = 0;
+ dbx_link_bpt = NULL;
+}
+
+/* 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 (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;
+}
+
+/* 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,
+ int (*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);
+}
+
/*
* Function: mappingflags
*
{
char *data_fmt_string;
- if (TARGET_ADDR_BIT == 32)
+ if (gdbarch_addr_bit (current_gdbarch) == 32)
data_fmt_string = "\t%#10lx %#10lx %#10x %#10x %7s\n";
else
data_fmt_string = " %#18lx %#18lx %#10x %#10x %7s\n";
- printf_filtered (data_fmt_string,
+ 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,
+ (unsigned int) map->pr_offset,
#else
map->pr_off,
#endif
{
char *header_fmt_string;
- if (TARGET_PTR_BIT == 32)
+ if (gdbarch_ptr_bit (current_gdbarch) == 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,
+ printf_filtered (_("Mapped address spaces:\n\n"));
+ printf_filtered (header_fmt_string,
"Start Addr",
" End Addr",
" Size",
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.
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);
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);
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__);
-
- if (mode == FLAG_SET)
- gdb_praddsysset (sysset, syscallnum);
- else
- gdb_prdelsysset (sysset, syscallnum);
+ const int syscallnum = atoi (args);
- 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);
{
init_procfs_ops ();
add_target (&procfs_ops);
- add_info ("proc", info_proc_cmd,
- "Show /proc process information about any running process.\n\
+ 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" =================== */
/* gcore only implemented on solaris and unixware (so far) */
static char *
-procfs_do_thread_registers (bfd *obfd, ptid_t ptid,
+procfs_do_thread_registers (bfd *obfd, ptid_t ptid,
char *note_data, int *note_size)
{
+ struct regcache *regcache = get_thread_regcache (ptid);
gdb_gregset_t gregs;
gdb_fpregset_t fpregs;
unsigned long merged_pid;
merged_pid = TIDGET (ptid) << 16 | PIDGET (ptid);
- fill_gregset (&gregs, -1);
+ fill_gregset (regcache, &gregs, -1);
#if defined (UNIXWARE)
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,
{
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_data = procfs_do_thread_registers (args->obfd, inferior_ptid,
+ args->note_data,
args->note_size);
inferior_ptid = saved_ptid;
}
char *note_data = NULL;
char *inf_args;
struct procfs_corefile_thread_data thread_args;
+ char *auxv;
+ int auxv_len;
if (get_exec_file (0))
{
strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname));
- strncpy (psargs, get_exec_file (0),
+ 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);
#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
{
/* 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 = procfs_do_thread_registers (obfd, inferior_ptid,
note_data, note_size);
}
else
note_data = thread_args.note_data;
}
+ auxv_len = target_read_alloc (¤t_target, TARGET_OBJECT_AUXV,
+ NULL, &auxv);
+ if (auxv_len > 0)
+ {
+ note_data = elfcore_write_note (obfd, note_data, note_size,
+ "CORE", NT_AUXV, auxv, auxv_len);
+ xfree (auxv);
+ }
+
make_cleanup (xfree, note_data);
return note_data;
}
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 */